C ++ (рдЕрднреНрдпрд╛рд╕) рдореЗрдВ рдмрд╣реБрдкрд░рдд рдкрд░реНрдпрд╡реЗрдХреНрд╖рдХ

рдЗрд╕ рдкреИрдЯрд░реНрди рдХреЗ рд╡рд┐рд╖рдп рдкрд░ рдХрдИ рднрд┐рдиреНрдирддрд╛рдПрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрдзрд┐рдХрд╛рдВрд╢ рдЙрджрд╛рд╣рд░рдг рдорд▓реНрдЯреАрдереНрд░реЗрдб рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рдирд╣реАрдВ рд╣реИрдВред

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рдкреИрдЯрд░реНрди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рдЕрдиреБрднрд╡ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдФрд░ рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реВрдВ рдЬреЛ рдореБрдЭреЗ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ рд╣реИред

рдЗрд╕ рд▓реЗрдЦ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рддреЗ рд╕рдордп рд╕рд╛рдордирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдореЗрдВ рдШрдЯрдХреЛрдВ рдХреЗ рдмреАрдЪ рд╕рдВрдЪрд╛рд░ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдиреБрдХрд╕рд╛рди рдХреА рдкрд╣рдЪрд╛рди рдХрд░реЗрдВред

рдпрджрд┐ рдЖрдкрдХреЛ рддреИрдпрд╛рд░ рд╕рдорд╛рдзрд╛рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рд╕рд┐рдЧреНрдирд▓ 2 рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ, рдЬрд┐рд╕реЗ рдордИ 2009 рд╕реЗ рдмрдврд╝рд╛рд╡рд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдореИрдВ рдПрдХ рдРрд╕рд╛ рд╕рдорд╛рдзрд╛рди рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред рдлрд┐рд░ рднреА, рд╕рд╛рдордЧреНрд░реА рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рдЙрди рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╡реЗ рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИрдВ рдпрд╛ рдХрд┐рд╕реА рдХрд╛рд░рдг (рдбреНрд░рд╛рдЗрд╡рд░, рдирд┐рдореНрди-рд╕реНрддрд░реАрдп рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ, рдЖрджрд┐) рдХреЗ рд▓рд┐рдП рдЕрд╡рд╛рдВрдЫрдиреАрдп рд╣реИрдВред



рд╡рд┐рд╖рдп рдХреНрд╖реЗрддреНрд░



рдкрд╛рддреНрд░


рд╕реВрдЪрдирд╛ рднреЗрдЬрдиреЗ рд╡рд╛рд▓рд╛ - рд╕рдВрджреЗрд╢ рднреЗрдЬрдиреЗ рд╡рд╛рд▓реА рд╡рд╕реНрддреБред

рдЖрдорддреМрд░ рдкрд░, рдпрд╣ рдЕрдкрдиреЗ рд░рд╛рдЬреНрдп рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ рд╡рд░реНрдХрдлрд╝реНрд▓реЛ рд╣реИ, рдЬрд┐рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

NotificationListener - рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдЬреЛ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред

рдЖрдорддреМрд░ рдкрд░, рдпрд╣ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реИ рдЬреЛ рдкреГрд╖реНрдарднреВрдорд┐ рдХрд╛рд░реНрдп рд╕реЗ рдЬреБрдбрд╝реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдПрдХ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред

рдРрд╕реА рдХрдИ рд╡рд╕реНрддреБрдПрдВ рд╣реЛ рд╕рдХрддреА рд╣реИрдВ, рдЬрдмрдХрд┐ рд╡реЗ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдХрдиреЗрдХреНрдЯ / рдбрд┐рд╕реНрдХрдиреЗрдХреНрдЯ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╕рдВрд╡рд╛рдж рдмреЙрдХреНрд╕ рдЦреЛрд▓рдирд╛ рдЬрд╣рд╛рдВ рдХрд╛рд░реНрдп рдХрд╛ рд╡рд┐рд╡рд░рдг рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ)

NotificationDispatcher - рдПрдХ рд╡рд╕реНрддреБ рдЬреЛ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдФрд░ рдореЗрд▓рд┐рдВрдЧ рд╕реВрдЪрд┐рдпреЛрдВ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рддреА рд╣реИред



рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдмреАрдЪ рдмрд╛рддрдЪреАрдд


рд╕рднреА рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рд╕рдВрджреЗрд╢реЛрдВ рдХрд╛ рд╡рд┐рддрд░рдгред

рдХрд┐рд╕реА рд╕рджрд╕реНрдпрддрд╛ рдХреЛ рд╕рдорд╛рдкреНрдд / рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ред

рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдЬреАрд╡рдирдХрд╛рд▓ред

