RflySimSDK v3.08
RflySimSDK说明文档
载入中...
搜索中...
未找到
vrpn_Mutex.h
1#ifndef VRPN_MUTEX_H
2#define VRPN_MUTEX_H
3
4#include <stddef.h> // for NULL
5
6#include "vrpn_Configure.h" // for VRPN_CALLBACK, VRPN_API
7#include "vrpn_Types.h" // for vrpn_int32, vrpn_uint32, etc
8
9class VRPN_API vrpn_Connection;
11// Every time a Mutex_Remote connects to a Mutex_Server, the server assigns
12// a unique ID to the remote.
13// HACK - because vrpn doesn't let us unicast within a multicast (multiple-
14// connection server) (in any clean way), or identify at a MC server which
15// connection a message came in over, this code is fragile - it depends
16// on the fact that vrpn_Connection only allows one connection to be made
17// before triggering the got_connection callback. If connections were somehow
18// batched, or we multithreaded vrpn_Connection, this would break.
19
20class VRPN_API vrpn_Mutex {
21
22public:
23 vrpn_Mutex(const char *name, vrpn_Connection * = NULL);
24 virtual ~vrpn_Mutex(void) = 0;
25
26 void mainloop(void);
27
28protected:
29 vrpn_Connection *d_connection;
30
31 vrpn_int32 d_myId;
32 vrpn_int32 d_requestIndex_type;
33 vrpn_int32 d_requestMutex_type;
34 vrpn_int32 d_release_type;
35 vrpn_int32 d_releaseNotification_type;
36 vrpn_int32 d_grantRequest_type;
37 vrpn_int32 d_denyRequest_type;
38 vrpn_int32 d_initialize_type;
39
40 void sendRequest(vrpn_int32 index);
41 void sendRelease(void);
42 void sendReleaseNotification(void);
43 void sendGrantRequest(vrpn_int32 index);
44 void sendDenyRequest(vrpn_int32 index);
45};
46
47class VRPN_API vrpn_Mutex_Server : public vrpn_Mutex {
48
49public:
50 vrpn_Mutex_Server(const char *name, vrpn_Connection * = NULL);
51 virtual ~vrpn_Mutex_Server(void);
52
53protected:
54 enum state { HELD, FREE };
55
56 state d_state;
57
58 vrpn_int32 d_remoteIndex;
59 ///< Counts remotes who have had IDs issued to them.
60
61 static int VRPN_CALLBACK handle_requestIndex(void *, vrpn_HANDLERPARAM);
62 static int VRPN_CALLBACK handle_requestMutex(void *, vrpn_HANDLERPARAM);
63 static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM);
64
65 static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM);
66 static int VRPN_CALLBACK
67 handle_dropLastConnection(void *, vrpn_HANDLERPARAM);
68};
69
70class VRPN_API vrpn_Mutex_Remote : public vrpn_Mutex {
71
72public:
73 vrpn_Mutex_Remote(const char *name, vrpn_Connection * = NULL);
74 virtual ~vrpn_Mutex_Remote(void);
75
76 // ACCESSORS
77
78 vrpn_bool isAvailable(void) const;
79 ///< True from when release() is called or we receive a release
80 ///< message from another process until request() is called or we
81 ///< grant the lock to another process in response to its request
82 ///< message.
83 vrpn_bool isHeldLocally(void) const;
84 ///< True from when RequestGranted callbacks are triggered until
85 ///< release() is called.
86 vrpn_bool isHeldRemotely(void) const;
87 ///< True from when we grant the lock to another process in response
88 ///< to its request message until we receive a release message from
89 ///< another process.
90
91 // MANIPULATORS
92
93 void request(void);
94 ///< Request the distributed lock. Does not request the lock
95 ///< if !isAvailable(), instead automatically triggering DeniedCallbacks.
96
97 void release(void);
98 ///< Release the distributed lock. Does nothing if !isHeldLocally()
99 ///< and there isn't a request pending.
100
101 vrpn_bool addRequestGrantedCallback(void *userdata, int (*)(void *));
102 ///< These callbacks are triggered when OUR request is granted.
103 vrpn_bool addRequestDeniedCallback(void *userdata, int (*)(void *));
104 ///< These callbacks are triggered when OUR request is denied.
105 vrpn_bool addTakeCallback(void *userdata, int (*)(void *));
106 ///< These callbacks are triggered when ANY peer gets the mutex.
107 vrpn_bool addReleaseCallback(void *userdata, int (*)(void *));
108 ///< These callbacks are triggered when ANY peer releases the
109 ///< mutex.
110
111protected:
112 void requestIndex(void);
113
114 enum state { OURS, REQUESTING, AVAILABLE, HELD_REMOTELY };
115
116 state d_state;
117 vrpn_int32 d_myIndex;
118 vrpn_bool d_requestBeforeInit;
119
120 static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM);
121 static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM);
122 static int VRPN_CALLBACK
123 handle_releaseNotification(void *, vrpn_HANDLERPARAM);
124
125 static int VRPN_CALLBACK handle_initialize(void *, vrpn_HANDLERPARAM);
126
127 static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM);
128
129 void triggerGrantCallbacks(void);
130 void triggerDenyCallbacks(void);
131 void triggerTakeCallbacks(void);
132 void triggerReleaseCallbacks(void);
133
135 int (*f)(void *);
136 void *userdata;
137 mutexCallback *next;
138 };
139
140 mutexCallback *d_reqGrantedCB;
141 mutexCallback *d_reqDeniedCB;
142 mutexCallback *d_takeCB;
143 mutexCallback *d_releaseCB;
144};
145
146/// vrpn_PeerMutex
147///
148/// This class provides distributed mutual exclusion between every instance
149/// with the same name for which addPeer() has been called.
150/// If a process calls request() when isAvailable() returns true,
151/// the mutex will attempt to secure a lock to whatever resource it is
152/// governing; either RequestGranted or RequestDenied callbacks will
153/// be triggered. If RequestGranted callbacks are triggered, the process
154/// has the lock until it explicitly calls release() (and can verify this
155/// by checking isHeldLocally()). Once the lock-owner calls release(),
156/// Release callbacks at every peer will be triggered.
157///
158/// Like most vrpn classes, the mainloop() must be called frequently.
159///
160/// Note that none of isAvailable(), isHeldLocally(), and isHeldRemotely()
161/// are true between when request() is called and either RequestGranted or
162/// RequestDenied callbacks are triggered.
163
164// Known bugs -
165
166// The constructor that takes a Connection as an argument will incorrectly
167// identify its IP address as the machine's default rather than the address
168// used by the Connection. This should not cause any errors in the protocol,
169// but will bias the tiebreaking algorithm. The same constructor will use
170// the wrong port number; without this information the tiebreaking algorithm
171// fails. Oops. Use only one mutex per Connection for now.
172
173// Possible bugs -
174
175// If on startup somebody else is holding the mutex we'll think it's
176// available. However, if we request it they'll deny it to us and
177// we won't break.
178// If sites don't execute the same set of addPeer() commands, they may
179// implicitly partition the network and not get true mutual exclusion.
180// This could be fixed by sending an addPeer message.
181// If sites execute addPeer() while the lock is held, or being requested,
182// we'll break.
183// - To fix: send messages, but defer all executions of addPeer until the
184// lock is released. If we want to be really careful here, on getting an
185// addPeer message when we think the lock is available we should request
186// the lock and then (if we get it) release it immediately, without
187// triggering any user callbacks. Sounds tough to code?
188
189// Handling more than 2 sites in a mutex requires multiconnection servers.
190// It's been tested with 1-3 sites, and works fine.
191
192// This is an O(n^2) network traffic implementation;
193// for details (and how to fix if it ever becomes a problem),
194// see the implementation notes in vrpn_Mutex.C.
195
196class VRPN_API vrpn_PeerMutex {
197
198public:
199 vrpn_PeerMutex(const char *name, int port, const char *NICaddress = NULL);
200 ///< This constructor opens a new connection/port for the mutex.
201
203 ///< If isHeldLocally(), calls release().
204
205 // ACCESSORS
206
207 vrpn_bool isAvailable(void) const;
208 ///< True from when release() is called or we receive a release
209 ///< message from another process until request() is called or we
210 ///< grant the lock to another process in response to its request
211 ///< message.
212 vrpn_bool isHeldLocally(void) const;
213 ///< True from when RequestGranted callbacks are triggered until
214 ///< release() is called.
215 vrpn_bool isHeldRemotely(void) const;
216 ///< True from when we grant the lock to another process in response
217 ///< to its request message until we receive a release message from
218 ///< another process.
219
220 int numPeers(void) const;
221
222 // MANIPULATORS
223
224 void mainloop(void);
225
226 void request(void);
227 ///< Request the distributed lock. Does not request the lock
228 ///< if !isAvailable(), instead automatically triggering DeniedCallbacks.
229
230 void release(void);
231 ///< Release the distributed lock. Does nothing if !isHeldLocally()
232 ///< and there isn't a request pending.
233
234 vrpn_bool addPeer(const char *stationName);
235 ///< Takes a VRPN station name of the form "<host>:<port>".
236
237 vrpn_bool addRequestGrantedCallback(void *userdata, int (*)(void *));
238 ///< These callbacks are triggered when OUR request is granted.
239 vrpn_bool addRequestDeniedCallback(void *userdata, int (*)(void *));
240 ///< These callbacks are triggered when OUR request is denied.
241 vrpn_bool addTakeCallback(void *userdata, int (*)(void *));
242 ///< These callbacks are triggered when ANY peer gets the mutex.
243 ///< (If several peers are competing for the mutex, and the
244 ///< implementation issues multiple "grants", these callbacks will
245 ///< only be triggered once between triggerings of ReleaseCallbacks.)
246 vrpn_bool addReleaseCallback(void *userdata, int (*)(void *));
247 ///< These callbacks are triggered when ANY peer releases the
248 ///< mutex.
249
250protected:
251 enum state { OURS, REQUESTING, AVAILABLE, HELD_REMOTELY };
252
253 char *d_mutexName;
254
255 state d_state;
256
258 ///< Counts the number of "grants" we've received after issuing
259 ///< a request; when this reaches d_numPeers, the lock is ours.
260
262 ///< Receive on this connection.
264 ///< Send on these connections to other Mutex's well-known-ports.
265
266 int d_numPeers;
268 ///< Dynamic array size for d_peer and d_peerGrantedLock.
269
270 vrpn_uint32 d_myIP;
271 vrpn_uint32 d_myPort;
272 vrpn_uint32 d_holderIP;
273 vrpn_int32 d_holderPort;
274
275 vrpn_int32 d_myId;
276 vrpn_int32 d_request_type;
277 vrpn_int32 d_release_type;
278 vrpn_int32 d_grantRequest_type;
279 vrpn_int32 d_denyRequest_type;
280 // vrpn_int32 d_losePeer_type;
281
282 static int VRPN_CALLBACK handle_request(void *, vrpn_HANDLERPARAM);
283 static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM);
284 static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM);
285 static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM);
286
287 static int VRPN_CALLBACK handle_losePeer(void *, vrpn_HANDLERPARAM);
288
289 void sendRequest(vrpn_Connection *);
290 void sendRelease(vrpn_Connection *);
291 void sendGrantRequest(vrpn_Connection *, vrpn_uint32 IPnumber,
292 vrpn_uint32 PortNumber);
293 void sendDenyRequest(vrpn_Connection *, vrpn_uint32 IPnumber,
294 vrpn_uint32 PortNumber);
295
296 void triggerGrantCallbacks(void);
297 void triggerDenyCallbacks(void);
298 void triggerTakeCallbacks(void);
299 void triggerReleaseCallbacks(void);
300
301 void checkGrantMutex(void);
302
303 void init(const char *name);
304
306 int (*f)(void *);
307 void *userdata;
308 mutexCallback *next;
309 };
310
311 mutexCallback *d_reqGrantedCB;
312 mutexCallback *d_reqDeniedCB;
313 mutexCallback *d_takeCB;
314 mutexCallback *d_releaseCB;
315
316 struct peerData {
317 vrpn_uint32 IPaddress;
318 vrpn_uint32 port;
319 vrpn_bool grantedLock;
320 };
321
323 ///< Needed only to clean up when a peer shuts down (mid-request).
324 ///< It isn't currently feasible to have all this data, so instead
325 ///< we abort requests that were interrupted by a shutdown.
326
327 vrpn_PeerMutex(const char *name, vrpn_Connection *c);
328 ///< This constructor reuses a SERVER connection for the mutex.
329 ///< BUG BUG BUG - do not use this constructor; it does not reliably
330 ///< resolve race conditions.
331};
332
333#endif // VRPN_MUTEX_H
Generic connection class not specific to the transport mechanism.
定义 vrpn_Connection.h:562
定义 vrpn_Mutex.h:70
void release(void)
vrpn_bool isAvailable(void) const
vrpn_bool isHeldLocally(void) const
void request(void)
vrpn_bool addTakeCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer gets the mutex.
vrpn_bool isHeldRemotely(void) const
vrpn_bool addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
vrpn_bool addReleaseCallback(void *userdata, int(*)(void *))
vrpn_bool addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
定义 vrpn_Mutex.h:47
vrpn_int32 d_remoteIndex
Counts remotes who have had IDs issued to them.
定义 vrpn_Mutex.h:58
定义 vrpn_Mutex.h:20
定义 vrpn_Mutex.h:196
void release(void)
vrpn_bool isAvailable(void) const
~vrpn_PeerMutex(void)
If isHeldLocally(), calls release().
int d_numConnectionsAllocated
Dynamic array size for d_peer and d_peerGrantedLock.
定义 vrpn_Mutex.h:267
vrpn_bool isHeldLocally(void) const
vrpn_PeerMutex(const char *name, vrpn_Connection *c)
vrpn_Connection * d_server
Receive on this connection.
定义 vrpn_Mutex.h:261
int d_numPeersGrantingLock
定义 vrpn_Mutex.h:257
vrpn_bool addPeer(const char *stationName)
Takes a VRPN station name of the form "<host>:<port>".
peerData * d_peerData
定义 vrpn_Mutex.h:322
void request(void)
vrpn_bool addTakeCallback(void *userdata, int(*)(void *))
vrpn_bool isHeldRemotely(void) const
vrpn_bool addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
vrpn_bool addReleaseCallback(void *userdata, int(*)(void *))
vrpn_bool addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
vrpn_Connection ** d_peer
Send on these connections to other Mutex's well-known-ports.
定义 vrpn_Mutex.h:263
vrpn_PeerMutex(const char *name, int port, const char *NICaddress=NULL)
This constructor opens a new connection/port for the mutex.
This structure is what is passed to a vrpn_Connection message callback.
定义 vrpn_Connection.h:41
定义 vrpn_Mutex.h:134
定义 vrpn_Mutex.h:305
定义 vrpn_Mutex.h:316