summaryrefslogtreecommitdiff
path: root/ace/Event_Handler_T.h
blob: 4f2d10f3df888eb979276463aef238654c757c84 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/* -*- C++ -*- */

//=============================================================================
/**
 *  @file    Event_Handler_T.h
 *
 *  $Id$
 *
 *  @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
 */
//=============================================================================

#ifndef ACE_EVENT_HANDLER_T_H
#define ACE_EVENT_HANDLER_T_H
#include /**/ "ace/pre.h"

#include "ace/Event_Handler.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)

/**
 * @class ACE_Event_Handler_T
 *
 * @brief Enable a class that doesn't inherit from the
 * ACE_Event_Handler to be incorporated into the ACE_Reactor
 * framework.  Thanks to Greg Lavender (g.lavender@isode.com)
 * for sharing this idea.
 *
 * It is sometimes the case that an application has a hierarchy
 * of operation dispatcher classes that have their own
 * inheritance hierarchy but also would like to integrate with
 * the ACE_Reactor.  Rather than adopt a "mixin" approach, it is
 * often cleaner to define a template as a subclass of
 * ACE_Event_Handler and paramterize it with an operation
 * dispatcher type.
 * When constructing an instantiation of the ACE_Event_Handler_T
 * object, a set of pointers to member functions must be
 * provided so that when one of the handle_* methods is called
 * by the ACE_Reactor, the appropriate method is called on the
 * underlying operations object.  This is done since in some
 * cases it is useful to map any event that happens to the same
 * method on an object.
 * The ACE_Event_Handler_T template is instantiated by an
 * operations object and registered with the ACE_Reactor, and it
 * then calls the appropriate op_handler.  So, it's basically
 * just another level of indirection in event dispatching. The
 * coupling betweent the ultimate handler of the event and the
 * ACE_Event_Handler class is relaxed a bit by have this
 * intermediate <op_handler_> object of type <T> around. The
 * client object can then dynamically change the bindings for
 * the various handlers so that during the life of one of the
 * operation objects, it can change how it wants events to be
 * handled. It just instantiates a new instance of the template
 * with different bindings and reregisters this new object with
 * the ACE_Reactor.
 */
template <class T>
class ACE_Event_Handler_T : public ACE_Event_Handler
{
public:
  // = Typedefs to simplify pointer-to-member-function registration.

  // Get/set the underlying handle.
  typedef ACE_HANDLE (T::*GET_HANDLE) (void) const;
  typedef void (T::*SET_HANDLE) (ACE_HANDLE);

  /// Handle I/O events.
  typedef int (T::*IO_HANDLER) (ACE_HANDLE);

  /// Handle timeout events.
  typedef int (T::*TO_HANDLER) (const ACE_Time_Value &, const void *);

  /// Handle close events.
  typedef int (T::*CL_HANDLER) (ACE_HANDLE, ACE_Reactor_Mask);

  /// = Initialization and termination methods.
  typedef int (T::*SIG_HANDLER) (int, siginfo_t*, ucontext_t*);

  /// Initialize the op_handler.
  ACE_Event_Handler_T (T *op_handler,
                       int delete_handler,
                       GET_HANDLE get_handle = 0,
                       IO_HANDLER input = 0,
                       CL_HANDLER close = 0,
                       SIG_HANDLER sig = 0,
                       TO_HANDLER timeout = 0,
                       IO_HANDLER output = 0,
                       SET_HANDLE set_handle = 0,
                       IO_HANDLER except = 0);

  /// Close down and delete the <op_handler>
  ~ACE_Event_Handler_T (void);

  // = Override all the ACE_Event_Handler methods.

  // These methods all delegate down to the <T> operations handler.
  virtual ACE_HANDLE get_handle (void) const;
  virtual void set_handle (ACE_HANDLE);
  virtual int handle_input (ACE_HANDLE fd = -1);
  virtual int handle_output (ACE_HANDLE fd = -1);
  virtual int handle_exception (ACE_HANDLE fd = -1);
  virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg = 0);
  virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask close_mask);
  virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);

  // = Get/set the operations handler.
  T *op_handler (void);
  void op_handler (T *);

  // = Get/set the target pointer-to-method used for dispatching.

  GET_HANDLE handle_get (void);
  void handle_get (GET_HANDLE);

  SET_HANDLE handle_set (void);
  void handle_set (SET_HANDLE);

  IO_HANDLER input_handler (void);
  void input_handler (IO_HANDLER);

  IO_HANDLER output_handler (void);
  void output_handler (IO_HANDLER);

  IO_HANDLER except_handler (void);
  void except_handler (IO_HANDLER);

  TO_HANDLER to_handler (void);
  void to_handler (TO_HANDLER);

  CL_HANDLER cl_handler (void);
  void cl_handler (CL_HANDLER);

  SIG_HANDLER sig_handler (void);
  void sig_handler (SIG_HANDLER);

  /// Dump the state of an object.
  void dump (void) const;

  /// Declare the dynamic allocation hooks.
  ACE_ALLOC_HOOK_DECLARE;

protected:
  /// Pointer to the object that handles all the delegated operations.
  T *op_handler_;

  // = Handle input, output, and exception events.
  IO_HANDLER input_handler_;
  IO_HANDLER output_handler_;
  IO_HANDLER except_handler_;

  /// Handle timeout events.
  TO_HANDLER to_handler_;

  /// Handle close events.
  CL_HANDLER cl_handler_;

  /// Handle signal events.
  SIG_HANDLER sig_handler_;

  /// Keeps track of whether we need to delete the handler in the
  /// destructor.
  int delete_handler_;

  // = Get/set underlying handle.
  SET_HANDLE set_handle_;
  GET_HANDLE get_handle_;
};

#if defined (__ACE_INLINE__)
#include "ace/Event_Handler_T.inl"
#endif /* __ACE_INLINE__ */

#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
#include "ace/Event_Handler_T.cpp"
#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */

#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
#pragma implementation ("Event_Handler_T.cpp")
#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */

#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
#include /**/ "ace/post.h"
#endif /* ACE_EVENT_HANDLER_H */