рдпрд╣ рдЖрд▓реЗрдЦ рдПрдХ рд╕рдордХрд╛рд▓рд┐рдХ рд╕рдВрджреЗрд╢ рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ SendMessage рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдХреЙрд▓ рд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд╣реЛрдЧрд╛, рдФрд░ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдереНрд░реЗрдб рд╕рднреА рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдмрд░реНрд╕ рдХреЛ рдореИрд╕реЗрдЬ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдВрддрдЬрд╛рд░ рдХрд░реЗрдЧрд╛ред рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдореЗрд▓рд┐рдВрдЧ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдЗрд╕реЗ рдЕрдирд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдХрд░рдиреЗ рдореЗрдВ рдХрдард┐рдирд╛рдИ рд╣реЛрддреА рд╣реИред



рд╕рдмрд╕реЗ рд╕рд░рд▓ рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди



typedef unsigned __int64 SubscriberId; class CSubscriber { public: virtual ~CSubscriber(){} virtual void MessageHandler(void* pContext) = 0; SubscriberId GetSubscriberId() {return (SubscriberId)this;} }; class CDispatcher { private: typedef std::vector<CSubscriber*> CSubscriberList; public: SubscriberId Subscribe(CSubscriber* pNewSubscriber) { for(size_t i = 0; i < m_SubscriberList.size(); ++i) { if(m_SubscriberList[i]->GetSubscriberId() == pNewSubscriber->GetSubscriberId()) { return 0; } } m_SubscriberList.push_back(pNewSubscriber); return pNewSubscriber->GetSubscriberId(); } bool Unsubscribe(SubscriberId id) { for(size_t i = 0; i < m_SubscriberList.size(); ++i) { if(m_SubscriberList[i]->GetSubscriberId() == id) { m_SubscriberList.erase(m_SubscriberList.begin() + i); return true; } } return false; } void SendMessage(void* pContext) { for(size_t i = 0; i < m_SubscriberList.size(); ++i) { m_SubscriberList[i]->MessageHandler(pContext); } } private: CSubscriberList m_SubscriberList; };
      
      





рдпрд╣рд╛рдВ рдЧреНрд░рд╛рд╣рдХ рдХреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкрд╣рдЪрд╛рди рдЧреНрд░рд╛рд╣рдХ рд╡рд╕реНрддреБ рдХрд╛ рдкрддрд╛ рд╣реИ, GetSubscriberId рдлрд╝рдВрдХреНрд╢рди рд╣рдореЗрд╢рд╛ рдПрдХ рдЧреНрд░рд╛рд╣рдХ рд╡рд╕реНрддреБ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рди рдорд╛рди рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдЪрд╛рд╣реЗ рд╡рд╣ рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реЛред



рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ


 class CListener: public CSubscriber { virtual void MessageHandler(void* pContext) { wprintf(L"%d\n", *((int*)pContext)); } }; int _tmain(int argc, _TCHAR* argv[]) { CDispatcher Dispatcher; CListener Listener1; CListener Listener2; Dispatcher.Subscribe(&Listener1); Dispatcher.Subscribe(&Listener2); for(int i = 0; i < 5; ++i) { Dispatcher.SendMessage(&i); } Dispatcher.Unsubscribe(Listener2.GetSubscriberId()); Dispatcher.Unsubscribe(Listener1.GetSubscriberId()); return 0; }
      
      





рдПрдХ рд╕рдВрджреЗрд╢ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдЕрдВрджрд░ рдПрдХ рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдмрд░ рдХреЛ рдЕрдХреНрд╖рдо рдХрд░рдирд╛



рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ рдЬреЛ рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╣реАрдВ рд╣реИред рдЬрдм рд╣рдо MessageHandler рд╣реИрдВрдбрд▓рд░ рдХреЗ рдЕрдВрджрд░ рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╕реНрд╡рдпрдВ рдкреНрд░рдХрдЯ рд╣реЛрддреА рд╣реИред MessageHandler рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рд╕реВрдЪреА рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдХрд░ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред



рдПрдХ рдмрд╣реБрдЖрдпрд╛рдореА рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдЖрдЧреЗ рдмрдврд╝ рд░рд╣рд╛ рд╣реИ



рдПрдХ рдзрд╛рдЧреЗ рдХреЗ рд╕рд╛рде, рдРрд╕рд╛ рдХреЛрдб рдХрд╛рдлреА рдХрд╛рдо рдХрд░реЗрдЧрд╛ред

рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдЬрдм рдХрдИ рдзрд╛рдЧреЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИред

 CDispatcher g_Dispatcher; DWORD WINAPI WorkingThread(PVOID pParam) { for(int i = 0;;++i) { g_Dispatcher.SendMessage(&i); } }; int _tmain(int argc, _TCHAR* argv[]) { ::CreateThread(NULL, 0, WorkingThread, NULL, 0, NULL); CListener Listener1; CListener Listener2; for(;;) { g_Dispatcher.Subscribe(&Listener1); g_Dispatcher.Subscribe(&Listener2); g_Dispatcher.Unsubscribe(Listener1.GetSubscriberId()); g_Dispatcher.Unsubscribe(Listener2.GetSubscriberId()); } return 0; }
      
      





рдЬрд▓реНрджреА рдпрд╛ рдмрд╛рдж рдореЗрдВ, рдПрдХ рджреБрд░реНрдШрдЯрдирд╛ рдШрдЯрд┐рдд рд╣реЛрдЧреАред

рд╕рдорд╕реНрдпрд╛ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рдЬреЛрдбрд╝ рд░рд╣реА рд╣реИ / рд╣рдЯрд╛ рд░рд╣реА рд╣реИ рдФрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдиреЛрдЯрд┐рдлрд┐рдХреЗрд╢рди рднреЗрдЬ рд░рд╣реА рд╣реИ (рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ CDispatcher :: m_SubscriberList рдкрд░ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдПрдХреНрд╕реЗрд╕)ред

рдпрд╣рд╛рдВ рдЖрдкрдХреЛ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рд╕реВрдЪреА рддрдХ рдкрд╣реБрдВрдЪ рдХреЛ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред



рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдмрд░ рд╕реВрдЪреА рдПрдХреНрд╕реЗрд╕ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди



 class CDispatcher { private: typedef std::vector<CSubscriber*> CSubscriberList; public: SubscriberId Subscribe(CSubscriber* pNewSubscriber) { CScopeLocker ScopeLocker(m_Lock); for(size_t i = 0; i < m_SubscriberList.size(); ++i) { if(m_SubscriberList[i]->GetSubscriberId() == pNewSubscriber->GetSubscriberId()) { return 0; } } m_SubscriberList.push_back(pNewSubscriber); return pNewSubscriber->GetSubscriberId(); } bool Unsubscribe(SubscriberId id) { CScopeLocker ScopeLocker(m_Lock); for(size_t i = 0; i < m_SubscriberList.size(); ++i) { if(m_SubscriberList[i]->GetSubscriberId() == id) { m_SubscriberList.erase(m_SubscriberList.begin() + i); return true; } } return false; } void SendMessage(void* pContext) { CScopeLocker ScopeLocker(m_Lock); for(size_t i = 0; i < m_SubscriberList.size(); ++i) { m_SubscriberList[i]->MessageHandler(pContext); } } private: CSubscriberList m_SubscriberList; CLock m_Lock; };
      
      





рдПрдХреНрд╕реЗрд╕ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рдХреЛ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ (рдХреНрд░рд┐рдЯрд┐рдХрд▓ рд╕реЗрдХреНрд╢рди рдпрд╛ рдореНрдпреВрдЯреЗрдХреНрд╕) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдЕрдзрд┐рдХ рдкреЛрд░реНрдЯреЗрдмрд┐рд▓рд┐рдЯреА рдХреЗ рд▓рд┐рдП рдФрд░ рдЬреЛ рдХреБрдЫ рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдЙрд╕рдХреЗ рд╕рд╛рд░ рд╕реЗ рд╡рд┐рдЪрд▓рд┐рдд рдирд╣реАрдВ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕реАрдзреЗ рдХреЙрд▓ рд╕реЗ рд▓реЗрдХрд░ рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо-рдбрд┐рдкреЗрдВрдбреЗрдВрдЯ рдлрдВрдХреНрд╢рдиреНрд╕ рдЬреИрд╕реЗ рдХрд┐ рдПрдВрдЯрд░рдХреНрд░рд┐рдЯрд▓реАрд╕реЗрдХреНрд╢рди рдкрд░ рдЕрдорд▓ рдХрд░рддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, CLock рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

C ++ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЗ рдкреНрд░рддрд┐рд░реЛрдз рдХреЗ рд▓рд┐рдП, RAII рддрдХрдиреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рдЕрд░реНрдерд╛рддреН CScopeLocker рд╡рд░реНрдЧ, рдЬреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдПрдХ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдкрдХрдбрд╝рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рд╡рд┐рдзреНрд╡рдВрд╕рдХ рдореЗрдВ рдореБрдХреНрдд рдХрд░рддрд╛ рд╣реИред

рдЗрд╕ рддрд░рд╣ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕реЗ, рдХрд╛рд░реНрдпрдХреНрд░рдо рдЧрд┐рд░ рдирд╣реАрдВ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдПрдХ рдФрд░ рдЕрдкреНрд░рд┐рдп рд╕реНрдерд┐рддрд┐ рд╣рдореЗрдВ рдЗрдВрддрдЬрд╛рд░ рдХрд░ рд░рд╣реА рд╣реИред



