1 // -*- c++ -*-
2 //---------------------------------------------------------------------------
3 // SigHandlersList.h
4 //------------------------------------------------------------------------------
5 // Copyright (c) 1997 by Vladislav Grinchenko
6 //
7 // Permission to use, copy, modify, and distribute this software
8 // and its documentation for any purpose and without fee is hereby
9 // granted, provided that the above copyright notice appear in all
10 // copies. The author makes no representations about the suitability
11 // of this software for any purpose. It is provided "as is" without
12 // express or implied warranty.
13 //---------------------------------------------------------------------------
14
15 #ifndef _SigHandlersList_h
16 #define _SigHandlersList_h
17
18 #include <signal.h>
19 #include <errno.h>
20 #include <sys/time.h>
21 #include <sys/types.h>
22
23 #include "assa/SigHandler.h"
24
25 #include <set>
26 using std::set;
27
28 namespace ASSA {
29
30 #if !defined(WIN32)
31
32 /** @file SigHandlersList.h
33
34 SigHandlersList is a Singleton class that maps signal number to a set of
35 EventHandlers listening for the delivery of the signal.
36 */
37
38 /** CFUNC_Handler class.
39
40 CFUNC_Handler is a wrapper around C signal handler function.
41 It wraps C signal handler function into EventHandler interface.
42 */
43
44 class CFUNC_Handler : public EventHandler
45 {
46 public:
47 CFUNC_Handler (C_SIG_HANDLER csigh_);
48
49 int handle_signal (int signum_);
handler()50 C_SIG_HANDLER handler () { return m_c_sig_hand; }
51
52 private:
53 C_SIG_HANDLER m_c_sig_hand;
54 };
55
56 /** SigHandlersList class.
57
58
59 SigHandlersList class is used by SigHandlers class to keep track of
60 EventHandlers installed to be called on signal's delivery. It is sort of
61 global process map of signal numbers into corresponding sets of
62 EventHandlers that are listening for signal delivery.
63 */
64
65 class SigHandlersList
66 {
67 public:
68 typedef EventHandler* key_type;
69 typedef EventHandler* data_type;
70
71 struct CompSHL {
operatorCompSHL72 bool operator () (const key_type c1_, const key_type c2_) const
73 {
74 // This wouldn't fly on 64-bit machines, 'cause ptr size there is 8 bytes long
75 // return int(c1_) < int(c2_);
76 //
77 return (c1_ < c2_);
78 }
79 };
80
81 typedef set< key_type, CompSHL > set_t;
82 typedef set< key_type, CompSHL >::iterator iterator;
83
84 /** Retrieve a pointer to the list of event handlers
85 listening to signum_ signal delivery.
86 */
87 static SigHandlersList* instance (int signum_);
88
89 /// Destructor
90 ~SigHandlersList ();
91
92 /// Is list empty
93 bool empty () const;
94
95 /// Size of the list
96 size_t size () const;
97
98 /** Add an event handler data_ to the list.
99 @return TRUE on success, FALSE on error.
100 */
101 bool insert (data_type data_);
102
103 /** Find and remove event handler key_ from the list.
104 */
105 void erase (const key_type key_);
106
107 /** Remove an event handler pointed by iterator it_
108 from the list.
109 */
110 void erase (iterator it_);
111
112 /** Empty event handlers' list.
113 */
114 void erase ();
115
116 /** Return an iterator pointing to the beginning of the list.
117 */
118 iterator begin ();
119
120 /** Return an iterator pointing to the end of the list.
121 */
122 iterator end ();
123
124 /** Find event handler by its pointer key_.
125 @return Iterator to the element.
126 */
127 iterator find (const key_type key_);
128
129 /** Save 3rd party C function handler to remember.
130 @param cfp_ New 3rd party C function handler. If it is NULL,
131 then seen_cfh flag is set to FALSE.
132 @return old 3rd party C function handler.
133 */
134 CFUNC_Handler* cfunc_handler (CFUNC_Handler* cfp_);
135
136 /** Retrieve pointer to 3rd party C function handler.
137 @return 3rd party C function handler.
138 */
139 CFUNC_Handler* cfunc_handler () const;
140
141 /** Indicate whether 3rd party C function handler was installed.
142 @param ft_ TRUE if was, FALSE if not.
143 */
144 void seen_cfunc_handler (bool ft_);
145
146 /** @return TRUE if we've seen 3rd party C function handler;
147 FALSE otherwise.
148 */
149 bool seen_cfunc_handler () const;
150
151 protected:
152 SigHandlersList (); // Singleton
153 SigHandlersList (const SigHandlersList& map_); // prohibit copying
154 SigHandlersList& operator= (const SigHandlersList& map_);
155
156 public:
157 /** Static map of signal numbers to SigHandlerLists.
158 */
159 static SigHandlersList* m_instance[NSIG];
160
161 private:
162 /// Set of all event handlers registered for this signal.
163 set_t* m_set;
164
165 /** If true this flag indicates that 3rd party event handler
166 has already been installed prior taking control by SigHandlers
167 manager.
168 */
169 int m_seen_cfh;
170
171 /** Pointer to the 3rd party signal handler in the set
172 */
173 CFUNC_Handler* m_cfhp;
174 };
175
176 //-------------------------------------------------------------------------
177 //----------------------- SigHandlersList Inlines -------------------------
178 //-------------------------------------------------------------------------
179
180 inline
181 SigHandlersList::
SigHandlersList()182 SigHandlersList ()
183 : m_seen_cfh (false), m_cfhp (NULL)
184 {
185 trace_with_mask("SigHandlersList::SigHandlersList", SIGHAND);
186
187 m_set = new set_t;
188 }
189
190 inline
191 SigHandlersList::
~SigHandlersList()192 ~SigHandlersList ()
193 {
194 trace_with_mask("SigHandlersList::~SigHandlersList", SIGHAND);
195
196 erase ();
197 delete m_set;
198 m_set = NULL;
199 }
200
201 inline SigHandlersList*
202 SigHandlersList::
instance(int signum_)203 instance (int signum_)
204 {
205 trace_with_mask("SigHandlersList::instance", SIGHAND);
206
207 DL((APP, "m_instance[%d] = 0x%x\n", signum_,
208 SigHandlersList::m_instance[signum_]));
209
210 if (SigHandlersList::m_instance[signum_] == 0) {
211 DL((APP, "new SigHandlersList allocated\n"));
212 SigHandlersList::m_instance[signum_] = new SigHandlersList();
213 }
214 return SigHandlersList::m_instance[signum_];
215 }
216
217 inline bool
218 SigHandlersList::
empty()219 empty () const
220 {
221 trace_with_mask("SigHandlersList::empty", SIGHAND);
222
223 // true if map is empty, false otherwise
224
225 return m_set->empty ();
226 }
227
228 inline size_t
229 SigHandlersList::
size()230 size () const
231 {
232 trace_with_mask("SigHandlersList::size", SIGHAND);
233
234 // return number of elements in the map
235
236 return m_set->size ();
237 }
238
239 inline bool
240 SigHandlersList::
insert(data_type eh_)241 insert (data_type eh_)
242 {
243 trace_with_mask("SigHandlersList::insert", SIGHAND);
244
245 /*---
246 Insert 'eh_' into the set. set::insert() returns a 'pair' object.
247
248 If the set doesn't contain an element that matches 'eh_', insert a
249 copy of 'eh_' and returns a 'pair' whose first element is an
250 iterator positioned at the new element and second element is
251 'true'.
252
253 If the set already contains an element that matches 'eh_', returns
254 a pair whose first element is an iterator positioned at the
255 existing element and second element is false!
256 ---*/
257
258 set_t::const_iterator it = m_set->find (eh_);
259
260 /*--- Not in the set ---*/
261 if (it == m_set->end ()) {
262 return (m_set->insert (eh_)).second;
263 }
264 /*--- Already in the set ---*/
265 return true;
266 }
267
268 inline void
269 SigHandlersList::
erase(const key_type key_)270 erase (const key_type key_)
271 {
272 // return number of erased elements
273 trace_with_mask("SigHandlersList::erase(key_)", SIGHAND);
274
275 m_set->erase (key_);
276 }
277
278 inline void
279 SigHandlersList::
erase()280 erase ()
281 {
282 // empty the map
283 trace_with_mask("SigHandlersList::erase(void)", SIGHAND);
284
285 m_set->erase (m_set->begin(), m_set->end());
286 }
287
288 inline void
289 SigHandlersList::
erase(iterator it_)290 erase(iterator it_)
291 {
292 // erase element pointed by iterator
293 trace_with_mask("SigHandlersList::erase(it_)", SIGHAND);
294
295 m_set->erase(it_);
296 }
297
298 inline SigHandlersList::iterator
299 SigHandlersList::
begin()300 begin ()
301 {
302 trace_with_mask("SigHandlersList::begin()", SIGHAND);
303
304 return m_set->begin ();
305 }
306
307 inline SigHandlersList::iterator
308 SigHandlersList::
end()309 end ()
310 {
311 trace_with_mask("SigHandlersList::end", SIGHAND);
312
313 return m_set->end ();
314 }
315
316 inline SigHandlersList::iterator
317 SigHandlersList::
find(const key_type key_)318 find (const key_type key_)
319 {
320 trace_with_mask("SigHandlersList::find", SIGHAND);
321
322 return m_set->find (key_);
323 }
324
325
326 inline CFUNC_Handler*
327 SigHandlersList::
cfunc_handler(CFUNC_Handler * cfhp_)328 cfunc_handler (CFUNC_Handler* cfhp_)
329 {
330 trace_with_mask("SigHandlersList::cfunc_handler", SIGHAND);
331
332 CFUNC_Handler* old_cfhp = m_cfhp;
333 m_cfhp = cfhp_;
334 m_seen_cfh = cfhp_ == NULL ? false : true;
335 return old_cfhp;
336 }
337
338 inline CFUNC_Handler*
339 SigHandlersList::
cfunc_handler()340 cfunc_handler () const
341 {
342 trace_with_mask("SigHandlersList::cfunc_handler", SIGHAND);
343
344 return m_cfhp;
345 }
346
347 inline void
348 SigHandlersList::
seen_cfunc_handler(bool ft_)349 seen_cfunc_handler (bool ft_)
350 {
351 trace_with_mask("SigHandlersList::seen_cfunc_handler", SIGHAND);
352
353 m_seen_cfh = ft_;
354 }
355
356 inline bool
357 SigHandlersList::
seen_cfunc_handler()358 seen_cfunc_handler () const
359 {
360 trace_with_mask("SigHandlersList::seen_cfunc_handler", SIGHAND);
361
362 return m_seen_cfh;
363 }
364
365 //-------------------------------------------------------------------------
366 //------------------------ CFUNC_Handler Inlines --------------------------
367 //-------------------------------------------------------------------------
368
369 inline
370 CFUNC_Handler::
CFUNC_Handler(C_SIG_HANDLER csigh_)371 CFUNC_Handler (C_SIG_HANDLER csigh_)
372 : m_c_sig_hand (csigh_)
373 {
374 trace_with_mask("CFUNC_Handler::CFUNC_Handler", SIGHAND);
375 }
376
377 inline int
378 CFUNC_Handler::
handle_signal(int signum_)379 handle_signal (int signum_)
380 {
381 trace_with_mask("CFUNC_Handler::handle_signal", SIGHAND);
382
383 if (m_c_sig_hand) {
384 (*m_c_sig_hand)(signum_);
385 }
386 return 1;
387 }
388
389 #endif // !defined(WIN32)
390
391 } // end namespace ASSA
392
393 #endif /* _SigHandlersList_h */
394
395