sigslot.hpp
Go to the documentation of this file.
1 
10 /*****************************************************************************
11 ** Ifdefs
12 *****************************************************************************/
13 
14 #ifndef ECL_SIGSLOTS_SIGSLOT_HPP_
15 #define ECL_SIGSLOTS_SIGSLOT_HPP_
16 
17 /*****************************************************************************
18 ** Includes
19 *****************************************************************************/
20 
21 #include <map>
22 #include <set>
23 #include <string>
24 #include <ecl/config/macros.hpp>
25 #include <ecl/threads/mutex.hpp>
26 #include <ecl/utilities/function_objects.hpp>
27 #include <ecl/utilities/void.hpp>
28 #include "manager.hpp"
29 
30 /*****************************************************************************
31 ** Namespaces
32 *****************************************************************************/
33 
34 namespace ecl {
35 
36 /*****************************************************************************
37 ** Interface [General]
38 *****************************************************************************/
45 template <typename Data=Void>
46 class SigSlot {
47 public:
48  /*********************
49  ** Typedefs
50  **********************/
51  typedef typename Topic<Data>::Subscribers Subscribers;
52  typedef typename std::map<std::string, const Subscribers*> PublicationMap;
54  /*********************
55  ** C&D
56  **********************/
62  function = new PartiallyBoundUnaryMemberFunction< SigSlot<Data> ,Data,void >( &SigSlot<Data>::emit, *this);
63  }
69  SigSlot(void (*f)(Data)) : processing_count(0), number_of_handles(1) {
70  function = new UnaryFreeFunction<Data>(f);
71  }
79  template<typename C>
80  SigSlot(void (C::*f)(Data), C &c) : processing_count(0), number_of_handles(1) {
81  function = new PartiallyBoundUnaryMemberFunction<C,Data,void>(f,c);
82  }
83 
91  ~SigSlot() {
92  disconnect(); // stop any new processing from connected signals
93  mutex.lock(); // acts like a barrier - holds up here if function still processing stuff.
94  delete function;
95  }
96 
97  const unsigned int& handles() const { return number_of_handles; }
98  void incrHandles() { ++number_of_handles; }
99  void decrHandles() { --number_of_handles; }
106  void emit(Data data) {
107  typename PublicationMap::const_iterator topic_iter;
108  typename Subscribers::const_iterator slots_iter;
109  for ( topic_iter = publications.begin(); topic_iter != publications.end(); ++topic_iter ) {
110  const Subscribers* subscribers = topic_iter->second;
111  for ( slots_iter = subscribers->begin(); slots_iter != subscribers->end(); ++slots_iter ) {
112  SigSlot<Data> *sigslot = *slots_iter;
113  sigslot->process(data);
114  }
115  }
116  }
123  void process(Data data) {
124  mutex.trylock(); // Only lock if its not already locked.
126  (*function)(data);
127  if ( --processing_count == 0 ) {
128  mutex.unlock();
129  }
130  }
138  void connectSignal(const std::string& topic) {
139  // Logic:
140  // - if already publishing to this topic
141  // - don't do anything
142  // - else
143  // - if topic doesn't exist
144  // - Manager will automatically create a new topic
145  // - Manager returns the subscribers handle
146  // - Topic name and subscribers handle are stored locally here in publications
147  publications.insert( std::pair<std::string, const Subscribers*>(topic, SigSlotsManager<Data>::connectSignal(topic,this)) );
148  }
156  void connectSlot(const std::string& topic) {
157  std::pair< std::set<std::string>::iterator,bool > ret;
158  // std::cout << "Topic: " << topic << std::endl;
159  ret = subscriptions.insert(topic); // Doesn't matter if it already exists.
160  if ( ret.second ) {
162  } // else { already subscribed to this topic }
163  }
167  void disconnect(const std::string &topic) {
168  std::set<std::string>::const_iterator listen_iter = subscriptions.find(topic);
169  publications.erase(topic); // Doesn't matter if it finds it or not.
171  }
177  void disconnect() {
178  std::set<std::string>::iterator iter;
179  for ( iter = subscriptions.begin(); iter != subscriptions.end(); ++iter ) {
181  }
182  subscriptions.clear();
183  typename std::map<std::string,const Subscribers*>::iterator emit_iter;
184  for ( emit_iter = publications.begin(); emit_iter != publications.end(); ++emit_iter ) {
185  SigSlotsManager<Data>::disconnect(emit_iter->first, this);
186  }
187  publications.clear();
188  }
189 
190  const std::set<std::string>& subscribedTopics() { return subscriptions; }
191 
192 private:
193  Mutex mutex;
194  unsigned int processing_count; // number of running process()'
195  unsigned int number_of_handles; // number of handles to this sigslot (allows copying)
196  std::set<std::string> subscriptions; // topics this sigslot is listening to
197  PublicationMap publications; // topics this sigslot is posting to, as well as the subscribers on the other end
198 
199  UnaryFunction<Data,void> *function;
200 };
201 
202 /*****************************************************************************
203 ** Interface [Void]
204 *****************************************************************************/
205 
213 template<>
214 class SigSlot<Void> {
215 public:
216  // typedef std::set<SigSlot<Void>*> Subscribers
218  typedef std::map<std::string, const Subscribers*> PublicationMap;
225  function = new BoundNullaryMemberFunction<SigSlot,void>(&SigSlot::emit,*this);
226  }
233  function = new NullaryFreeFunction<void>(f);
234  }
242  template<typename C>
243  SigSlot(void (C::*f)(void), C &c) : processing_count(0), number_of_handles(1) {
244  function = new BoundNullaryMemberFunction<C,void>(f,c);
245  }
246 
254  ~SigSlot() {
255  disconnect(); // stop any new processing from connected signals
256  mutex.lock(); // acts like a barrier - holds up here if function still processing stuff.
257  delete function;
258  }
259 
260  const unsigned int& handles() const { return number_of_handles; }
261  void incrHandles() { ++number_of_handles; }
262  void decrHandles() { --number_of_handles; }
269  void emit() {
270  PublicationMap::const_iterator topic_iter;
271  Subscribers::const_iterator slots_iter;
272  for ( topic_iter = publications.begin(); topic_iter != publications.end(); ++topic_iter ) {
273  const Subscribers* subscribers = topic_iter->second;
274  for ( slots_iter = subscribers->begin(); slots_iter != subscribers->end(); ++slots_iter ) {
275  SigSlot *sigslot = *slots_iter;
276  sigslot->process();
277  }
278  }
279  }
286  void process(Void void_arg = Void()) {
287  mutex.trylock(); // Only lock if its not already locked.
289  (*function)();
290  if ( --processing_count == 0 ) {
291  mutex.unlock();
292  }
293  }
301  void connectSignal(const std::string& topic) {
302  // Logic:
303  // - if already publishing to this topic
304  // - don't do anything
305  // - else
306  // - if topic doesn't exist
307  // - Manager will automatically create a new topic
308  // - Manager returns the subscribers handle
309  // - Topic name and subscribers handle are stored locally here in publications
310  publications.insert( std::pair<std::string, const Subscribers*>(topic, SigSlotsManager<Void>::connectSignal(topic,this)) );
311  }
315  void connectSlot(const std::string& topic){
316  std::pair< std::set<std::string>::iterator,bool > ret;
317  ret = subscriptions.insert(topic); // Doesn't matter if it already exists.
318  if ( ret.second ) {
320  } // else { already subscribed to this topic }
321  }
329  void disconnect(const std::string &topic) {
330  std::set<std::string>::const_iterator listen_iter = subscriptions.find(topic);
331  publications.erase(topic); // Doesn't matter if it finds it or not.
333  }
339  void disconnect() {
340  std::set<std::string>::iterator iter;
341  for ( iter = subscriptions.begin(); iter != subscriptions.end(); ++iter ) {
343  }
344  subscriptions.clear();
345  std::map<std::string,const Subscribers*>::iterator emit_iter;
346  for ( emit_iter = publications.begin(); emit_iter != publications.end(); ++emit_iter ) {
347  SigSlotsManager<Void>::disconnect(emit_iter->first, this);
348  }
349  publications.clear();
350  }
351 
352 private:
353  Mutex mutex;
354  unsigned int processing_count; // number of running process()'
355  unsigned int number_of_handles; // number of handles to this sigslot (allows copying)
356  std::set<std::string> subscriptions; // topics this sigslot is listening to
357  PublicationMap publications; // topics this sigslot is posting to, as well as the subscribers on the other end
358 
359  NullaryFunction<void> *function;
360 };
361 
362 } // namespace ecl
363 
364 #endif /* ECL_SIGSLOTS_SIGSLOT_HPP_ */
static void connectSlot(const std::string &topic, SigSlot< Data > *sigslot)
Topic< Data >::Subscribers Subscribers
std::set< SigSlot< Data > * > Subscribers
void emit(Data data)
void connectSignal(const std::string &topic)
const std::set< std::string > & subscribedTopics()
void(* VoidFunction)()
unsigned int number_of_handles
Definition: sigslot.hpp:195
void decrHandles()
const unsigned int & handles() const
Mutex mutex
Definition: sigslot.hpp:193
void incrHandles()
PublicationMap publications
Definition: sigslot.hpp:197
static void disconnect(const std::string &topic, SigSlot< Data > *sigslot)
unsigned int processing_count
Definition: sigslot.hpp:194
std::map< std::string, const Subscribers * > PublicationMap
void f(int i) ecl_debug_throw_decl(StandardException)
std::set< std::string > subscriptions
Definition: sigslot.hpp:196
void disconnect()
static const Subscribers * connectSignal(const std::string &topic, SigSlot< Data > *sigslot)
void connectSlot(const std::string &topic)
void process(Data data)


xbot_driver
Author(s): Roc, wangpeng@droid.ac.cn
autogenerated on Sat Oct 10 2020 03:27:38