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


canopen_master
Author(s): Mathias Lüdtke
autogenerated on Sat May 4 2019 02:40:43