00001 00011 /***************************************************************************** 00012 ** Includes 00013 *****************************************************************************/ 00014 00015 00016 #include "../../include/ecl/sigslots/sigslot.hpp" 00017 00018 /***************************************************************************** 00019 ** Namespaces 00020 *****************************************************************************/ 00021 00022 namespace ecl { 00023 00024 /***************************************************************************** 00025 ** Using 00026 *****************************************************************************/ 00027 00028 using std::map; 00029 using std::set; 00030 using std::string; 00031 using ecl::Void; 00032 00033 /***************************************************************************** 00034 ** Implementation 00035 *****************************************************************************/ 00036 00037 SigSlot<Void>::~SigSlot() { 00038 disconnect(); // stop any new processing from connected signals 00039 mutex.lock(); // acts like a barrier - holds up here if function still processing stuff. 00040 delete function; 00041 } 00042 00043 void SigSlot<Void>::emit() { 00044 PublicationMap::const_iterator topic_iter; 00045 Subscribers::const_iterator slots_iter; 00046 for ( topic_iter = publications.begin(); topic_iter != publications.end(); ++topic_iter ) { 00047 const Subscribers* subscribers = topic_iter->second; 00048 for ( slots_iter = subscribers->begin(); slots_iter != subscribers->end(); ++slots_iter ) { 00049 SigSlot *sigslot = *slots_iter; 00050 sigslot->process(); 00051 } 00052 } 00053 }; 00054 00055 void SigSlot<Void>::process(Void void_arg) { 00056 mutex.trylock(); // Only lock if its not already locked. 00057 ++processing_count; 00058 (*function)(); 00059 if ( --processing_count == 0 ) { 00060 mutex.unlock(); 00061 } 00062 00063 } 00064 00065 void SigSlot<Void>::connectSignal(const std::string& topic) { 00066 // Logic: 00067 // - if already publishing to this topic 00068 // - don't do anything 00069 // - else 00070 // - if topic doesn't exist 00071 // - Manager will automatically create a new topic 00072 // - Manager returns the subscribers handle 00073 // - Topic name and subscribers handle are stored locally here in publications 00074 publications.insert( std::pair<std::string, const Subscribers*>(topic, SigSlotsManager<Void>::connectSignal(topic,this)) ); 00075 } 00076 00077 void SigSlot<Void>::connectSlot(const std::string& topic) { 00078 std::pair< set<std::string>::iterator,bool > ret; 00079 ret = subscriptions.insert(topic); // Doesn't matter if it already exists. 00080 if ( ret.second ) { 00081 SigSlotsManager<Void>::connectSlot(topic,this); 00082 } // else { already subscribed to this topic } 00083 } 00084 void SigSlot<Void>::disconnect(const std::string &topic) { 00085 set<std::string>::const_iterator listen_iter = subscriptions.find(topic); 00086 publications.erase(topic); // Doesn't matter if it finds it or not. 00087 SigSlotsManager<Void>::disconnect(topic,this); 00088 } 00089 00090 void SigSlot<Void>::disconnect() { 00091 set<std::string>::iterator iter; 00092 for ( iter = subscriptions.begin(); iter != subscriptions.end(); ++iter ) { 00093 SigSlotsManager<Void>::disconnect(*iter, this); 00094 } 00095 subscriptions.clear(); 00096 map<std::string,const Subscribers*>::iterator emit_iter; 00097 for ( emit_iter = publications.begin(); emit_iter != publications.end(); ++emit_iter ) { 00098 SigSlotsManager<Void>::disconnect(emit_iter->first, this); 00099 } 00100 publications.clear(); 00101 } 00102 00103 } // namespace ecl 00104