Go to the documentation of this file.00001
00010
00011
00012
00013
00014 #ifndef ECL_SIGSLOTS_SIGSLOT_HPP_
00015 #define ECL_SIGSLOTS_SIGSLOT_HPP_
00016
00017
00018
00019
00020
00021 #include <map>
00022 #include <set>
00023 #include <string>
00024 #include <ecl/config/macros.hpp>
00025 #include <ecl/threads/mutex.hpp>
00026 #include <ecl/utilities/function_objects.hpp>
00027 #include <ecl/utilities/void.hpp>
00028 #include "manager.hpp"
00029
00030
00031
00032
00033
00034 namespace ecl {
00035
00036
00037
00038
00045 template <typename Data=Void>
00046 class SigSlot {
00047 public:
00048
00049
00050
00051 typedef typename Topic<Data>::Subscribers Subscribers;
00052 typedef typename std::map<std::string, const Subscribers*> PublicationMap;
00054
00055
00056
00061 SigSlot() : processing_count(0), number_of_handles(1) {
00062 function = new PartiallyBoundUnaryMemberFunction< SigSlot<Data> ,Data,void >( &SigSlot<Data>::emit, *this);
00063 }
00069 SigSlot(void (*f)(Data)) : processing_count(0), number_of_handles(1) {
00070 function = new UnaryFreeFunction<Data>(f);
00071 }
00079 template<typename C>
00080 SigSlot(void (C::*f)(Data), C &c) : processing_count(0), number_of_handles(1) {
00081 function = new PartiallyBoundUnaryMemberFunction<C,Data,void>(f,c);
00082 }
00083
00091 ~SigSlot() {
00092 disconnect();
00093 mutex.lock();
00094 delete function;
00095 }
00096
00097 const unsigned int& handles() const { return number_of_handles; }
00098 void incrHandles() { ++number_of_handles; }
00099 void decrHandles() { --number_of_handles; }
00106 void emit(Data data) {
00107 typename PublicationMap::const_iterator topic_iter;
00108 typename Subscribers::const_iterator slots_iter;
00109 for ( topic_iter = publications.begin(); topic_iter != publications.end(); ++topic_iter ) {
00110 const Subscribers* subscribers = topic_iter->second;
00111 for ( slots_iter = subscribers->begin(); slots_iter != subscribers->end(); ++slots_iter ) {
00112 SigSlot<Data> *sigslot = *slots_iter;
00113 sigslot->process(data);
00114 }
00115 }
00116 }
00123 void process(Data data) {
00124 mutex.trylock();
00125 ++processing_count;
00126 (*function)(data);
00127 if ( --processing_count == 0 ) {
00128 mutex.unlock();
00129 }
00130 }
00138 void connectSignal(const std::string& topic) {
00139
00140
00141
00142
00143
00144
00145
00146
00147 publications.insert( std::pair<std::string, const Subscribers*>(topic, SigSlotsManager<Data>::connectSignal(topic,this)) );
00148 }
00156 void connectSlot(const std::string& topic) {
00157 std::pair< std::set<std::string>::iterator,bool > ret;
00158
00159 ret = subscriptions.insert(topic);
00160 if ( ret.second ) {
00161 SigSlotsManager<Data>::connectSlot(topic,this);
00162 }
00163 }
00167 void disconnect(const std::string &topic) {
00168 std::set<std::string>::const_iterator listen_iter = subscriptions.find(topic);
00169 publications.erase(topic);
00170 SigSlotsManager<Void>::disconnect(topic,this);
00171 }
00177 void disconnect() {
00178 std::set<std::string>::iterator iter;
00179 for ( iter = subscriptions.begin(); iter != subscriptions.end(); ++iter ) {
00180 SigSlotsManager<Data>::disconnect(*iter, this);
00181 }
00182 subscriptions.clear();
00183 typename std::map<std::string,const Subscribers*>::iterator emit_iter;
00184 for ( emit_iter = publications.begin(); emit_iter != publications.end(); ++emit_iter ) {
00185 SigSlotsManager<Data>::disconnect(emit_iter->first, this);
00186 }
00187 publications.clear();
00188 }
00189
00190 const std::set<std::string>& subscribedTopics() { return subscriptions; }
00191
00192 private:
00193 Mutex mutex;
00194 unsigned int processing_count;
00195 unsigned int number_of_handles;
00196 std::set<std::string> subscriptions;
00197 PublicationMap publications;
00198
00199 UnaryFunction<Data,void> *function;
00200 };
00201
00202
00203
00204
00205
00213 template<>
00214 class SigSlot<Void> {
00215 public:
00216
00217 typedef Topic<Void>::Subscribers Subscribers;
00218 typedef std::map<std::string, const Subscribers*> PublicationMap;
00224 SigSlot() : processing_count(0), number_of_handles(1) {
00225 function = new BoundNullaryMemberFunction<SigSlot,void>(&SigSlot::emit,*this);
00226 }
00232 SigSlot(VoidFunction f) : processing_count(0), number_of_handles(1) {
00233 function = new NullaryFreeFunction<void>(f);
00234 }
00242 template<typename C>
00243 SigSlot(void (C::*f)(void), C &c) : processing_count(0), number_of_handles(1) {
00244 function = new BoundNullaryMemberFunction<C,void>(f,c);
00245 }
00246
00254 ~SigSlot() {
00255 disconnect();
00256 mutex.lock();
00257 delete function;
00258 }
00259
00260 const unsigned int& handles() const { return number_of_handles; }
00261 void incrHandles() { ++number_of_handles; }
00262 void decrHandles() { --number_of_handles; }
00269 void emit() {
00270 PublicationMap::const_iterator topic_iter;
00271 Subscribers::const_iterator slots_iter;
00272 for ( topic_iter = publications.begin(); topic_iter != publications.end(); ++topic_iter ) {
00273 const Subscribers* subscribers = topic_iter->second;
00274 for ( slots_iter = subscribers->begin(); slots_iter != subscribers->end(); ++slots_iter ) {
00275 SigSlot *sigslot = *slots_iter;
00276 sigslot->process();
00277 }
00278 }
00279 }
00286 void process(Void void_arg = Void()) {
00287 mutex.trylock();
00288 ++processing_count;
00289 (*function)();
00290 if ( --processing_count == 0 ) {
00291 mutex.unlock();
00292 }
00293 }
00301 void connectSignal(const std::string& topic) {
00302
00303
00304
00305
00306
00307
00308
00309
00310 publications.insert( std::pair<std::string, const Subscribers*>(topic, SigSlotsManager<Void>::connectSignal(topic,this)) );
00311 }
00315 void connectSlot(const std::string& topic){
00316 std::pair< std::set<std::string>::iterator,bool > ret;
00317 ret = subscriptions.insert(topic);
00318 if ( ret.second ) {
00319 SigSlotsManager<Void>::connectSlot(topic,this);
00320 }
00321 }
00329 void disconnect(const std::string &topic) {
00330 std::set<std::string>::const_iterator listen_iter = subscriptions.find(topic);
00331 publications.erase(topic);
00332 SigSlotsManager<Void>::disconnect(topic,this);
00333 }
00339 void disconnect() {
00340 std::set<std::string>::iterator iter;
00341 for ( iter = subscriptions.begin(); iter != subscriptions.end(); ++iter ) {
00342 SigSlotsManager<Void>::disconnect(*iter, this);
00343 }
00344 subscriptions.clear();
00345 std::map<std::string,const Subscribers*>::iterator emit_iter;
00346 for ( emit_iter = publications.begin(); emit_iter != publications.end(); ++emit_iter ) {
00347 SigSlotsManager<Void>::disconnect(emit_iter->first, this);
00348 }
00349 publications.clear();
00350 }
00351
00352 private:
00353 Mutex mutex;
00354 unsigned int processing_count;
00355 unsigned int number_of_handles;
00356 std::set<std::string> subscriptions;
00357 PublicationMap publications;
00358
00359 NullaryFunction<void> *function;
00360 };
00361
00362 }
00363
00364 #endif