Титульная страница   Пространства имен   Иерархия классов   Алфавитный указатель   Классы   Файлы   Члены пространства имен   Члены классов   Члены файла  

pubsub.hpp

См. документацию.
00001 /*
00002  * Copyright (C) Sergey P. Derevyago, 2003-2004.
00003  *
00004  * Permission to copy, use, modify, sell and distribute this software is granted
00005  * provided this copyright notice appears in all copies.
00006  * This software is provided "as is" without express or implied warranty, and
00007  * with no claim as to its suitability for any purpose.
00008  *
00009  */
00010 
00015 #ifndef __PUBSUB_HPP__
00016  #define __PUBSUB_HPP__
00017 
00018 #include <list>
00019 
00024 namespace PubSub_private {
00025 
00031  struct PubImpl {
00033         typedef std::list<void*> list_type;
00035         list_type subs;
00036 
00038         bool subscribe(void* sub);
00039 
00041         bool unsubscribe(void* sub);
00042 
00044         bool isSubscribed(void* sub) const;
00045 
00047         int subCount() const { return subs.size(); }
00048  };
00049 
00050 }
00051 
00052 template<class M> class Subscriber;
00053 
00064 template<class M>
00065 class Publisher {
00066       friend class Subscriber<M>;
00067 
00069       PubSub_private::PubImpl impl;
00070 
00072       Publisher(const Publisher&);
00074       Publisher& operator=(const Publisher&);
00075 
00076  public:
00080       Publisher() {}
00081 
00087       virtual ~Publisher();
00088 
00094       bool subscribe(Subscriber<M>& sub);
00095 
00102       bool unsubscribe(Subscriber<M>& sub);
00103 
00107       bool isSubscribed(Subscriber<M>& sub) const
00108       {
00109        return impl.isSubscribed(&sub);
00110       }
00111 
00115       int subCount() const { return impl.subCount(); }
00116 
00124       int send(const M& msg);
00125 };
00126 
00135 template<class M>
00136 class Subscriber {
00137       friend class Publisher<M>;
00138 
00140       typedef typename std::list<Publisher<M>*> list_type;
00142       list_type pubs;
00143 
00145       Subscriber(const Subscriber&);
00147       Subscriber& operator=(const Subscriber&);
00148 
00149  public:
00153       Subscriber() {}
00154 
00160       virtual ~Subscriber();
00161 
00171       virtual bool regularMsg(const Publisher<M>& pub, const M& msg);
00172 
00180       virtual void subscribedMsg(const Publisher<M>& pub);
00181 
00189       virtual void unsubscribedMsg(const Publisher<M>& pub);
00190 };
00191 
00192 template<class M>
00193 Publisher<M>::~Publisher()
00194 {
00195  for (PubSub_private::PubImpl::list_type::const_iterator cit=impl.subs.begin(),
00196       cend=impl.subs.end(); cit!=cend; ++cit) {
00197      Subscriber<M>* psub=static_cast<Subscriber<M>*>(*cit);
00198      psub->pubs.remove(this);
00199 
00200      try { psub->unsubscribedMsg(*this); }
00201      catch (...) {}  // игнорируем
00202  }
00203 }
00204 
00205 template<class M>
00206 bool Publisher<M>::subscribe(Subscriber<M>& sub)
00207 {
00208  bool ret=impl.subscribe(&sub);
00209 
00210  if (ret) {
00211     sub.pubs.push_back(this);
00212 
00213     try { sub.subscribedMsg(*this); }
00214     catch (...) {}  // игнорируем
00215  }
00216 
00217  return ret;
00218 }
00219 
00220 template<class M>
00221 bool Publisher<M>::unsubscribe(Subscriber<M>& sub)
00222 {
00223  bool ret=impl.unsubscribe(&sub);
00224 
00225  if (ret) {
00226     sub.pubs.remove(this);
00227 
00228     try { sub.unsubscribedMsg(*this); }
00229     catch (...) {}  // игнорируем
00230  }
00231 
00232  return ret;
00233 }
00234 
00235 template<class M>
00236 int Publisher<M>::send(const M& msg) 
00237 {
00238  int count=0;
00239  for (PubSub_private::PubImpl::list_type::iterator it=impl.subs.begin(),
00240       end=impl.subs.end(); it!=end; count++) {
00241      Subscriber<M>* psub=static_cast<Subscriber<M>*>(*it);
00242 
00243      bool ret=1;
00244      try { ret=psub->regularMsg(*this, msg); }
00245      catch (...) {}  // игнорируем
00246 
00247      ++it;
00248      if (!ret) unsubscribe(*psub);
00249  }
00250 
00251  return count;
00252 }
00253 
00254 template<class M>
00255 Subscriber<M>::~Subscriber()
00256 {
00257  for (typename list_type::const_iterator cit=pubs.begin(), cend=pubs.end();
00258       cit!=cend; ++cit) {
00259      (*cit)->impl.unsubscribe(this);
00260  }
00261 }
00262 
00263 template<class M>
00264 bool Subscriber<M>::regularMsg(const Publisher<M>&, const M&)
00265 {
00266  return 1;
00267 }
00268 
00269 template<class M>
00270 void Subscriber<M>::subscribedMsg(const Publisher<M>&)
00271 {
00272 }
00273 
00274 template<class M>
00275 void Subscriber<M>::unsubscribedMsg(const Publisher<M>&)
00276 {
00277 }
00278 
00279 #endif

Документация по ftext. Последние изменения: Sat Mar 20 17:58:15 2004. Создано системой doxygen1.3