vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Mutex.h
Go to the documentation of this file.
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 
10 struct vrpn_HANDLERPARAM;
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 
21 
22 public:
23  vrpn_Mutex(const char *name, vrpn_Connection * = NULL);
24  virtual ~vrpn_Mutex(void) = 0;
25 
26  void mainloop(void);
27 
28 protected:
30 
31  vrpn_int32 d_myId;
32  vrpn_int32 d_requestIndex_type;
33  vrpn_int32 d_requestMutex_type;
34  vrpn_int32 d_release_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 
48 
49 public:
50  vrpn_Mutex_Server(const char *name, vrpn_Connection * = NULL);
51  virtual ~vrpn_Mutex_Server(void);
52 
53 protected:
54  enum state { HELD, FREE };
55 
57 
58  vrpn_int32 d_remoteIndex;
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 
71 
72 public:
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;
83  vrpn_bool isHeldLocally(void) const;
86  vrpn_bool isHeldRemotely(void) const;
90 
91  // MANIPULATORS
92 
93  void request(void);
96 
97  void release(void);
100 
101  void addRequestGrantedCallback(void *userdata, int (*)(void *));
103  void addRequestDeniedCallback(void *userdata, int (*)(void *));
105  void addTakeCallback(void *userdata, int (*)(void *));
107  void addReleaseCallback(void *userdata, int (*)(void *));
110 
111 protected:
112  void requestIndex(void);
113 
114  enum state { OURS, REQUESTING, AVAILABLE, HELD_REMOTELY };
115 
117  vrpn_int32 d_myIndex;
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 
134  struct mutexCallback {
135  int (*f)(void *);
136  void *userdata;
138  };
139 
144 };
145 
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 
197 
198 public:
199  vrpn_PeerMutex(const char *name, int port, const char *NICaddress = NULL);
201 
202  ~vrpn_PeerMutex(void);
204 
205  // ACCESSORS
206 
207  vrpn_bool isAvailable(void) const;
212  vrpn_bool isHeldLocally(void) const;
215  vrpn_bool isHeldRemotely(void) const;
219 
220  int numPeers(void) const;
221 
222  // MANIPULATORS
223 
224  void mainloop(void);
225 
226  void request(void);
229 
230  void release(void);
233 
234  void addPeer(const char *stationName);
236 
237  void addRequestGrantedCallback(void *userdata, int (*)(void *));
239  void addRequestDeniedCallback(void *userdata, int (*)(void *));
241  void addTakeCallback(void *userdata, int (*)(void *));
246  void addReleaseCallback(void *userdata, int (*)(void *));
249 
250 protected:
251  enum state { OURS, REQUESTING, AVAILABLE, HELD_REMOTELY };
252 
253  char *d_mutexName;
254 
256 
260 
265 
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;
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 
305  struct mutexCallback {
306  int (*f)(void *);
307  void *userdata;
309  };
310 
315 
316  struct peerData {
317  vrpn_uint32 IPaddress;
318  vrpn_uint32 port;
319  vrpn_bool grantedLock;
320  };
321 
326 
327  vrpn_PeerMutex(const char *name, vrpn_Connection *c);
331 };
332 
333 #endif // VRPN_MUTEX_H
vrpn_int32 d_holderPort
Definition: vrpn_Mutex.h:273
vrpn_int32 d_denyRequest_type
Definition: vrpn_Mutex.h:37
vrpn_int32 d_denyRequest_type
Definition: vrpn_Mutex.h:279
vrpn_uint32 d_myPort
Definition: vrpn_Mutex.h:271
vrpn_int32 d_request_type
Definition: vrpn_Mutex.h:276
vrpn_int32 d_myId
Definition: vrpn_Mutex.h:31
vrpn_int32 d_releaseNotification_type
Definition: vrpn_Mutex.h:35
mutexCallback * d_takeCB
Definition: vrpn_Mutex.h:142
vrpn_int32 d_requestMutex_type
Definition: vrpn_Mutex.h:33
mutexCallback * d_releaseCB
Definition: vrpn_Mutex.h:314
int d_numPeersGrantingLock
Counts the number of "grants" we&#39;ve received after issuing a request; when this reaches d_numPeers...
Definition: vrpn_Mutex.h:257
vrpn_uint32 d_myIP
Definition: vrpn_Mutex.h:270
mutexCallback * d_reqDeniedCB
Definition: vrpn_Mutex.h:312
vrpn_Connection * d_connection
Definition: vrpn_Mutex.h:29
Generic connection class not specific to the transport mechanism.
mutexCallback * d_takeCB
Definition: vrpn_Mutex.h:313
vrpn_int32 d_release_type
Definition: vrpn_Mutex.h:277
#define VRPN_CALLBACK
vrpn_bool d_requestBeforeInit
Definition: vrpn_Mutex.h:118
#define VRPN_API
vrpn_Connection ** d_peer
Send on these connections to other Mutex&#39;s well-known-ports.
Definition: vrpn_Mutex.h:263
vrpn_int32 d_initialize_type
Definition: vrpn_Mutex.h:38
This structure is what is passed to a vrpn_Connection message callback.
vrpn_int32 d_requestIndex_type
Definition: vrpn_Mutex.h:32
vrpn_uint32 d_holderIP
Definition: vrpn_Mutex.h:272
peerData * d_peerData
Needed only to clean up when a peer shuts down (mid-request). It isn&#39;t currently feasible to have all...
Definition: vrpn_Mutex.h:322
vrpn_PeerMutex
Definition: vrpn_Mutex.h:196
mutexCallback * d_reqDeniedCB
Definition: vrpn_Mutex.h:141
vrpn_int32 d_grantRequest_type
Definition: vrpn_Mutex.h:278
char * d_mutexName
Definition: vrpn_Mutex.h:253
vrpn_int32 d_myIndex
Definition: vrpn_Mutex.h:117
mutexCallback * d_reqGrantedCB
Definition: vrpn_Mutex.h:311
vrpn_int32 d_myId
Definition: vrpn_Mutex.h:275
vrpn_int32 d_release_type
Definition: vrpn_Mutex.h:34
mutexCallback * d_reqGrantedCB
Definition: vrpn_Mutex.h:140
vrpn_Connection * d_server
Receive on this connection.
Definition: vrpn_Mutex.h:261
vrpn_int32 d_grantRequest_type
Definition: vrpn_Mutex.h:36
mutexCallback * d_releaseCB
Definition: vrpn_Mutex.h:143
int d_numConnectionsAllocated
Dynamic array size for d_peer and d_peerGrantedLock.
Definition: vrpn_Mutex.h:267
vrpn_int32 d_remoteIndex
Counts remotes who have had IDs issued to them.
Definition: vrpn_Mutex.h:58