рдЧрддрд┐рд░реЛрдз рд╕реЗ рд▓рдбрд╝рдирд╛



рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдзрд╛рдЧрд╛ рд╣реИ рдЬреЛ рдХреБрдЫ рдкреГрд╖реНрдарднреВрдорд┐ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдЦрд┐рдбрд╝рдХреА рд╣реИ рдЬрд╣рд╛рдВ рдЗрд╕ рдХрд╛рд░реНрдп рдХреА рдкреНрд░рдЧрддрд┐ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрддреА рд╣реИред

рдЖрдорддреМрд░ рдкрд░, рдПрдХ рдереНрд░реЗрдб рд╡рд┐рдВрдбреЛ рдХреНрд▓рд╛рд╕ рдХреЛ рдПрдХ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рднреЗрдЬрддрд╛ рд╣реИ, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ SendMessage рд╕рд┐рд╕реНрдЯрдо рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рд╡рд┐рдВрдбреЛ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдХреБрдЫ рдХрд╛рд░реНрд░рд╡рд╛рдИ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИред

SendMessage рд╕рд┐рд╕реНрдЯрдо рдлрд╝рдВрдХреНрд╢рди рдЕрд╡рд░реБрджреНрдз рд╣реИ, рдпрд╣ рд╡рд┐рдВрдбреЛ рдереНрд░реЗрдб рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрджреЗрд╢ рднреЗрдЬрддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИред

рдпрджрд┐ рд╢реНрд░реЛрддрд╛ рд╡рд╕реНрддреБ рдХрд╛ рдХрдиреЗрдХреНрд╢рди / рд╡рд┐рдпреЛрдЧ рд╡рд┐рдВрдбреЛ рдкреНрд░рдХреНрд░рд┐рдпрд╛ (рд╡рд┐рдВрдбреЛ рдереНрд░реЗрдб рдореЗрдВ), рдереНрд░реЗрдбреНрд╕ рдХреЗ рдЖрдкрд╕реА рдЕрд╡рд░реЛрдзрди, рддрдерд╛рдХрдерд┐рдд рдЧрддрд┐рд░реЛрдз рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рднреА рд╣реЛрдЧрд╛, рддреЛ рд╕рдВрднрд╡ рд╣реИред

рдЗрд╕ рддрд░рд╣ рдХреЗ рдЧрддрд┐рд░реЛрдз рдХреЛ рд╢рд╛рдпрдж рд╣реА рдХрднреА рдкреБрди: рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдХреЙрд▓рд┐рдВрдЧ рдХреЗ рд╕рдордп рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдВ / рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░реЗрдВ рдФрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ MessageHandler рдХреЛ рдЕрд▓рдЧ рдереНрд░реЗрдб рдореЗрдВ рдмреБрд▓рд╛рдПрдВ)

