00001 // -*- C++ -*- 00019 #ifndef RTM_UTIL_LISTENERHOLDER_H 00020 #define RTM_UTIL_LISTENERHOLDER_H 00021 00022 #include <vector> 00023 #include <utility> 00024 #include <coil/Mutex.h> 00025 #include <coil/Guard.h> 00026 #include <coil/NonCopyable.h> 00027 00028 namespace RTM 00029 { 00030 namespace util 00031 { 00143 template <typename ListenerClass> 00144 class ListenerHolder 00145 : public coil::NonCopyable 00146 { 00147 public: 00148 typedef coil::Guard<coil::Mutex> Guard; 00149 typedef std::pair<ListenerClass*, bool> Entry; 00150 typedef std::vector<Entry> EntryList; 00151 typedef typename EntryList::iterator EntryIterator; 00152 00160 ListenerHolder() 00161 { 00162 } 00163 00171 virtual ~ListenerHolder() 00172 { 00173 Guard guard(m_mutex); 00174 EntryIterator it(m_listeners.begin()); 00175 00176 for (; it != m_listeners.end(); ++it) 00177 { 00178 if ((*it).second) 00179 { 00180 delete (*it).first; 00181 } 00182 m_listeners.erase(it); 00183 } 00184 } 00185 00193 virtual void addListener(ListenerClass* listener, 00194 bool autoclean) 00195 { 00196 Guard guard(m_mutex); 00197 m_listeners.push_back(Entry(listener, autoclean)); 00198 } 00199 00207 virtual void removeListener(ListenerClass* listener) 00208 { 00209 Guard guard(m_mutex); 00210 EntryIterator it(m_listeners.begin()); 00211 00212 for (; it != m_listeners.end(); ++it) 00213 { 00214 if ((*it).first == listener) 00215 { 00216 if ((*it).second) 00217 { 00218 delete (*it).first; 00219 } 00220 m_listeners.erase(it); 00221 return; 00222 } 00223 } 00224 } 00225 00226 protected: 00234 coil::Mutex m_mutex; 00235 00243 EntryList m_listeners; 00244 }; 00245 }; // util 00246 }; // RTM 00247 00248 #define LISTENERHOLDER_CALLBACK(func, args) \ 00249 { \ 00250 Guard guard(m_mutex); \ 00251 for (int i(0), len(m_listeners.size()); i < len; ++i) \ 00252 { \ 00253 m_listeners[i].first->func args; \ 00254 } \ 00255 } 00256 00257 #endif // RTM_UITL_LISTENERHOLDER_H