layer.h
Go to the documentation of this file.
1 #ifndef H_CANOPEN_LAYER
2 #define H_CANOPEN_LAYER
3 
4 #include <vector>
5 #include <memory>
6 #include <boost/thread/shared_mutex.hpp>
7 #include <atomic>
8 #include <boost/exception/diagnostic_information.hpp>
9 
10 namespace canopen{
11 
13  mutable boost::mutex write_mutex_;
14  enum State{
15  OK = 0, WARN = 1, ERROR= 2, STALE = 3, UNBOUNDED = 3
16  };
17  std::atomic<State> state;
18  std::string reason_;
19 
20  virtual void set(const State &s, const std::string &r){
21  boost::mutex::scoped_lock lock(write_mutex_);
22  if(s > state) state = s;
23  if(!r.empty()){
24  if(reason_.empty()) reason_ = r;
25  else reason_ += "; " + r;
26  }
27  }
28 public:
29  struct Ok { static const State state = OK; private: Ok();};
30  struct Warn { static const State state = WARN; private: Warn(); };
31  struct Error { static const State state = ERROR; private: Error(); };
32  struct Stale { static const State state = STALE; private: Stale(); };
33  struct Unbounded { static const State state = UNBOUNDED; private: Unbounded(); };
34 
35  template<typename T> bool bounded() const{ return state <= T::state; }
36  template<typename T> bool equals() const{ return state == T::state; }
37 
38  LayerStatus() : state(OK) {}
39 
40  int get() const { return state; }
41 
42  const std::string reason() const { boost::mutex::scoped_lock lock(write_mutex_); return reason_; }
43 
44  const void warn(const std::string & r) { set(WARN, r); }
45  const void error(const std::string & r) { set(ERROR, r); }
46  const void stale(const std::string & r) { set(STALE, r); }
47 };
48 class LayerReport : public LayerStatus {
49  std::vector<std::pair<std::string, std::string> > values_;
50 public:
51  const std::vector<std::pair<std::string, std::string> > &values() const { return values_; }
52  template<typename T> void add(const std::string &key, const T &value) {
53  std::stringstream str;
54  str << value;
55  values_.push_back(std::make_pair(key,str.str()));
56  }
57 };
58 
59 #define CATCH_LAYER_HANDLER_EXCEPTIONS(command, status) \
60  try{ command; } \
61  catch(std::exception &e) {status.error(boost::diagnostic_information(e)); }
62 
63 class Layer{
64 public:
65  enum LayerState{
66  Off,
72  Ready
73  };
74 
75  const std::string name;
76 
77  void read(LayerStatus &status) {
78  if(state > Off) CATCH_LAYER_HANDLER_EXCEPTIONS(handleRead(status, state), status);
79  }
80  void write(LayerStatus &status) {
81  if(state > Off) CATCH_LAYER_HANDLER_EXCEPTIONS(handleWrite(status, state), status);
82  }
83  void diag(LayerReport &report) {
84  if(state > Shutdown) CATCH_LAYER_HANDLER_EXCEPTIONS(handleDiag(report), report);
85  }
86  void init(LayerStatus &status) {
87  if(state == Off){
88  if(status.bounded<LayerStatus::Warn>()){
89  state = Init;
90  CATCH_LAYER_HANDLER_EXCEPTIONS(handleInit(status), status);
91  }
92  if(!status.bounded<LayerStatus::Warn>()) shutdown(status);
93  else state = Ready;
94  }
95  }
96  void shutdown(LayerStatus &status) {
97  if(state != Off){
98  state = Shutdown;
99  CATCH_LAYER_HANDLER_EXCEPTIONS(handleShutdown(status), status);
100  state = Off;
101  }
102  }
103  void halt(LayerStatus &status) {
104  if(state > Halt){
105  state = Halt;
106  CATCH_LAYER_HANDLER_EXCEPTIONS(handleHalt(status), status);
107  state = Error;
108  }
109  }
110  void recover(LayerStatus &status) {
111  if(state == Error){
112  if(status.bounded<LayerStatus::Warn>()){
113  state = Recover;
114  CATCH_LAYER_HANDLER_EXCEPTIONS(handleRecover(status), status);
115  }
116  if(!status.bounded<LayerStatus::Warn>()){
117  halt(status);
118  }else{
119  state = Ready;
120  }
121  }
122 
123  }
124 
126 
127  Layer(const std::string &n) : name(n), state(Off) {}
128 
129  virtual ~Layer() {}
130 
131 protected:
132  virtual void handleRead(LayerStatus &status, const LayerState &current_state) = 0;
133  virtual void handleWrite(LayerStatus &status, const LayerState &current_state) = 0;
134 
135  virtual void handleDiag(LayerReport &report) = 0;
136 
137  virtual void handleInit(LayerStatus &status) = 0;
138  virtual void handleShutdown(LayerStatus &status) = 0;
139 
140  virtual void handleHalt(LayerStatus &status) = 0;
141  virtual void handleRecover(LayerStatus &status) = 0;
142 
143 private:
144  std::atomic<LayerState> state;
145 
146 };
147 
148 template<typename T> class VectorHelper{
149 public:
150  typedef std::shared_ptr<T> VectorMemberSharedPtr;
151 protected:
152  typedef std::vector<VectorMemberSharedPtr> vector_type ;
153  template<typename Bound, typename Data, typename FuncType> typename vector_type::iterator call(FuncType func, Data &status){
154  boost::shared_lock<boost::shared_mutex> lock(mutex);
155  return call<Bound>(func, status, layers.begin(), layers.end());
156  }
157  template<typename Data, typename FuncType> typename vector_type::iterator call(FuncType func, Data &status){
158  boost::shared_lock<boost::shared_mutex> lock(mutex);
159  return call<LayerStatus::Unbounded>(func, status, layers.begin(), layers.end());
160  }
161  template<typename Bound, typename Data, typename FuncType> typename vector_type::reverse_iterator call_rev(FuncType func, Data &status){
162  boost::shared_lock<boost::shared_mutex> lock(mutex);
163  return call<Bound>(func, status, layers.rbegin(), layers.rend());
164  }
165  template<typename Data, typename FuncType> typename vector_type::reverse_iterator call_rev(FuncType func, Data &status){
166  boost::shared_lock<boost::shared_mutex> lock(mutex);
167  return call<LayerStatus::Unbounded>(func, status, layers.rbegin(), layers.rend());
168  }
169  void destroy() { boost::unique_lock<boost::shared_mutex> lock(mutex); layers.clear(); }
170 
171 public:
172  virtual void add(const VectorMemberSharedPtr &l) { boost::unique_lock<boost::shared_mutex> lock(mutex); layers.push_back(l); }
173 
174  template<typename Bound, typename Data, typename FuncType> bool callFunc(FuncType func, Data &status){
175  boost::shared_lock<boost::shared_mutex> lock(mutex);
176  return call<Bound>(func, status, layers.begin(), layers.end()) == layers.end();
177  }
178 private:
179  vector_type layers;
180  boost::shared_mutex mutex;
181 
182  template<typename Bound, typename Iterator, typename Data, typename FuncType> Iterator call(FuncType func, Data &status, const Iterator &begin, const Iterator &end){
183  bool okay_on_start = status.template bounded<Bound>();
184 
185  for(Iterator it = begin; it != end; ++it){
186  ((**it).*func)(status);
187  if(okay_on_start && !status.template bounded<Bound>()){
188  return it;
189  }
190  }
191  return end;
192  }
193  template<typename Iterator, typename Data, typename FuncType> Iterator call(FuncType func, Data &status, const Iterator &begin, const Iterator &end){
194  return call<LayerStatus::Unbounded, Iterator, Data>(func, status, begin, end);
195  }
196 };
197 
198 template<typename T=Layer> class LayerGroup : public Layer, public VectorHelper<T> {
199 protected:
200  template<typename Data, typename FuncType, typename FailType> void call_or_fail(FuncType func, FailType fail, Data &status){
201  this->template call(func, status);
202  if(!status.template bounded<LayerStatus::Warn>()){
203  this->template call(fail, status);
204  (this->*fail)(status);
205  }
206  }
207  template<typename Data, typename FuncType, typename FailType> void call_or_fail_rev(FuncType func, FailType fail, Data &status){
208  this->template call_rev(func, status);
209  if(!status.template bounded<LayerStatus::Warn>()){
210  this->template call_rev(fail, status);
211  (this->*fail)(status);
212  }
213  }
214 
215  virtual void handleRead(LayerStatus &status, const LayerState &current_state) {
216  this->template call_or_fail(&Layer::read, &Layer::halt, status);
217  }
218  virtual void handleWrite(LayerStatus &status, const LayerState &current_state) {
219  this->template call_or_fail(&Layer::write, &Layer::halt, status);
220  }
221 
222  virtual void handleDiag(LayerReport &report) { this->template call(&Layer::diag, report); }
223 
224  virtual void handleInit(LayerStatus &status) { this->template call<LayerStatus::Warn>(&Layer::init, status); }
225  virtual void handleShutdown(LayerStatus &status) { this->template call(&Layer::shutdown, status); }
226 
227  virtual void handleHalt(LayerStatus &status) { this->template call(&Layer::halt, status); }
228  virtual void handleRecover(LayerStatus &status) { this->template call<LayerStatus::Warn>(&Layer::recover, status); }
229 public:
230  LayerGroup(const std::string &n) : Layer(n) {}
231 };
232 
233 class LayerStack : public LayerGroup<>{
234 
235 protected:
236  virtual void handleWrite(LayerStatus &status, const LayerState &current_state) { call_or_fail_rev(&Layer::write, &Layer::halt, status);}
237  virtual void handleShutdown(LayerStatus &status) { call_rev(&Layer::shutdown, status); }
238 public:
239  LayerStack(const std::string &n) : LayerGroup(n) {}
240 };
241 
242 template<typename T> class LayerGroupNoDiag : public LayerGroup<T>{
243 public:
244  LayerGroupNoDiag(const std::string &n) : LayerGroup<T>(n) {}
245  virtual void handleDiag(LayerReport &report) {}
246 };
247 
248 template<typename T> class DiagGroup : public VectorHelper<T>{
250 public:
251  virtual void diag(LayerReport &report){
252  this->template call(&Layer::diag, report);
253  }
254 };
255 
256 
257 
258 } // namespace canopen
259 
260 #endif
virtual void add(const VectorMemberSharedPtr &l)
Definition: layer.h:172
Iterator call(FuncType func, Data &status, const Iterator &begin, const Iterator &end)
Definition: layer.h:193
void init(LayerStatus &status)
Definition: layer.h:86
vector_type::reverse_iterator call_rev(FuncType func, Data &status)
Definition: layer.h:161
virtual void handleWrite(LayerStatus &status, const LayerState &current_state)
Definition: layer.h:218
boost::shared_mutex mutex
Definition: layer.h:180
VectorHelper< T > V
Definition: layer.h:249
const std::string reason() const
Definition: layer.h:42
LayerGroupNoDiag(const std::string &n)
Definition: layer.h:244
Iterator call(FuncType func, Data &status, const Iterator &begin, const Iterator &end)
Definition: layer.h:182
void shutdown(LayerStatus &status)
Definition: layer.h:96
virtual void diag(LayerReport &report)
Definition: layer.h:251
void read(LayerStatus &status)
Definition: layer.h:77
std::vector< std::pair< std::string, std::string > > values_
Definition: layer.h:49
const void warn(const std::string &r)
Definition: layer.h:44
vector_type::iterator call(FuncType func, Data &status)
Definition: layer.h:157
std::atomic< State > state
Definition: layer.h:17
std::string reason_
Definition: layer.h:18
void recover(LayerStatus &status)
Definition: layer.h:110
virtual void handleHalt(LayerStatus &status)
Definition: layer.h:227
std::atomic< LayerState > state
Definition: layer.h:144
virtual void handleInit(LayerStatus &status)
Definition: layer.h:224
virtual void handleRecover(LayerStatus &status)
Definition: layer.h:228
void halt(LayerStatus &status)
Definition: layer.h:103
const std::vector< std::pair< std::string, std::string > > & values() const
Definition: layer.h:51
LayerGroup(const std::string &n)
Definition: layer.h:230
LayerStack(const std::string &n)
Definition: layer.h:239
bool equals() const
Definition: layer.h:36
void call_or_fail(FuncType func, FailType fail, Data &status)
Definition: layer.h:200
virtual void handleRead(LayerStatus &status, const LayerState &current_state)
Definition: layer.h:215
bool callFunc(FuncType func, Data &status)
Definition: layer.h:174
LayerState getLayerState()
Definition: layer.h:125
bool bounded() const
Definition: layer.h:35
void call_or_fail_rev(FuncType func, FailType fail, Data &status)
Definition: layer.h:207
std::shared_ptr< T > VectorMemberSharedPtr
Definition: layer.h:150
const std::string name
Definition: layer.h:75
virtual ~Layer()
Definition: layer.h:129
static const State state
Definition: layer.h:29
vector_type layers
Definition: layer.h:179
#define CATCH_LAYER_HANDLER_EXCEPTIONS(command, status)
Definition: layer.h:59
virtual void handleDiag(LayerReport &report)
Definition: layer.h:222
std::vector< VectorMemberSharedPtr > vector_type
Definition: layer.h:152
vector_type::iterator call(FuncType func, Data &status)
Definition: layer.h:153
void add(const std::string &key, const T &value)
Definition: layer.h:52
void write(LayerStatus &status)
Definition: layer.h:80
void diag(LayerReport &report)
Definition: layer.h:83
const void error(const std::string &r)
Definition: layer.h:45
vector_type::reverse_iterator call_rev(FuncType func, Data &status)
Definition: layer.h:165
virtual void handleWrite(LayerStatus &status, const LayerState &current_state)
Definition: layer.h:236
const void stale(const std::string &r)
Definition: layer.h:46
virtual void handleShutdown(LayerStatus &status)
Definition: layer.h:225
Layer(const std::string &n)
Definition: layer.h:127
virtual void handleDiag(LayerReport &report)
Definition: layer.h:245
virtual void handleShutdown(LayerStatus &status)
Definition: layer.h:237
boost::mutex write_mutex_
Definition: layer.h:13


canopen_master
Author(s): Mathias Lüdtke
autogenerated on Mon Feb 28 2022 23:28:03