рдирд┐рдореНрди рдХреЛрдб SendMessage рд╕рд┐рд╕реНрдЯрдо рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд╡рд░реБрджреНрдз рдХреЙрд▓ рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░рддрд╛ рд╣реИред



 CDispatcher g_Dispatcher; CLock g_Lock; class CListener: public CSubscriber { virtual void MessageHandler(void* pContext) { //   SendMessage g_Lock.Lock(); wprintf(L"%d\n", *((int*)pContext)); g_Lock.Unlock(); } }; DWORD WINAPI WorkingThread(PVOID pParam) { for(int i = 0;;++i) { g_Dispatcher.SendMessage(&i); } }; int _tmain(int argc, _TCHAR* argv[]) { ::CreateThread(NULL, 0, WorkingThread, NULL, 0, NULL); CListener Listener1; CListener Listener2; for(;;) { //    (  ) g_Lock.Lock(); g_Dispatcher.Subscribe(&Listener1); g_Dispatcher.Subscribe(&Listener2); g_Lock.Unlock(); Sleep(0); g_Lock.Lock(); g_Dispatcher.Unsubscribe(Listener1.GetSubscriberId()); g_Dispatcher.Unsubscribe(Listener2.GetSubscriberId()); g_Lock.Unlock(); } return 0; }
      
      





рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдореБрдЦреНрдп рдереНрд░реЗрдб g_Lock рдЧреНрд▓реЛрдмрд▓ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ (рд╡рд┐рдВрдбреЛ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реЛрдиреЗ рдкрд░, рдпрд╣ рд╡рд┐рдВрдбреЛ рд╕реНрдЯреНрд░реАрдо рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрддрд╛ рд╣реИ) рдХреЛ рдХреИрдкреНрдЪрд░ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ Subscribe / Unsubscribe рдореЗрдердб рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдЕрдВрджрд░ рджреВрд╕рд░рд╛ CDispatcher :: m_Lock рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреИрдкреНрдЪрд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИред

рдЗрд╕ рд╕рдордп, рд╡рд░реНрдХрд░ рдереНрд░реЗрдб рдПрдХ рд╕реВрдЪрдирд╛ рднреЗрдЬрддрд╛ рд╣реИ, CDispatcher :: m_Lock in CDispatcher :: SendMessage рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреИрдкреНрдЪрд░ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ g_Lock рдЧреНрд▓реЛрдмрд▓ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ (рд╡рд┐рдВрдбреЛ рдХреЗ рд╕рд╛рде рд╕рд╛рджреГрд╢реНрдп рдореЗрдВ, рдпрд╣ SendMessage рд╕рд┐рд╕реНрдЯрдо рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ) рдХреЛ рдХреИрдкреНрдЪрд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИред



 рд╡рд┐рдВрдбреЛ рдлреНрд▓реЛ рдП -> рдмреА
 рд╡рд░реНрдХрдлрд╝реНрд▓реЛ рдмреА -> рдП


рдЗрд╕реЗ рдХреНрд▓рд╛рд╕рд┐рдХ рдЧрддрд┐рд░реЛрдз рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рд╕рдорд╕реНрдпрд╛ CDispatcher :: SendMessage () рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИред

рдпрд╣рд╛рдВ рдирд┐рдпрдо рдХрд╛ рдкрд╛рд▓рди рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП - рдЖрдк рдХрд┐рд╕реА рднреА рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдХреИрдкреНрдЪрд░ рдХрд░рддреЗ рд╕рдордп рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред

рдЗрд╕рд▓рд┐рдП, рд╣рдо рд╕реВрдЪрдирд╛рдПрдБ рднреЗрдЬрддреЗ рд╕рдордп рддрд╛рд▓рд╛ рд╣рдЯрд╛ рджреЗрддреЗ рд╣реИрдВред



 void SendMessage(void* pContext) { CSubscriberList SubscriberList; { CScopeLocker ScopeLocker(m_Lock); SubscriberList = m_SubscriberList; } for(size_t i = 0; i < SubscriberList.size(); ++i) { SubscriberList[i]->MessageHandler(pContext); } }
      
      





рдЖрдЬреАрд╡рди рдирд┐рдпрдВрддреНрд░рдг рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрддрд╛ рд╣реИ



рдбреЗрдбрд▓реЙрдХ рд╣рдЯрд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдПрдХ рдФрд░ рд╕рдорд╕реНрдпрд╛ рд╕рд╛рдордиреЗ рдЖрдИ - рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рдХрд╛ рдЬреАрд╡рдирдХрд╛рд▓ред

рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдпрд╣ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рд╣реИ рдХрд┐ Unsubscribe рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж MessageHandler рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдЗрд╕рд▓рд┐рдП рд╣рдо Unsubscribe рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж рд╕рдмреНрд╕реНрдХреНрд░рд╛рдЗрдмреНрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╣рдЯрд╛ рдирд╣реАрдВ рд╕рдХрддреЗред

рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рд▓рд┐рдВрдХ рдХрд╛рдЙрдВрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рдХреЗ рдЬреАрд╡рдирдХрд╛рд▓ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рд╣реИред

рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк COM рддрдХрдиреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ - IUnogn рд╕реЗ CSubscriber рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╡рд╛рд░рд┐рд╕ рдХрд░реЗрдВ рдФрд░ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреА рд╕рджрд╕реНрдпрддрд╛ рдХреА рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП ATL CComPtr рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рдпрд╛рдиреА std :: рд╡реЗрдХреНрдЯрд░ <CSubscriber *> std :: рд╡реЗрдХреНрдЯрд░ <CComPtr> рдХреА рдЬрдЧрд╣ рд▓реЗрдВред

рд▓реЗрдХрд┐рди рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЧреНрд░рд╛рд╣рдХ рд╡рд░реНрдЧреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рд▓рд╛рдЧрддреЛрдВ рд╕реЗ рднрд░рд╛ рд╣реБрдЖ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдореЗрдВ AddRef / Release рдФрд░ рдЕрдирд╛рд╡рд╢реНрдпрдХ QueryInterface рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрджрд┐ рдкрд░рд┐рдпреЛрдЬрдирд╛ COM рдХрд╛ рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реА рд╣реИ, рддреЛ рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдПрдХ рдлрд╛рдпрджрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рд╕реНрдорд╛рд░реНрдЯ рдкреЙрдЗрдВрдЯрд░реНрд╕ рд▓рд┐рдВрдХ рдХрд╛рдЙрдВрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рдХреЗ рдЬреАрд╡рдирдХрд╛рд▓ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЕрдиреБрдХреВрд▓ рд╣реИрдВред



рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рд╡рд╛рддрд╛рд╡рд░рдг рдХреЗ рд▓рд┐рдП рд╕рд░рд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди



 typedef unsigned __int64 SubscriberId; class CSubscriber { public: virtual ~CSubscriber(){} virtual void MessageHandler(void* pContext) = 0; SubscriberId GetSubscriberId() {return (SubscriberId)this;} }; typedef boost::shared_ptr<CSubscriber> CSubscriberPtr; class CDispatcher { private: typedef std::vector<CSubscriberPtr> CSubscriberList; public: SubscriberId Subscribe(CSubscriberPtr pNewSubscriber) { CScopeLocker ScopeLocker(m_Lock); for(size_t i = 0; i < m_SubscriberList.size(); ++i) { if(m_SubscriberList[i]->GetSubscriberId() == pNewSubscriber->GetSubscriberId()) { return 0; } } m_SubscriberList.push_back(pNewSubscriber); return pNewSubscriber->GetSubscriberId(); } bool Unsubscribe(SubscriberId id) { CSubscriberPtr toRelease; CScopeLocker ScopeLocker(m_Lock); for(size_t i = 0; i < m_SubscriberList.size(); ++i) { if(m_SubscriberList[i]->GetSubscriberId() == id) { toRelease = m_SubscriberList[i]; m_SubscriberList.erase(m_SubscriberList.begin() + i); return true; } } return false; } void SendMessage(void* pContext) { CSubscriberList SubscriberList; { CScopeLocker ScopeLocker(m_Lock); SubscriberList = m_SubscriberList; } for(size_t i = 0; i < SubscriberList.size(); ++i) { SubscriberList[i]->MessageHandler(pContext); } } private: CSubscriberList m_SubscriberList; CLock m_Lock; };
      
      





рдЗрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ, рдореИрдВрдиреЗ рдПрдХ рд╕рдВрджрд░реНрдн рдХрд╛рдЙрдВрдЯрд░ рдХреЗ рд╕рд╛рде "рд╕реНрдорд╛рд░реНрдЯ" рд╕реВрдЪрдХ рдХреЗ рд╕рд╛рде "рдирдВрдЧреЗ" CSubscriber рдХреЗ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдмрджрд▓ рджрд┐рдпрд╛, рдЬреЛ рдмреВрд╕реНрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдирд┐рдХрд▓рд╛ред

рд╕рд╛рде рд╣реА, рдореИрдВрдиреЗ рдЕрдирд▓реЙрдХ рдХреЗ рдмрд╛рдж рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдмрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдбрд┐рд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдирд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ toRelease рд╡реИрд░рд┐рдПрдмрд▓ рдХреЛ рдЬреЛрдбрд╝рд╛ (рдЖрдк рдЕрдкрдиреЗ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдХреИрдкреНрдЪрд░ рдХрд░рддреЗ рд╕рдордп рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдмрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдбрд┐рд╕реНрдЯреНрд░рдХреНрдЯрд░ рд╕рд╣рд┐рдд рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ)ред

рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ SendMessage рдлрд╝рдВрдХреНрд╢рди рд╕реНрдорд╛рд░реНрдЯ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреА рд╕реВрдЪреА рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рддрд╛ рд╣реИ (рдХреЙрдкреА рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╕рднреА рдкреЙрдЗрдВрдЯрд░реНрд╕ рдЙрдирдХреЗ рд╕рдВрджрд░реНрдн рдХреА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╡реГрджреНрдзрд┐ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЬрдм рд╡реЗ рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рддреЗ рд╣реИрдВ, рддреЛ рд╡реЗ рдШрдЯ рдЬрд╛рддреЗ рд╣реИрдВ, рдЬреЛ рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рдХреЗ рдЬреАрд╡рдирдХрд╛рд▓ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реИ)



рдкрд░реАрдХреНрд╖рдг



 CDispatcher g_Dispatcher; CLock g_Lock; class CListener: public CSubscriber { virtual void MessageHandler(void* pContext) { //   SendMessage g_Lock.Lock(); wprintf(L"%d\n", *((int*)pContext)); g_Lock.Unlock(); } }; DWORD WINAPI WorkingThread(PVOID pParam) { for(int i = 0;;++i) { g_Dispatcher.SendMessage(&i); } }; int _tmain(int argc, _TCHAR* argv[]) { ::CreateThread(NULL, 0, WorkingThread, NULL, 0, NULL); for(;;) { boost::shared_ptr<CListener> pListener1(new CListener); boost::shared_ptr<CListener> pListener2(new CListener); //    (  ) g_Lock.Lock(); g_Dispatcher.Subscribe(pListener1); g_Dispatcher.Subscribe(pListener2); g_Lock.Unlock(); Sleep(0); g_Lock.Lock(); g_Dispatcher.Unsubscribe(pListener1->GetSubscriberId()); g_Dispatcher.Unsubscribe(pListener2->GetSubscriberId()); g_Lock.Unlock(); } return 0; }
      
      





рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рд╡рд╛рддрд╛рд╡рд░рдг рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди



рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, SendMessage рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рджрд╕реНрдпрддрд╛ / рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рдмрд╛рд░ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ред рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рд╕рд╛рде, SendMessage рдХреЗ рдЕрдВрджрд░ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рдЕрдбрд╝рдЪрди рдХреА рдирдХрд▓ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред

рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдмрд░реНрд╕ рдХреА рд▓рд┐рд╕реНрдЯ рдХреЛ рдХреЙрдкреА рдХрд░рдХреЗ рдлрдВрдХреНрд╢рди рдореЗрдВ рдЯреНрд░рд╛рдВрд╕рдлрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ Subscribe / Unsubscribe рдпрд╣ рд▓реЙрдХ-рдлреНрд░реА рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреА рддрдХрдиреАрдХ рдХреЗ рд╕рдорд╛рди рд╣реЛрдЧрд╛ред

CDispatcher рдСрдмреНрдЬреЗрдХреНрдЯ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рд╕реВрдЪреА рдХреЛ рд╕реАрдзреЗ рд╕реНрдЯреЛрд░ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдПрдХ рд╕реНрдорд╛рд░реНрдЯ рдкреЙрдЗрдВрдЯрд░ рдХреЗ рд╕рд╛рдеред SendMessage рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░, рд╣рдореЗрдВ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рд╡рд░реНрддрдорд╛рди рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдХреЗрддрдХ рдорд┐рд▓реЗрдЧрд╛ рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм / рдЕрдирд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ, рд╣рд░ рдмрд╛рд░ рд╣рдо рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рдПрдХ рдирдИ рд╕реВрдЪреА рдмрдирд╛рдПрдВрдЧреЗ рдФрд░ CDispatcher рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдЕрдВрджрд░ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рдирдИ рд╕реВрдЪреА рдореЗрдВ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░реЗрдВрдЧреЗред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЬрдмрдХрд┐ CDispatcher рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдмрд░ рдХреА рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП рд╕реВрдЪрдХ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рдирдИ рд╕реВрдЪреА рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ, SendMessage рдлрд╝рдВрдХреНрд╢рди рдЕрднреА рднреА рдкреБрд░рд╛рдиреА рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рдЪреВрдВрдХрд┐ рдХреЛрдИ рднреА рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рдкреБрд░рд╛рдиреА рд╕реВрдЪреА рдХреЛ рдирд╣реАрдВ рдмрджрд▓рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕рдм рдХреБрдЫ рдПрдХ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред

рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдЖрдк рд╕рджрд╕реНрдпрддрд╛ / рдЕрдирд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдереЛрдбрд╝рд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд▓реЙрдХ-рдореБрдХреНрдд рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рдФрд░ рд╡рд┐рд╖рдп рд╣реИред

рдЕрдирд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рд╣рдиреАрдЯ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╣реИ рдФрд░ рдореЗрд▓рд┐рдВрдЧ рдХреЗ рдкреВрд░реНрдг рд╕рдорд╛рдкреНрддрд┐ рдХреЗ рдмрд╛рдж рдЗрд╕рдХреА рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ, рдПрдХ рдЖрдзрд╛ рд╕рдорд╛рдзрд╛рди - рдЧреНрд░рд╛рд╣рдХ рдЕрдирд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдмреНрдбрд╣реИрдВрдбрд▓рд░ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рджрд╕реНрдпрддрд╛ рд░рджреНрдж рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд╕реВрдЪрдирд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдордзреНрдпрд╡рд░реНрддреА рд╡рд░реНрдЧ CSubscriberItem рдХреЛ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рдЗрд╕рдХреЗ рд╡рд┐рдирд╛рд╢рдХрд░реНрддрд╛ рдореЗрдВ рдЕрдирд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдмреНрдбрд╣реИрдВрдбрд▓рд░ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред

 namespace Observer { ////////////////////////// // Subscriber ////////////////////////// typedef unsigned __int64 SubscriberId; class CSubscriber { public: virtual ~CSubscriber(){} virtual void MessageHandler(void* pContext) = 0; virtual void UnsubscribeHandler() = 0; SubscriberId GetSubscriberId() {return (SubscriberId)this;} }; typedef boost::shared_ptr<CSubscriber> CSubscriberPtr; ////////////////////////////////////////////////////////////////////// // Dispatcher /////////////////////////////////// class CDispatcher { private: class CSubscriberItem { public: CSubscriberItem(CSubscriberPtr pSubscriber) :m_pSubscriber(pSubscriber) { } ~CSubscriberItem() { m_pSubscriber->UnsubscribeHandler(); }; CSubscriberPtr Subscriber()const {return m_pSubscriber;} private: CSubscriberPtr m_pSubscriber; }; typedef boost::shared_ptr<CSubscriberItem> CSubscriberItemPtr; typedef std::vector<CSubscriberItemPtr> CSubscriberList; typedef boost::shared_ptr<CSubscriberList> CSubscriberListPtr; public: CDispatcher() { } private: CDispatcher(const CDispatcher&){} CDispatcher& operator=(const CDispatcher&){return *this;} public: SubscriberId Subscribe(CSubscriberPtr pNewSubscriber) { //Declaration of the next shared pointer before ScopeLocker //prevents release of subscribers from under lock CSubscriberListPtr pNewSubscriberList(new CSubscriberList()); //Enter to locked section CScopeLocker ScopeLocker(m_Lock); if(m_pSubscriberList) { //Copy existing subscribers pNewSubscriberList->assign(m_pSubscriberList->begin(), m_pSubscriberList->end()); } for(size_t i = 0; i < pNewSubscriberList->size(); ++i) { CSubscriberItemPtr pSubscriberItem = (*pNewSubscriberList)[i]; if(pSubscriberItem->Subscriber()->GetSubscriberId() == pNewSubscriber->GetSubscriberId()) { return 0; } } //Add new subscriber to new subscriber list pNewSubscriberList->push_back(CSubscriberItemPtr(new CSubscriberItem(pNewSubscriber))); //Exchange subscriber lists m_pSubscriberList = pNewSubscriberList; return pNewSubscriber->GetSubscriberId(); } bool Unsubscribe(SubscriberId id) { //Declaration of the next shared pointers before ScopeLocker //prevents release of subscribers from under lock CSubscriberItemPtr pSubscriberItemToRelease; CSubscriberListPtr pNewSubscriberList; //Enter to locked section CScopeLocker ScopeLocker(m_Lock); if(!m_pSubscriberList) { //No subscribers return false; } pNewSubscriberList = CSubscriberListPtr(new CSubscriberList()); for(size_t i = 0; i < m_pSubscriberList->size(); ++i) { CSubscriberItemPtr pSubscriberItem = (*m_pSubscriberList)[i]; if(pSubscriberItem->Subscriber()->GetSubscriberId() == id) { pSubscriberItemToRelease = pSubscriberItem; } else { pNewSubscriberList->push_back(pSubscriberItem); } } //Exchange subscriber lists m_pSubscriberList = pNewSubscriberList; if(!pSubscriberItemToRelease.get()) { return false; } return true; } void SendMessage(void* pContext) { CSubscriberListPtr pSubscriberList; { CScopeLocker ScopeLocker(m_Lock); if(!m_pSubscriberList) { //No subscribers return; } //Get shared pointer to an existing list of subscribers pSubscriberList = m_pSubscriberList; } //pSubscriberList pointer to copy of subscribers' list for(size_t i = 0; i < pSubscriberList->size(); ++i) { (*pSubscriberList)[i]->Subscriber()->MessageHandler(pContext); } } private: CSubscriberListPtr m_pSubscriberList; CLock m_Lock; }; }; //namespace Observer
      
      





рд╕рдВрджрд░реНрдн



рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рдмрдврд╝рд╛рд╡рд╛ рджреЗрдВ :: рд╕рд┐рдЧреНрдирд▓ 2 рд▓реЗрдЦ

рд╕реНрдорд╛рд░реНрдЯ рдкреНрд╡рд╛рдЗрдВрдЯреНрд╕ рдЬреЗрдл рдЕрд▓реНрдЬреАрд░рд┐рдпрд╛

рд╕рдВрд╕рд╛рдзрди рдкреНрд░рд╛рдкреНрддрд┐ рдкреНрд░рд╛рд░рдВрднрд┐рдХ (RAII) рд╡рд┐рдХрд┐рдкреАрдбрд┐рдпрд╛ рд╣реИ

рдЗрд╕ рд▓реЗрдЦ рдХреЗ рдкрд╣рд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдкрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ рдпрд╣рд╛рдБ рдкрд╛рдИ рдЬрд╛ рд╕рдХрддреА рд╣реИрдВред



All Articles