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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
|
/* -*- C++ -*- */
//=============================================================================
/**
* @file Token_Handler.h
*
* $Id$
*
* @author Douglas C. Schmidt (schmidt@cs.wustl.edu)
* Tim Harrison (harrison@cs.wustl.edu)
*/
//=============================================================================
#ifndef ACE_TOKEN_HANDLER_H
#define ACE_TOKEN_HANDLER_H
#include "ace/Acceptor.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
#include "ace/SOCK_Acceptor.h"
#include "ace/Local_Tokens.h"
#include "ace/Token_Collection.h"
#include "ace/Token_Request_Reply.h"
#include "ace/svc_export.h"
#if defined (ACE_HAS_TOKENS_LIBRARY)
/**
* @class ACE_Token_Handler
*
* @brief Product object created by an <ACE_Token_Acceptor>. A
* <Token_Handler> exchanges messages with a <Token_Proxy> object
* on the client-side.
*
* This class is the main workhorse of the ACE Token service. It
* receives token operation requests from remote clients and turns
* them into calls on local tokens (acquire, release, renew, and
* remove). In OMG CORBA terms, it is an object adapter. It also
* schedules and handles timeouts that are used to support "timed
* waits." Clients used timed waits to bound the amount of time
* they block trying to get a token.
*/
class ACE_Svc_Export ACE_Token_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
{
public:
// = Initialization and termination.
/// Default constructor.
ACE_Token_Handler (ACE_Thread_Manager * = 0);
// = Accessor and mutator methods.
// = Remote operations "exported" to a client.
/**
* Try to acquire the token.
* Precondition: client *may* hold the token already (i.e.,
* supports recursive acquisitions).
*/
virtual int acquire (ACE_Token_Proxy *proxy);
/// Try to acquire the token.
virtual int try_acquire (ACE_Token_Proxy *proxy);
/// Release the token and allow the next client that is waiting to
/// proceed. Preconditions: client must hold the token.
virtual int release (ACE_Token_Proxy *proxy);
/// Yield the token if any clients are waiting, otherwise keep the
/// token. Preconditions: client must hold the token.
virtual int renew (ACE_Token_Proxy *proxy);
/**
* Remove the specified token from the Token_Map. Preconditions:
* ACE_Token must exist. @@ Any other preconditions, e.g., must
* client hold token, must there be no waiters, etc.?
*/
virtual int remove (ACE_Token_Proxy *proxy);
/// Called by TS_[Mutex,RLock,WLock] when we hold the mutex and
/// someone wants it.
void sleep_hook (void);
/// Called by TS_[Mutex,RLock,WLock] when we are waiting and acquire
/// the mutex.
void token_acquired (ACE_TPQ_Entry *);
protected:
// = Low level routines for framing requests, dispatching
// operations, and returning replies.
/// Our connection has been closed.
virtual int abandon (int send_error);
/// Receive, frame, and decode the client's request.
virtual int recv_request (void);
/// Dispatch the appropriate operation to handle the client's
/// request.
virtual int dispatch (void);
/// Create and send a reply to the client.
virtual int send_reply (ACE_UINT32 errnum);
// = Demultiplexing hooks.
/// Callback method invoked by the <ACE_Reactor> when client events
/// arrive.
virtual int handle_input (ACE_HANDLE);
// = Timer hook.
/// Enable clients to limit the amount of time they wait for a token.
virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg);
/// return a proxy for the calling client_id and token name.
ACE_Token_Proxy *get_proxy (void);
private:
/// Switches on the type of token_request_ and creates a new
/// Token_Proxy.
virtual ACE_Token_Proxy *create_proxy (void);
/// Keeps track of the synchronization options (i.e., the timeout
/// interval).
ACE_Synch_Options request_options_;
/// collection of the client's token proxies.
ACE_Token_Collection collection_;
/// ID returned by the Reactor that is used to kill registered timers
/// when a token operation times out.
long timeout_id_;
/// Cache request from the client.
ACE_Token_Request token_request_;
/// Cache reply to the client.
ACE_Token_Reply token_reply_;
};
// = DESCRIPTION of ACE_TS_* classes:
// When Tokens are released, waiting token proxies are notified
// when the releasing thread calls token_acquired on the waiting
// proxy. The Token Server specializes ACE_Token_Proxy to
// redefine the implementation of token_acquired. When
// token_acquired is called, the Token_Handler can then send the
// response back over the socket connection to unblock the
// client side.
// Since only the Token_Handler uses ACE_TS_Mutex, we've moved
// the definition to the .cpp file.
/**
* @class ACE_TS_Mutex
*
* @brief ACE_TS_Mutex -- ACE_*T*oken_*S*erver_Mutex
*/
class ACE_TS_Mutex : public ACE_Local_Mutex
{
public:
/// Creation.
ACE_TS_Mutex (const ACE_TCHAR *name,
ACE_Token_Handler *th);
protected:
/// Somebody wants our token!
virtual void sleep_hook (void);
/**
* We've been taken off the waiters list and given the token! Call
* the Token_Handler associated at construction, so it can tell the
* remote client.
*/
virtual void token_acquired (ACE_TPQ_Entry *);
/// Duplication.
ACE_TS_Mutex (const ACE_TS_Mutex &);
/// Return a deep copy.
virtual ACE_Token_Proxy *clone (void) const;
private:
/// The Token Handler associated with this proxy. Set at
/// construction and notified when blocking acquires succeed.
ACE_Token_Handler* th_;
};
/**
* @class ACE_TS_RLock
*
* @brief ACE_TS_RLock -- ACE_*T*oken_*S*erver_RLock
*/
class ACE_TS_RLock : public ACE_Local_RLock
{
public:
/// Creation.
ACE_TS_RLock (const ACE_TCHAR *name,
ACE_Token_Handler *th);
protected:
/// Somebody wants our token!
virtual void sleep_hook (void);
/**
* We've been taken off the waiters list and given the token! Call
* the Token_Handler associated at construction, so it can tell the
* remote client.
*/
virtual void token_acquired (ACE_TPQ_Entry *);
/// Duplication.
ACE_TS_RLock (const ACE_TS_RLock&);
/// Return a deep copy.
virtual ACE_Token_Proxy *clone (void) const;
private:
/// the Token Handler associated with this proxy. Set at
/// construction and notified when blocking acquires succeed.
ACE_Token_Handler* th_;
};
/**
* @class ACE_TS_WLock
*
* @brief ACE_TS_WLock -- ACE_*T*oken_*S*erver_WLock
*/
class ACE_TS_WLock : public ACE_Local_WLock
{
public:
/// Creation.
ACE_TS_WLock (const ACE_TCHAR *name,
ACE_Token_Handler *th);
protected:
/// Somebody wants our token!
virtual void sleep_hook (void);
/**
* We've been taken off the waiters list and given the token! Call
* the Token_Handler associated at construction, so it can tell the
* remote client.
*/
virtual void token_acquired (ACE_TPQ_Entry *);
/// Duplication.
ACE_TS_WLock (const ACE_TS_WLock&);
/// Return a deep copy.
virtual ACE_Token_Proxy *clone (void) const;
private:
/// the Token Handler associated with this proxy. Set at
/// construction and notified when blocking acquires succeed.
ACE_Token_Handler* th_;
};
/**
* @class ACE_Token_Acceptor
*
* @brief This class contains the service-specific methods that can't
* easily be factored into the <ACE_Strategy_Acceptor>.
*/
class ACE_Token_Acceptor : public ACE_Strategy_Acceptor<ACE_Token_Handler, ACE_SOCK_ACCEPTOR>
{
public:
/// Dynamic linking hook.
virtual int init (int argc, ACE_TCHAR *argv[]);
/// Parse svc.conf arguments.
int parse_args (int argc, ACE_TCHAR *argv[]);
private:
/// The scheduling strategy is designed for Reactive services.
ACE_Schedule_All_Reactive_Strategy<ACE_Token_Handler> scheduling_strategy_;
};
ACE_SVC_FACTORY_DECLARE (ACE_Token_Acceptor)
#endif /* ACE_HAS_TOKENS_LIBRARY */
#endif /* ACE_TOKEN_HANDLER_H */
|