NCBI C++ ToolKit
event_handler.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef GUI_UTILS___EVENT_HANDLER__HPP
2 #define GUI_UTILS___EVENT_HANDLER__HPP
3 
4 /* $Id: event_handler.hpp 40286 2018-01-19 18:22:51Z katargir $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Authors: Vladimir Tereshkov, Andrey Yazhuk
30  *
31  * File Description:
32  * Endpoint or target for public event.
33  */
34 
35 /** @addtogroup GUI_UTILS
36 *
37 * @{
38 */
39 
40 #include <map>
41 #include <functional>
42 #include <corelib/ncbiexpt.hpp>
43 #include <corelib/ncbimtx.hpp>
44 
45 #include <gui/utils/event.hpp>
46 
48 class CEventHandler;
50 
52 
53 class CEvent;
54 
55 typedef int TCmdID;
56 
57 /// event handler
58 typedef void (CEventHandler::*FEventHandler) (CEvent *);
59 
60 ///////////////////////////////////////////////////////////////////////////////
61 /// Command map entry.
63 {
64  CEvent::EEventClass evt_class; /// message or command or update
65  CEvent::TEventTypeInfo type_info; /// Type Information
66  CEvent::TEventID id; /// Event ID (or ID range start)
67  CEvent::TEventID last_id; /// Envent ID range end
68  FEventHandler handler; /// pointer to command handler mapped to the Command ID
69 };
70 
71 
72 /// Command Map.
73 struct SEvtMap
74 {
75  const SEvtMap* base_map; /// pointer to command map of the base class
76  const SEvtMapEntry* entries; /// pointer to array of map entries
77 };
78 
79 
80 // MACRO for declaring and defining command maps
81 #define DECLARE_EVENT_MAP() \
82 private: \
83  static const SEvtMapEntry sm_EvtMapEntries[]; \
84 protected: \
85  static const SEvtMap sm_EvtMap; \
86  virtual const SEvtMap* GetEventMap() const
87 
88 /// Begins definition of Command Map for CEventHandler-derived class.
89 #define BEGIN_EVENT_MAP(thisClass, baseClass) \
90  const SEvtMap* thisClass::GetEventMap() const \
91  { return &thisClass::sm_EvtMap; } \
92  const SEvtMap thisClass::sm_EvtMap = \
93  { &baseClass::sm_EvtMap, &thisClass::sm_EvtMapEntries[0] }; \
94  const SEvtMapEntry thisClass::sm_EvtMapEntries[] = \
95  { \
96 
97 /// Ends definition of Command Map.
98 #define END_EVENT_MAP() \
99  { CEvent::eEvent_Message, typeid(void).name(), \
100  CEvent::eEvent_InvalidID, CEvent::eEvent_InvalidID, 0} \
101  };
102 
103 #define ON_EVENT(type, id, handler) \
104 { ncbi::CEvent::eEvent_Message, typeid(type).name(), id, id, (FEventHandler) handler },
105 
106 #define ON_EVENT_RANGE(type, id, id_last, handler) \
107 { CEvent::eEvent_Message, typeid(type).name(), id, id_last, (FEventHandler) handler },
108 
109 
110 ///////////////////////////////////////////////////////////////////////////////
111 /// CEventHandler
112 ///
113 /// CEventHandler provides basic support for event handling. Event handling
114 /// includes processing events and dispatching events.
115 /// Processing involves recognizing an event of the particular type and invoking
116 /// a corresponding callback. CEventHandler provide support for mapping events
117 /// to callback by means of Event Maps (see macros in this file). A class can
118 /// define its own Event Map that can be inherited from the Event map of the
119 /// base class.
120 /// Dispatching is a process of forwarding an event to other CEventHandler-s
121 /// subscribed as listeners to the current handler. Dispatching algorithm can be
122 /// controlled by specifying a strategy (EDispatch enumeration).
123 /// All events are dispatched within pools. Pools are isolated networks of
124 /// listeners subscribed to each other. An event sent to a pool will reach only
125 /// listeners added to this particular pool, all other listeners will be ignored.
126 /// CEventHandler has several entry points:
127 /// OnEvent() processes an event, locates a callback corresponding to it
128 /// and executes the callback.
129 /// Dispatch() dispatches an event to listeners.
130 /// Send() synchronously handles events by calling OnEvent() and Dispatch().
131 /// Post() posts an event to the event queue. Events are retrieved from the
132 /// queue by HandlePostRequest() and then sent to the handler.
133 
134 
136 {
137 public:
138  /// enum controlling dispatching strategies
139  enum EDispatch {
140  eDispatch_SelfOnly, /// handle and do not dispatch to listeners
141  eDispatch_AllHandlers, /// dispatch to all handlers
142  eDispatch_FirstHandler, /// dispatch until handled at least by one handler
143 
144  eDispatch_Default = eDispatch_AllHandlers
145  };
146 
147  /// Identifiers for standard pools. Set of pools is extandable, programmers can
148  /// define their own pools but need to make sure that pool identifiers are unique.
149  enum EPoolName {
150  ePool_Default = 0,
154 
155  ePool_NextAvailable /// this needs to be last!
156  };
157 
158  typedef vector<CEventHandler*> TListeners;
159 
161  {
166  };
167 
169  typedef list< AutoPtr<SPostRequest> > TPostRequests;
170  typedef std::map<CEventHandler*, int> THandlerToCount;
171  typedef void (*FOnPostCallback)();
172 
173  CEventHandler();
174  virtual ~CEventHandler();
175 
176  /// @name Event Dispatching Interface
177  /// @{
178 
179  /// Add a listener. The listener will always be added to the default pool;
180  /// the 'name' parameter may be used to indicate an additional pool to which
181  // the listener is subscribed.
182  virtual void AddListener(CEventHandler* listener,
183  int pool_name = ePool_Default);
184 
185  /// Remove a listener. This will remove the listener from all pools in which
186  /// it exists.
187  virtual void RemoveListener(CEventHandler* listener);
188 
189  virtual void RemoveAllListeners(void);
190 
191  /// returns "true" if the given listener belongs to the specified pool
192  virtual bool HasListener(CEventHandler* listener,
193  int pool_name = ePool_Default) const;
194 
195  /// returns a set of listeners fro the specified pool
196  virtual const TListeners* GetListeners(int pool_name = ePool_Default) const;
197 
198  /// Processes en event. Returns "true" if event has been processed.
199  virtual bool OnEvent(CEvent * evt);
200 
201  /// Dispatches an event to the listeners (but does not handle it). Returns
202  /// "true" if event has been dispatched and handled by a listener.
203  virtual bool Dispatch(CEvent* evt,
204  EDispatch disp_how = eDispatch_Default,
205  int pool_name = ePool_Default);
206 
207  /// Sends an event synchronously. Returns "true" if event has been handled.
208  /// An event that is provided as the argument can be created on heap or stack.
209  virtual bool Send(CEvent* evt,
210  EDispatch disp_how = eDispatch_Default,
211  int pool_name = ePool_Default);
212  virtual bool Send(CEvent* evt, int pool_name);
213 
214  /// Handles an event asynchronously (process and/or dispatch). The event
215  /// will be posted to the event queue and then Post() will return, the event
216  /// will be processed at indefenite point in time after Post() returns.
217  /// The event must be created on heap and managed by CRef.
218  void Post(CRef<CEvent> evt,
219  EDispatch disp_how = eDispatch_Default,
220  int pool_name = ePool_Default);
221  /// @}
222 
223  /// @name Static API
224  /// @{
225  /// extracts the next request from the Post Queue and sends it to the target
226  /// returns true if the Queue is empty
227 
228  static bool HandlePostRequest();
229 
230  /// erases all events from the queue
231  static void ClearPostQueue();
232  static void DestroyPostQueue();
233 
234  /// @}
235 
236 protected:
238 
239  /// Removes itself unavailable for async event delivery.
240  void x_DeclareDead();
241 
242  void x_AddListenerToPool(CEventHandler* listener, int pool_name);
243 
244 protected:
246 
247 private:
248  /// CPostQueue - singleton queue for asynchronous events
249  /// all methods are synchronized
250  class CPostQueue : public CObject
251  {
252  public:
253  static CRef<CPostQueue> GetInstance(); /// returns Singleton
254  static void DestroyInstance(); /// destroys singleton
255 
256  ~CPostQueue();
257 
258  void Post(SPostRequest* req);
259  bool ExecuteFirstRequest();
260 
261  void DeclareDead(CEventHandler* handler);
262  void Clear();
263 
264  private:
265  static CRef<CPostQueue> sm_PostQueue; /// the only instance
266 
267  /// contains pointer to "alive" event targets and number of events for every target.
268  /// When target is destroyed it must remove itself from this map.
270 
271  TPostRequests m_Queue; /// queue of Events for async sending
272  CMutex m_Mutex; /// mutex guarding the sm_PostQueue and sm
273  };
274 
275 private:
276  CRef<CPostQueue> m_Queue; /// a reference to the singleton (to make sure that
277  /// the queue will not be destroyed until the Last handler is destroyed
278 };
279 
280 
282 
283 /* @} */
284 
285 #endif // GUI_UTILS___EVENT_HANDLER__HPP
CPostQueue - singleton queue for asynchronous events all methods are synchronized.
CEventHandler.
CEvent - generic event implementation TODO TODO - Attachments.
Definition: event.hpp:86
CMutex –.
Definition: ncbimtx.hpp:749
CObject –.
Definition: ncbiobj.hpp:180
void(*)(CSeq_entry_Handle seh, IWorkbench *wb, const CSerialObject &obj) handler
CMutex m_Mutex
queue of Events for async sending
CEvent::EEventClass evt_class
vector< CEventHandler * > TListeners
Int4 TEventID
Definition: event.hpp:90
CEvent::TEventID last_id
Event ID (or ID range start)
FEventHandler handler
Envent ID range end.
const char * TEventTypeInfo
Definition: event.hpp:88
const SEvtMapEntry * entries
pointer to command map of the base class
CEvent::TEventID id
Type Information.
void(CEventHandler::* FEventHandler)(CEvent *)
event handler
CEvent::TEventTypeInfo type_info
message or command or update
const SEvtMap * base_map
std::map< CEventHandler *, int > THandlerToCount
EEventClass
default event classes
Definition: event.hpp:98
THandlerToCount m_AliveTargets
the only instance
EDispatch
enum controlling dispatching strategies
#define DECLARE_EVENT_MAP()
map< int, TListeners > TPools
int TCmdID
CRef< CPostQueue > m_Queue
static CRef< CPostQueue > sm_PostQueue
CPostQueue.
list< AutoPtr< SPostRequest > > TPostRequests
EPoolName
Identifiers for standard pools.
@ eDispatch_AllHandlers
handle and do not dispatch to listeners
@ eDispatch_FirstHandler
dispatch to all handlers
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define NCBI_GUIUTILS_EXPORT
Definition: gui_export.h:518
Defines NCBI C++ exception handling.
Multi-threading – mutexes; rw-locks; semaphore.
Command map entry.
Command Map.
Modified on Fri Dec 01 04:47:35 2023 by modify_doxy.py rev. 669887