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 ECL_PUBLIC 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
00093 const unsigned int& handles() const { return number_of_handles; }
00094 void incrHandles() { ++number_of_handles; }
00095 void decrHandles() { --number_of_handles; }
00102 void emit(Data data);
00109 void process(Data data);
00117 void connectSignal(const std::string& topic);
00125 void connectSlot(const std::string& topic);
00129 void disconnect(const std::string &topic);
00135 void disconnect();
00136
00137 const std::set<std::string>& subscribedTopics() { return subscriptions; }
00138
00139 private:
00140 Mutex mutex;
00141 unsigned int processing_count;
00142 unsigned int number_of_handles;
00143 std::set<std::string> subscriptions;
00144 PublicationMap publications;
00145
00146 UnaryFunction<Data,void> *function;
00147 };
00148
00149
00150
00151
00152 template<typename Data>
00153 SigSlot<Data>::~SigSlot() {
00154 disconnect();
00155 mutex.lock();
00156 delete function;
00157 }
00158
00159 template<typename Data>
00160 void SigSlot<Data>::emit(Data data) {
00161 typename PublicationMap::const_iterator topic_iter;
00162 typename Subscribers::const_iterator slots_iter;
00163 for ( topic_iter = publications.begin(); topic_iter != publications.end(); ++topic_iter ) {
00164 const Subscribers* subscribers = topic_iter->second;
00165 for ( slots_iter = subscribers->begin(); slots_iter != subscribers->end(); ++slots_iter ) {
00166 SigSlot<Data> *sigslot = *slots_iter;
00167 sigslot->process(data);
00168 }
00169 }
00170 };
00171
00172 template<typename Data>
00173 void SigSlot<Data>::process(Data data) {
00174 mutex.trylock();
00175 ++processing_count;
00176 (*function)(data);
00177 if ( --processing_count == 0 ) {
00178 mutex.unlock();
00179 }
00180
00181 }
00182
00183 template<typename Data>
00184 void SigSlot<Data>::connectSignal(const std::string& topic) {
00185
00186
00187
00188
00189
00190
00191
00192
00193 publications.insert( std::pair<std::string, const Subscribers*>(topic, SigSlotsManager<Data>::connectSignal(topic,this)) );
00194 }
00195
00196 template<typename Data>
00197 void SigSlot<Data>::connectSlot(const std::string& topic) {
00198 std::pair< std::set<std::string>::iterator,bool > ret;
00199
00200 ret = subscriptions.insert(topic);
00201 if ( ret.second ) {
00202 SigSlotsManager<Data>::connectSlot(topic,this);
00203 }
00204 }
00205 template<typename Data>
00206 void SigSlot<Data>::disconnect(const std::string &topic) {
00207 std::set<std::string>::const_iterator listen_iter = subscriptions.find(topic);
00208 publications.erase(topic);
00209 SigSlotsManager<Void>::disconnect(topic,this);
00210 }
00211
00212 template<typename Data>
00213 void SigSlot<Data>::disconnect() {
00214 std::set<std::string>::iterator iter;
00215 for ( iter = subscriptions.begin(); iter != subscriptions.end(); ++iter ) {
00216 SigSlotsManager<Data>::disconnect(*iter, this);
00217 }
00218 subscriptions.clear();
00219 typename std::map<std::string,const Subscribers*>::iterator emit_iter;
00220 for ( emit_iter = publications.begin(); emit_iter != publications.end(); ++emit_iter ) {
00221 SigSlotsManager<Data>::disconnect(emit_iter->first, this);
00222 }
00223 publications.clear();
00224 }
00225
00226
00227
00228
00229
00237 template<>
00238 class ECL_PUBLIC SigSlot<Void> {
00239 public:
00240
00241 typedef Topic<Void>::Subscribers Subscribers;
00242 typedef std::map<std::string, const Subscribers*> PublicationMap;
00248 SigSlot() : processing_count(0), number_of_handles(1) {
00249 function = new BoundNullaryMemberFunction<SigSlot,void>(&SigSlot::emit,*this);
00250 }
00256 SigSlot(VoidFunction f) : processing_count(0), number_of_handles(1) {
00257 function = new NullaryFreeFunction<void>(f);
00258 }
00266 template<typename C>
00267 SigSlot(void (C::*f)(void), C &c) : processing_count(0), number_of_handles(1) {
00268 function = new BoundNullaryMemberFunction<C,void>(f,c);
00269 }
00270
00278 ~SigSlot();
00279
00280 const unsigned int& handles() const { return number_of_handles; }
00281 void incrHandles() { ++number_of_handles; }
00282 void decrHandles() { --number_of_handles; }
00289 void emit();
00296 void process(Void void_arg = Void());
00304 void connectSignal(const std::string& topic);
00308 void connectSlot(const std::string& topic);
00316 void disconnect(const std::string &topic);
00322 void disconnect();
00323
00324 private:
00325 Mutex mutex;
00326 unsigned int processing_count;
00327 unsigned int number_of_handles;
00328 std::set<std::string> subscriptions;
00329 PublicationMap publications;
00330
00331 NullaryFunction<void> *function;
00332 };
00333
00334 }
00335
00336 #endif