GetFEM  5.5
gmm_feedback_management.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2002-2026 Yves Renard
5 
6  This file is a part of GetFEM
7 
8  GetFEM is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program. If not, see https://www.gnu.org/licenses/.
19 
20  As a special exception, you may use this file as it is a part of a free
21  software library without restriction. Specifically, if other files
22  instantiate templates or use macros or inline functions from this file,
23  or you compile this file and link it with other files to produce an
24  executable, this file does not by itself cause the resulting executable
25  to be covered by the GNU Lesser General Public License. This exception
26  does not however invalidate any other reasons why the executable file
27  might be covered by the GNU Lesser General Public License.
28 
29 ===========================================================================*/
30 
31 /** @file gmm_feedback_management.h
32  @date July 03, 2017.
33  @brief Support for run time management of trace, warning and assert
34  feedback.
35 */
36 
37 #ifndef GMM_FEEDBACK_MANAGEMENT_H__
38 #define GMM_FEEDBACK_MANAGEMENT_H__
39 #include <iostream>
40 #include <string>
41 #include <memory>
42 
43 namespace gmm {
44 
45 /* *********************************************************************** */
46 /* GetFEM warnings. */
47 /* *********************************************************************** */
48 
49 // This allows to dynamically hide warnings
50 struct warning_level {
51  static int level(int l = -2)
52  { static int level_ = 3; return (l != -2) ? (level_ = l) : level_; }
53 };
54 
55 inline void set_warning_level(int l) { warning_level::level(l>0 ? l : 0); }
56 inline int get_warning_level(void) { return warning_level::level(-2); }
57 
58 /* *********************************************************************** */
59 /* GetFEM traces. */
60 /* *********************************************************************** */
61 
62 // This allows to dynamically hide traces
63 struct traces_level {
64  static int level(int l = -2)
65  { static int level_ = 3; return (l != -2) ? (level_ = l) : level_; }
66 };
67 
68 inline void set_traces_level(int l) { traces_level::level(l>0 ? l : 0); }
69 inline int get_traces_level(void) { return traces_level::level(); }
70 
71 
72 /* *********************************************************************** */
73 /* GetFEM feedback management */
74 /* *********************************************************************** */
75 
76 enum class FeedbackType {
77  TRACE = 0,
78  WARNING,
79  ASSERT
80 };
81 
82 // Abstract class providing feedback management interface.
83 // The interface consist of three functions:
84 // * for sending feedback message
85 // * for getting traces level
86 // * for getting warning level
87 // * for action to be done after feedback is handled
88 struct base_feedback_handler {
89  virtual ~base_feedback_handler() = default;
90  virtual void send(const std::string &message, FeedbackType messageType, size_t level) = 0;
91  virtual size_t traces_level() { return get_traces_level(); }
92  virtual size_t warning_level() { return get_warning_level(); }
93  virtual void terminating_action() = 0;
94 };
95 
96 
97 // Provides the default implementation of feedback handling.
98 struct default_feedback_handler final : public base_feedback_handler {
99  void send(const std::string &message, FeedbackType, size_t) override {
100  std::cerr << message << std::endl;
101  }
102  void terminating_action() override {
103  std::exit(1);
104  }
105 };
106 
107 // This class acts as a run-time dispatcher for sending feedback
108 // messages and getting trace and warning levels.
109 class feedback_manager {
110 public:
111  // Management actions
112  enum Action {
113  SET, // Sets the feedback handler, releasing the one previously set.
114  GET, // Returns currently managed handler (it is still managed).
115  REPLACE, // Replace manager with a new one, stop managing the old one
116  // and returns it unmanaged to the caller. The caller is
117  // then responsible for managing the memory of the handler.
118  };
119 
120  // Steals the pointer to a messenger object that provides
121  // feedback handling implementation.
122  //
123  // Example:
124  // feedback_manager::manage(new default_feedback_handler);
125  //
126  static base_feedback_handler* manage(enum Action action=GET, base_feedback_handler *pHandler=nullptr);
127  static void send(const std::string &message, FeedbackType type, size_t level);
128  static size_t traces_level();
129  static size_t warning_level();
130  // Action to be taken when feedback handling is done
131  static void terminating_action();
132 };
133 
134 // Depending on action either gets, sets or replaces feedback handler. Setting handler to null resets
135 // it to gmm::default_feedback_handler.
136 inline base_feedback_handler* feedback_manager::manage(enum Action action, base_feedback_handler *pHandler) {
137  static std::unique_ptr<base_feedback_handler>
138  pHandler_ = std::make_unique<default_feedback_handler>();
139  base_feedback_handler *rethandler = nullptr;
140  switch(action) {
141  case SET:
142  pHandler_.reset(pHandler != nullptr ? pHandler : new default_feedback_handler);
143  rethandler = pHandler_.get();
144  break;
145  case GET:
146  rethandler = pHandler_.get();
147  break;
148  case REPLACE:
149  rethandler = pHandler_.release();
150  pHandler_.reset(pHandler != nullptr ? pHandler : new default_feedback_handler);
151  break;
152  }
153  return rethandler;
154 }
155 
156 inline void feedback_manager::send(const std::string &message, FeedbackType type, size_t level) {
157  feedback_manager::manage()->send(message, type, level);
158 }
159 
160 inline void feedback_manager::terminating_action() {
161  feedback_manager::manage()->terminating_action();
162 }
163 
164 inline size_t feedback_manager::traces_level() {
165  return feedback_manager::manage()->traces_level();
166 }
167 
168 inline size_t feedback_manager::warning_level() {
169  return feedback_manager::manage()->warning_level();
170 }
171 
172 } // namespace gmm
173 #endif /* GMM_FEEDBACK_MANAGEMENT_H__ */