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