vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Mutex.C
Go to the documentation of this file.
1 #include <stdio.h> // for fprintf, stderr, sprintf
2 #include <string.h> // for NULL, memcpy, strlen, etc
3 
4 #include "vrpn_Connection.h" // for vrpn_Connection, etc
5 #include "vrpn_Mutex.h"
6 #include "vrpn_Shared.h" // for vrpn_buffer, vrpn_unbuffer, etc
7 
8 #ifndef VRPN_USE_WINSOCK_SOCKETS
9 #include <arpa/inet.h> // for inet_addr
10 #include <netdb.h> // for gethostbyname, hostent, etc
11 //#include <sys/socket.h>
12 #include <netinet/in.h> // for in_addr, ntohl, INADDR_NONE
13 #include <unistd.h> // for getpid, gethostname
14 #endif
15 
16 #ifdef _WIN32
17 #include <process.h> // for _getpid()
18 #endif
19 
20 #ifdef sparc
21 #define INADDR_NONE -1
22 #endif
23 
24 /*
25 
26  Server State diagram:
27 
28  handle_release()
29  +-------------------------+
30  | |
31  v |
32  handle_request()
33  FREE ------------------> HELD
34 
35  Peer State diagram:
36 
37  release()
38  +--------------------------------------------+
39  | |
40  v |
41  request()
42  AVAILABLE --------------> REQUESTING ----> OURS
43 
44  | ^ |
45  v | |
46  |
47  HELD_REMOTELY <---------------+
48 
49 */
50 
51 //#define VERBOSE
52 
53 // static const char * myID = "vrpn_Mutex";
54 static const char *requestIndex_type = "vrpn_Mutex Request Index";
55 static const char *requestMutex_type = "vrpn_Mutex Request Mutex";
56 static const char *release_type = "vrpn_Mutex Release";
57 static const char *releaseNotification_type = "vrpn_Mutex Release_Notification";
58 static const char *grantRequest_type = "vrpn_Mutex Grant_Request";
59 static const char *denyRequest_type = "vrpn_Mutex Deny_Request";
60 // static const char * losePeer_type = "vrpn_Mutex Lose_Peer";
61 static const char *initialize_type = "vrpn_Mutex Initialize";
62 
63 struct losePeerData {
64  vrpn_Connection *connection;
65  vrpn_PeerMutex *mutex;
66 };
67 
68 // Mostly copied from vrpn_Connection.C's vrpn_getmyIP() and some man pages.
69 // Should return in host order.
70 // Returns 0 on error.
71 static vrpn_uint32 getmyIP(const char *NICaddress = NULL)
72 {
73  struct hostent *host;
74  char myname[100];
75  in_addr in;
76  int retval;
77 
78  if (NICaddress) {
79  // First, see if NIC is specified as IP address.
80  // inet_addr() comes back in network order
81  in.s_addr = inet_addr(NICaddress);
82  if (in.s_addr != INADDR_NONE) {
83  return ntohl(in.s_addr);
84  }
85  // Second, try a name.
86  // gethostbyname() comes back in network order
87  host = gethostbyname(NICaddress);
88  if (host) {
89  memcpy(&in.s_addr, host->h_addr, host->h_length);
90  return ntohl(in.s_addr);
91  }
92 
93  fprintf(stderr, "getmyIP: Can't get host entry for %s.\n", NICaddress);
94  return 0;
95  }
96 
97  retval = gethostname(myname, sizeof(myname));
98  if (retval) {
99  fprintf(stderr, "getmyIP: Couldn't determine local hostname.\n");
100  return 0;
101  }
102 
103  // gethostname() is guaranteed to produce something gethostbyname() can
104  // parse.
105  // gethostbyname() comes back in network order
106  host = gethostbyname(myname);
107  if (!host) {
108  fprintf(stderr, "getmyIP: Couldn't find host by name (%s).\n", myname);
109  return 0;
110  }
111 
112  memcpy(&in.s_addr, host->h_addr, host->h_length);
113  return ntohl(in.s_addr);
114 }
115 
117  : d_connection(c)
118 {
119  char *servicename;
120 
121  servicename = vrpn_copy_service_name(name);
122 
123  if (c) {
124  c->addReference();
125  d_myId = c->register_sender(servicename);
126  d_requestIndex_type = c->register_message_type(requestIndex_type);
127  d_requestMutex_type = c->register_message_type(requestMutex_type);
128  d_release_type = c->register_message_type(release_type);
130  c->register_message_type(releaseNotification_type);
131  d_grantRequest_type = c->register_message_type(grantRequest_type);
132  d_denyRequest_type = c->register_message_type(denyRequest_type);
133  d_initialize_type = c->register_message_type(initialize_type);
134  }
135 
136  if (servicename) {
137  delete[] servicename;
138  }
139 }
140 
141 // virtual
143 {
144  if (d_connection) {
145  d_connection->removeReference(); // possibly destroy connection.
146  }
147 }
148 
150 {
151 
152  if (d_connection) {
154  }
155 }
156 
157 void vrpn_Mutex::sendRequest(vrpn_int32 index)
158 {
159  timeval now;
160  char buffer[32];
161  char *b = buffer;
162  vrpn_int32 bl = 32;
163 
164  if (!d_connection) return;
165  vrpn_gettimeofday(&now, NULL);
166  vrpn_buffer(&b, &bl, index);
168  buffer, vrpn_CONNECTION_RELIABLE);
169 }
170 
172 {
173  timeval now;
174 
175  if (!d_connection) return;
176 
177  vrpn_gettimeofday(&now, NULL);
180 }
181 
183 {
184  timeval now;
185 
186  if (!d_connection) return;
187  vrpn_gettimeofday(&now, NULL);
190 }
191 
192 void vrpn_Mutex::sendGrantRequest(vrpn_int32 index)
193 {
194  timeval now;
195  char buffer[32];
196  char *b = buffer;
197  vrpn_int32 bl = 32;
198 
199  if (!d_connection) return;
200  vrpn_gettimeofday(&now, NULL);
201  vrpn_buffer(&b, &bl, index);
203  buffer, vrpn_CONNECTION_RELIABLE);
204 }
205 
206 void vrpn_Mutex::sendDenyRequest(vrpn_int32 index)
207 {
208  timeval now;
209  char buffer[32];
210  char *b = buffer;
211  vrpn_int32 bl = 32;
212 
213  if (!d_connection) return;
214  vrpn_gettimeofday(&now, NULL);
215  vrpn_buffer(&b, &bl, index);
216  d_connection->pack_message(32 - bl, now, d_denyRequest_type, d_myId, buffer,
218 }
219 
221  : vrpn_Mutex(name, c)
222  , d_state(FREE)
223  , d_remoteIndex(0)
224 {
225  vrpn_int32 got;
226  vrpn_int32 droppedLast;
227 
228  if (c) {
232 
234  c->register_handler(got, handle_gotConnection, this);
236  c->register_handler(droppedLast, handle_dropLastConnection, this);
237  }
238 }
239 
240 // virtual
242 {
243  if (d_connection) {
244  vrpn_int32 got, droppedLast;
246  droppedLast =
249  handle_requestIndex, this);
251  handle_requestMutex, this);
255  this);
256  }
257 }
258 
259 // static
261 {
262  vrpn_Mutex_Server *me = (vrpn_Mutex_Server *)userdata;
263  const char *b = p.buffer;
264  vrpn_int32 remoteId;
265 
266  vrpn_unbuffer(&b, &remoteId);
267 
268 #ifdef VERBOSE
269  fprintf(stderr, "vrpn_Mutex_Server::handle_request from %d.\n", remoteId);
270 #endif
271 
272  if (me->d_state == FREE) {
273  me->d_state = HELD;
274 
275  // BUG BUG BUG - how does the Mutex_Remote recognize that this grant
276  // is for it, not for some other?
277  me->sendGrantRequest(remoteId);
278 
279  return 0;
280  }
281  else {
282  me->sendDenyRequest(remoteId);
283 
284  return 0;
285  }
286 }
287 
288 // static
290 {
291  vrpn_Mutex_Server *me = (vrpn_Mutex_Server *)userdata;
292 
293 #ifdef VERBOSE
294  fprintf(stderr, "vrpn_Mutex_Server::handle_release.\n");
295 #endif
296 
297  me->d_state = FREE;
299 
300  return 0;
301 }
302 
303 // static
305 {
306  vrpn_Mutex_Server *me = (vrpn_Mutex_Server *)userdata;
307 
308  timeval now;
309  vrpn_int32 msg_len = sizeof(vrpn_int32) + p.payload_len;
310  char *buffer = new char[msg_len];
311  char *b = buffer;
312  vrpn_int32 bl = msg_len;
313 
314 #ifdef VERBOSE
315  fprintf(stderr, "vrpn_Mutex_Server::handle_requestIndex: "
316  "Initializing client %d (%lu %d).\n",
317  me->d_remoteIndex, ntohl(*(vrpn_uint32 *)p.buffer),
318  ntohl(*(vrpn_int32 *)(p.buffer + sizeof(vrpn_uint32))));
319 #endif
320 
321  if (me->d_connection) {
322  vrpn_gettimeofday(&now, NULL);
323  // echo back whatever the client gave us as a unique identifier
324  vrpn_buffer(&b, &bl, p.buffer, p.payload_len);
325  vrpn_buffer(&b, &bl, (me->d_remoteIndex));
326  me->d_connection->pack_message(msg_len, now, me->d_initialize_type,
327  me->d_myId, buffer,
329  }
330 
331  me->d_remoteIndex++;
332  delete[] buffer;
333  return 0;
334 }
335 
336 // static
338 {
339  return 0;
340  // return handle_requestIndex(userdata, p);
341 }
342 
343 // static
346 {
347  vrpn_Mutex_Server *me = (vrpn_Mutex_Server *)userdata;
348 
349  // Force the lock to release, to avoid deadlock.
350  if (me->d_state == HELD) {
351  fprintf(stderr, "vrpn_Mutex_Server::handle_dropLastConnection: "
352  "Forcing the state to FREE to avoid deadlock.\n");
353  }
354 
355  me->d_state = FREE;
356 
357  return 0;
358 }
359 
361  : vrpn_Mutex(name, c ? c : ((strcmp(name, "null") == 0)
362  ? (vrpn_Connection *)NULL
364  , d_state(AVAILABLE)
365  , d_myIndex(-1)
366  , d_requestBeforeInit(vrpn_FALSE)
367  , d_reqGrantedCB(NULL)
368  , d_reqDeniedCB(NULL)
369  , d_takeCB(NULL)
370  , d_releaseCB(NULL)
371 {
372 
373  if (d_connection) {
375  this);
377  this);
381  this);
382  if (d_connection->connected()) {
383  requestIndex();
384  }
385  vrpn_int32 got =
388  }
389 }
390 
391 // virtual
393 {
394 
395  // Make sure we don't deadlock things
396  release();
397 
398  if (d_connection) {
400  handle_grantRequest, this);
402  this);
406  this);
407  vrpn_int32 got =
410  }
411 }
412 
413 vrpn_bool vrpn_Mutex_Remote::isAvailable(void) const
414 {
415  return (d_state == AVAILABLE);
416 }
417 
418 vrpn_bool vrpn_Mutex_Remote::isHeldLocally(void) const
419 {
420  return (d_state == OURS);
421 }
422 
424 {
425  return (d_state == HELD_REMOTELY);
426 }
427 
429 {
430  timeval now;
431  vrpn_int32 buflen = sizeof(vrpn_int32) + sizeof(vrpn_uint32);
432  char *buf = new char[buflen];
433  char *bufptr = buf;
434  vrpn_int32 len = buflen;
435  vrpn_uint32 ip_addr = getmyIP();
436 #ifdef _WIN32
437  vrpn_int32 pid = _getpid();
438 #else
439  vrpn_int32 pid = getpid();
440 #endif
441  vrpn_buffer(&bufptr, &len, ip_addr);
442  vrpn_buffer(&bufptr, &len, pid);
443 #ifdef VERBOSE
444  printf("requesting index for %lu, %d\n", ip_addr, pid);
445 #endif
446  vrpn_gettimeofday(&now, NULL);
449  delete[] buf;
450  return;
451 }
452 
454 {
455  if (!isAvailable()) {
456 
457 #ifdef VERBOSE
458  fprintf(stderr, "Requested unavailable mutex.\n");
459 #endif
461  return;
462  }
463  else if (d_myIndex == -1) {
464 #ifdef VERBOSE
465  fprintf(stderr, "Requested mutex before initialization; deferring.\n");
466 #endif
467  d_requestBeforeInit = vrpn_TRUE;
468  return;
469  }
470 
471 #ifdef VERBOSE
472  fprintf(stderr, "Requesting mutex\n");
473 #endif
474 
477 
478  return;
479 }
480 
482 {
483  if (!isHeldLocally()) {
484  return;
485  }
486 
487 #ifdef VERBOSE
488  fprintf(stderr, "Releasing mutex.\n");
489 #endif
490 
491  d_state = AVAILABLE;
492  sendRelease();
494 }
495 
497  int (*f)(void *))
498 {
499  mutexCallback *cb = new mutexCallback;
500  if (!cb) {
501  fprintf(stderr, "vrpn_Mutex_Remote::addRequestGrantedCallback: "
502  "Out of memory.\n");
503  return;
504  }
505 
506  cb->userdata = userdata;
507  cb->f = f;
508  cb->next = d_reqGrantedCB;
509  d_reqGrantedCB = cb;
510 }
511 
513  int (*f)(void *))
514 {
515  mutexCallback *cb = new mutexCallback;
516  if (!cb) {
517  fprintf(stderr, "vrpn_Mutex_Remote::addRequestDeniedCallback: "
518  "Out of memory.\n");
519  return;
520  }
521 
522  cb->userdata = userdata;
523  cb->f = f;
524  cb->next = d_reqDeniedCB;
525  d_reqDeniedCB = cb;
526 }
527 
528 void vrpn_Mutex_Remote::addTakeCallback(void *userdata, int (*f)(void *))
529 {
530  mutexCallback *cb = new mutexCallback;
531  if (!cb) {
532  fprintf(stderr,
533  "vrpn_Mutex_Remote::addTakeCallback: Out of memory.\n");
534  return;
535  }
536 
537  cb->userdata = userdata;
538  cb->f = f;
539  cb->next = d_takeCB;
540  d_takeCB = cb;
541 }
542 
543 // static
544 void vrpn_Mutex_Remote::addReleaseCallback(void *userdata, int (*f)(void *))
545 {
546  mutexCallback *cb = new mutexCallback;
547  if (!cb) {
548  fprintf(stderr, "vrpn_Mutex_Remote::addReleaseCallback: "
549  "Out of memory.\n");
550  return;
551  }
552 
553  cb->userdata = userdata;
554  cb->f = f;
555  cb->next = d_releaseCB;
556  d_releaseCB = cb;
557 }
558 
559 // static
561 {
562  vrpn_Mutex_Remote *me = (vrpn_Mutex_Remote *)userdata;
563  const char *b = p.buffer;
564  vrpn_int32 index;
565 
566  vrpn_unbuffer(&b, &index);
567 
568 #ifdef VERBOSE
569  fprintf(stderr, "vrpn_Mutex_Remote::handle_grantRequest for %d.\n", index);
570 #endif
571 
572  if (me->d_myIndex != index) {
573  me->d_state = HELD_REMOTELY;
574  me->triggerTakeCallbacks();
575  return 0;
576  }
577 
578  me->d_state = OURS;
579  me->triggerGrantCallbacks();
580  me->triggerTakeCallbacks();
581 
582  return 0;
583 }
584 
585 // static
587 {
588  vrpn_Mutex_Remote *me = (vrpn_Mutex_Remote *)userdata;
589  const char *b = p.buffer;
590  vrpn_int32 index;
591 
592  vrpn_unbuffer(&b, &index);
593 
594 #ifdef VERBOSE
595  fprintf(stderr, "vrpn_Mutex_Remote::handle_denyRequest for %d.\n", index);
596 #endif
597 
598  if (me->d_myIndex != index) {
599  return 0;
600  }
601 
602  me->d_state = HELD_REMOTELY;
603  me->triggerDenyCallbacks();
604 
605  return 0;
606 }
607 
608 // static
611 {
612  vrpn_Mutex_Remote *me = (vrpn_Mutex_Remote *)userdata;
613 
614 #ifdef VERBOSE
615  fprintf(stderr, "vrpn_Mutex_Remote::handle_releaseNotification.\n");
616 #endif
617 
618  me->d_state = AVAILABLE;
620 
621  return 0;
622 }
623 
624 // static
626 {
627  vrpn_Mutex_Remote *me = (vrpn_Mutex_Remote *)userdata;
628  const char *b = p.buffer;
629 
630  // Only pay attention to the first initialize() message we get
631  // after startup.
632  if (me->d_myIndex != -1) {
633  return 0;
634  }
635 
636  vrpn_int32 expected_payload_len =
637  2 * sizeof(vrpn_int32) + sizeof(vrpn_uint32);
638  if (p.payload_len != expected_payload_len) {
639  fprintf(stderr,
640  "vrpn_Mutex_Remote::handle_initialize: "
641  "Warning: Ignoring message with length %d, expected %d\n",
642  p.payload_len, expected_payload_len);
643  return 0;
644  }
645 
646  vrpn_uint32 ip_addr;
647  vrpn_int32 pid;
648  vrpn_unbuffer(&b, &ip_addr);
649  vrpn_unbuffer(&b, &pid);
650  vrpn_int32 my_pid = 0;
651 #ifdef _WIN32
652  my_pid = _getpid();
653 #else
654  my_pid = getpid();
655 #endif
656  if ((ip_addr != getmyIP()) || (pid != my_pid)) {
657  fprintf(
658  stderr,
659  "vrpn_Mutex_Remote::handle_initialize: "
660  "Warning: Ignoring message that doesn't match ip/pid identifier\n");
661 #ifdef VERBOSE
662  fprintf(stderr, "Got %lu %d, expected %lu %d.\n", ip_addr, pid,
663  getmyIP(), my_pid);
664 #endif
665  return 0;
666  }
667  vrpn_unbuffer(&b, &(me->d_myIndex));
668 
669 #ifdef VERBOSE
670  fprintf(stderr, "vrpn_Mutex_Remote::handle_initialize: "
671  "Got assigned index %d.\n",
672  me->d_myIndex);
673 #endif
674 
675  if (me->d_requestBeforeInit) {
676 #ifdef VERBOSE
677  fprintf(stderr, "vrpn_Mutex_Remote::handle_initialize: "
678  "Sending request\n");
679 #endif
680  me->request();
681  }
682 
683  return 0;
684 }
685 
686 // static
688 {
689  vrpn_Mutex_Remote *me = (vrpn_Mutex_Remote *)userdata;
690  if (me->d_myIndex == -1) {
691  me->requestIndex();
692  }
693  return 0;
694 }
695 
697 {
698  mutexCallback *cb;
699 
700  // trigger callbacks
701  for (cb = d_reqGrantedCB; cb; cb = cb->next) {
702  (cb->f)(cb->userdata);
703  }
704 }
705 
707 {
708  mutexCallback *cb;
709 
710  // trigger callbacks
711  for (cb = d_reqDeniedCB; cb; cb = cb->next) {
712  (cb->f)(cb->userdata);
713  }
714 }
715 
717 {
718  mutexCallback *cb;
719 
720  // trigger callbacks
721  for (cb = d_takeCB; cb; cb = cb->next) {
722  (cb->f)(cb->userdata);
723  }
724 }
725 
727 {
728  mutexCallback *cb;
729 
730  // trigger callbacks
731  for (cb = d_releaseCB; cb; cb = cb->next) {
732  (cb->f)(cb->userdata);
733  }
734 }
735 
736 // Implementation notes:
737 //
738 // We broadcast messages over d_peer[] tagged with our IP number in
739 // network format.
740 // We broadcast REPLIES over d_peer[] tagged with the sender's IP number
741 // in network format. When we get a reply, we check the IP number it
742 // contains against our own and discard it if it doesn't match.
743 //
744 // This is an ugly n^2 implementation, when we could do it in 2n, but the
745 // data structures would be a little more complex - we'd have to have a
746 // mapping from IP numbers to vrpn_Connections in d_peer[]. What I'd probably
747 // do would be abandon IP numbers and ports and just use lexographical
748 // ordering of station names. But then we'd have to ensure that every
749 // instance used the same station name (evans vs. evans.cs.unc.edu vs.
750 // evans.cs.unc.edu:4500) for each peer, which is ugly.
751 
752 vrpn_PeerMutex::vrpn_PeerMutex(const char *name, int port,
753  const char *NICaddress)
754  : d_state(AVAILABLE)
755  , d_server(NULL)
756  , d_peer(NULL)
757  , d_numPeers(0)
758  , d_numConnectionsAllocated(0)
759  , d_myIP(getmyIP(NICaddress))
760  , d_myPort(port)
761  , d_holderIP(0)
762  , d_holderPort(-1)
763  , d_reqGrantedCB(NULL)
764  , d_reqDeniedCB(NULL)
765  , d_takeCB(NULL)
766  , d_releaseCB(NULL)
767  , d_peerData(NULL)
768 {
769 
770  if (!name) {
771  fprintf(stderr, "vrpn_PeerMutex: NULL name!\n");
772  return;
773  }
774  // XXX Won't work with non-IP connections (MPI, for example)
775  char con_name[512];
776  sprintf(con_name, "%s:%d", NICaddress, port);
778  if (d_server) {
781  }
782  else {
783  fprintf(stderr, "vrpn_PeerMutex: "
784  "Couldn't open connection on port %d!\n",
785  port);
786  return;
787  }
788 
789  init(name);
790 }
791 
793  : d_state(AVAILABLE)
794  , d_server(server)
795  , d_peer(NULL)
796  , d_numPeers(0)
797  , d_numConnectionsAllocated(0)
798  , d_myIP(getmyIP(NULL))
799  , d_myPort(0)
800  , d_holderIP(0)
801  , d_holderPort(-1)
802  , d_reqGrantedCB(NULL)
803  , d_reqDeniedCB(NULL)
804  , d_takeCB(NULL)
805  , d_releaseCB(NULL)
806  , d_peerData(NULL)
807 {
808 
809  if (!name) {
810  fprintf(stderr, "vrpn_PeerMutex: NULL name!\n");
811  return;
812  }
813  if (server) {
815  }
816  else {
817  fprintf(stderr, "vrpn_PeerMutex: NULL connection!\n");
818  return;
819  }
820 
821  init(name);
822 }
823 
825 {
826 
827  // Send an explicit message so they know we're shutting down, not
828  // just disconnecting temporarily and will be back.
829 
830  // Probably a safer way to do it would be to do addPeer and losePeer
831  // implicitly through dropped_connection/got_connection on d_server
832  // and d_peer?
833 
834  // There is no good solution!
835 
836  // Possible improvement: if we lose our connection and regain it,
837  // send some sort of announcement message to everybody who used to
838  // be our peer so they add us back into their tables.
839 
840  if (isHeldLocally()) {
841  release();
842  }
843 
844  if (d_mutexName) {
845  delete[] d_mutexName;
846  }
847  for (int i = 0; i < d_numPeers; ++i) {
848  if (d_peer[i]) {
849  d_peer[i]->removeReference();
850  }
851  }
852  if (d_peer) {
853  delete[] d_peer;
854  }
855 
856  if (d_server) {
858  }
859 }
860 
861 vrpn_bool vrpn_PeerMutex::isAvailable(void) const
862 {
863  return (d_state == AVAILABLE);
864 }
865 
866 vrpn_bool vrpn_PeerMutex::isHeldLocally(void) const
867 {
868  return (d_state == OURS);
869 }
870 
871 vrpn_bool vrpn_PeerMutex::isHeldRemotely(void) const
872 {
873  return (d_state == HELD_REMOTELY);
874 }
875 
876 int vrpn_PeerMutex::numPeers(void) const { return d_numPeers; }
877 
879 {
880  int i;
881 
882  d_server->mainloop();
883  for (i = 0; i < d_numPeers; i++) {
884  d_peer[i]->mainloop();
885  }
886 
887  checkGrantMutex();
888 }
889 
891 {
892  int i;
893 
894  // No point in sending requests if it's not currently available.
895  // However, we need to trigger any local denial callbacks; otherwise
896  // this looks like a silent failure.
897  if (!isAvailable()) {
899 
900 #ifdef VERBOSE
901  fprintf(stderr,
902  "vrpn_PeerMutex::request: the mutex isn't available.\n");
903 #endif
904 
905  return;
906  }
907 
910  for (i = 0; i < d_numPeers; i++) {
911  // d_peerData[i].grantedLock = VRPN_FALSE;
912  sendRequest(d_peer[i]);
913  }
914 
915  // If somebody else sends a request before we get all our grants,
916  // and their IP/port# is lower than ours, we have to yield to them.
917 
918  d_holderIP = d_myIP;
920 
921  // We used to wait until the next pass through mainloop() to check
922  // this (our request could be trivially granted if we have no
923  // peers), but that leads to bad things (TM), like having to
924  // insert extra calls to mainloop() in client code just to guarantee
925  // that we have the mutex.
926 
927  checkGrantMutex();
928 
929 #ifdef VERBOSE
930  fprintf(stderr, "vrpn_PeerMutex::request: requested the mutex "
931  "(from %d peers).\n",
932  d_numPeers);
933 #endif
934 }
935 
937 {
938  int i;
939 
940  // Can't release it if we don't already have it.
941  // There aren't any appropriate callbacks to trigger here. :)
942  if (!isHeldLocally()) {
943 
944 #ifdef VERBOSE
945  fprintf(stderr, "vrpn_PeerMutex::release: we don't hold the mutex.\n");
946 #endif
947 
948  return;
949  }
950 
951  d_state = AVAILABLE;
952  d_holderIP = 0;
953  d_holderPort = -1;
954  for (i = 0; i < d_numPeers; i++) {
955  sendRelease(d_peer[i]);
956  }
957 
959 
960 #ifdef VERBOSE
961  fprintf(stderr, "vrpn_PeerMutex::release: released the mutex.\n");
962 #endif
963 }
964 
965 void vrpn_PeerMutex::addPeer(const char *stationName)
966 {
967  vrpn_Connection **newc;
968  peerData *newg;
969  losePeerData *d;
970  int i;
971 
972  // complex
974 
975  // reallocate arrays
979  if (!newc || !newg) {
980  fprintf(stderr, "vrpn_PeerMutex::addPeer: Out of memory.\n");
981  return;
982  }
983  for (i = 0; i < d_numPeers; i++) {
984  newc[i] = d_peer[i];
985  newg[i] = d_peerData[i];
986  }
987  if (d_peer) {
988  delete[] d_peer;
989  }
990  if (d_peerData) {
991  delete[] d_peerData;
992  }
993  d_peer = newc;
994  d_peerData = newg;
995  }
997  // d_peerData[d_numPeers].grantedLock = vrpn_false;
998 
999  d = new losePeerData;
1000  if (!d) {
1001  fprintf(stderr, "vrpn_PeerMutex::addPeer: Out of memory.\n");
1002  return;
1003  }
1004  d->connection = d_peer[d_numPeers];
1005  d->mutex = this;
1006  vrpn_int32 control;
1007  vrpn_int32 drop;
1010  d_peer[d_numPeers]->register_handler(drop, handle_losePeer, d, control);
1011 
1012 #ifdef VERBOSE
1013  fprintf(stderr, "vrpn_PeerMutex::addPeer: added peer named %s.\n",
1014  stationName);
1015 #endif
1016 
1017  d_numPeers++;
1018 }
1019 
1020 void vrpn_PeerMutex::addRequestGrantedCallback(void *ud, int (*f)(void *))
1021 {
1022  mutexCallback *cb = new mutexCallback;
1023  if (!cb) {
1024  fprintf(stderr, "vrpn_PeerMutex::addRequestGrantedCallback: "
1025  "Out of memory.\n");
1026  return;
1027  }
1028 
1029  cb->userdata = ud;
1030  cb->f = f;
1031  cb->next = d_reqGrantedCB;
1032  d_reqGrantedCB = cb;
1033 }
1034 
1035 void vrpn_PeerMutex::addRequestDeniedCallback(void *ud, int (*f)(void *))
1036 {
1037  mutexCallback *cb = new mutexCallback;
1038  if (!cb) {
1039  fprintf(stderr, "vrpn_PeerMutex::addRequestDeniedCallback: "
1040  "Out of memory.\n");
1041  return;
1042  }
1043 
1044  cb->userdata = ud;
1045  cb->f = f;
1046  cb->next = d_reqDeniedCB;
1047  d_reqDeniedCB = cb;
1048 }
1049 
1050 void vrpn_PeerMutex::addTakeCallback(void *ud, int (*f)(void *))
1051 {
1052  mutexCallback *cb = new mutexCallback;
1053  if (!cb) {
1054  fprintf(stderr, "vrpn_PeerMutex::addTakeCallback: Out of memory.\n");
1055  return;
1056  }
1057 
1058  cb->userdata = ud;
1059  cb->f = f;
1060  cb->next = d_takeCB;
1061  d_takeCB = cb;
1062 }
1063 
1064 // static
1065 void vrpn_PeerMutex::addReleaseCallback(void *ud, int (*f)(void *))
1066 {
1067  mutexCallback *cb = new mutexCallback;
1068  if (!cb) {
1069  fprintf(stderr, "vrpn_PeerMutex::addReleaseCallback: "
1070  "Out of memory.\n");
1071  return;
1072  }
1073 
1074  cb->userdata = ud;
1075  cb->f = f;
1076  cb->next = d_releaseCB;
1077  d_releaseCB = cb;
1078 }
1079 
1080 // static
1082 {
1083  vrpn_PeerMutex *me = (vrpn_PeerMutex *)userdata;
1084  const char *b = p.buffer;
1085  vrpn_uint32 senderIP;
1086  vrpn_uint32 senderPort;
1087  int i;
1088 
1089  vrpn_unbuffer(&b, &senderIP);
1090  vrpn_unbuffer(&b, &senderPort);
1091 
1092 // This function is where we're n^2. If we could look up the peer
1093 // given their IP number we could be 2n instead.
1094 
1095 #ifdef VERBOSE
1096  in_addr nad;
1097  nad.s_addr = htonl(senderIP);
1098  fprintf(stderr,
1099  "vrpn_PeerMutex::handle_request: got one from %s port %d.\n",
1100  inet_ntoa(nad), senderPort);
1101 #endif
1102 
1103  // If several nodes request the lock at once, ties are broken in favor
1104  // of the node with the lowest IP number & port.
1105 
1106  if ((me->d_state == AVAILABLE) ||
1107  (((me->d_state == HELD_REMOTELY) || (me->d_state == REQUESTING)) &&
1108  ((senderIP < me->d_holderIP) ||
1109  ((senderIP == me->d_holderIP) &&
1110  ((vrpn_int32)senderPort < me->d_holderPort))))) {
1111 
1112  me->d_holderIP = senderIP;
1113  me->d_holderPort = senderPort;
1114 
1115  if (me->d_state != HELD_REMOTELY) {
1116  me->triggerTakeCallbacks();
1117  }
1118 
1119  me->d_state = HELD_REMOTELY;
1120  for (i = 0; i < me->d_numPeers; i++) {
1121  me->sendGrantRequest(me->d_peer[i], senderIP, senderPort);
1122  }
1123  return 0;
1124  }
1125 
1126  for (i = 0; i < me->d_numPeers; i++) {
1127  me->sendDenyRequest(me->d_peer[i], senderIP, senderPort);
1128  }
1129 
1130  return 0;
1131 }
1132 
1133 // static
1135 {
1136  vrpn_PeerMutex *me = (vrpn_PeerMutex *)userdata;
1137  const char *b = p.buffer;
1138  vrpn_uint32 senderIP;
1139  vrpn_uint32 senderPort;
1140 
1141  vrpn_unbuffer(&b, &senderIP);
1142  vrpn_unbuffer(&b, &senderPort);
1143 
1144 #ifdef VERBOSE
1145  in_addr nad;
1146 
1147  nad.s_addr = senderIP;
1148  fprintf(stderr,
1149  "vrpn_PeerMutex::handle_release: got one from %s port %d.\n",
1150  inet_ntoa(nad), senderPort);
1151 #endif
1152 
1153  if ((senderIP != me->d_holderIP) ||
1154  ((vrpn_int32)senderPort != me->d_holderPort)) {
1155  fprintf(stderr, "vrpn_PeerMutex::handle_release: Got a release from "
1156  "somebody who didn't have the lock!?\n");
1157  }
1158 
1159  me->d_state = AVAILABLE;
1160  me->d_holderIP = 0;
1161  me->d_holderPort = -1;
1162 
1164 
1165  return 0;
1166 }
1167 
1168 // static
1170 {
1171  vrpn_PeerMutex *me = (vrpn_PeerMutex *)userdata;
1172  const char *b = p.buffer;
1173  vrpn_uint32 senderIP;
1174  vrpn_uint32 senderPort;
1175 
1176  vrpn_unbuffer(&b, &senderIP);
1177  vrpn_unbuffer(&b, &senderPort);
1178 
1179 #ifdef VERBOSE
1180  in_addr nad;
1181  nad.s_addr = senderIP;
1182  fprintf(stderr, "vrpn_PeerMutex::handle_grantRequest: "
1183  "got one for %s port %d.\n",
1184  inet_ntoa(nad), senderPort);
1185 #endif
1186 
1187  if ((senderIP != me->d_myIP) || (senderPort != me->d_myPort)) {
1188  // we can treat this as a denial -
1189  // but we'll get a denial eventually,
1190  // so we need not do so.
1191  return 0;
1192  }
1193 
1194  me->d_numPeersGrantingLock++;
1195 
1196  me->checkGrantMutex();
1197 
1198  return 0;
1199 }
1200 
1201 // static
1203 {
1204  vrpn_PeerMutex *me = (vrpn_PeerMutex *)userdata;
1205  const char *b = p.buffer;
1206  vrpn_uint32 senderIP;
1207  vrpn_uint32 senderPort;
1208 
1209  vrpn_unbuffer(&b, &senderIP);
1210  vrpn_unbuffer(&b, &senderPort);
1211 
1212 #ifdef VERBOSE
1213  in_addr nad;
1214  nad.s_addr = senderIP;
1215  fprintf(stderr, "vrpn_PeerMutex::handle_denyRequest: "
1216  "got one for %s port %d.\n",
1217  inet_ntoa(nad), senderPort);
1218 #endif
1219 
1220  if ((senderIP != me->d_myIP) || (senderPort != me->d_myPort)) {
1221  return 0;
1222  }
1223 
1224  me->d_numPeersGrantingLock = 0;
1225 
1226  me->triggerDenyCallbacks();
1227 
1228  me->d_state = HELD_REMOTELY;
1229 
1230  return 0;
1231 }
1232 
1233 // static
1235 {
1236  losePeerData *data = (losePeerData *)userdata;
1237  vrpn_PeerMutex *me = data->mutex;
1238  vrpn_Connection *c = data->connection;
1239  int i;
1240 
1241  // Need to abort a request since we don't have enough data to correctly
1242  // compensate for losing a peer mid-request.
1243 
1244  if (me->d_state == REQUESTING) {
1245  me->release();
1246  }
1247 
1248  for (i = 0; i < me->d_numPeers; i++) {
1249  if (c == me->d_peer[i]) {
1250  break;
1251  }
1252  }
1253  if (i == me->d_numPeers) {
1254  fprintf(stderr,
1255  "vrpn_PeerMutex::handle_losePeer: Can't find lost peer.\n");
1256  return 0; // -1?
1257  }
1258 
1259  fprintf(stderr, "vrpn_PeerMutex::handle_losePeer: lost peer #%d.\n", i);
1260 
1261  if (me->d_peer[i]) {
1262  me->d_peer[i]->removeReference();
1263  }
1264  me->d_numPeers--;
1265  me->d_peer[i] = me->d_peer[me->d_numPeers];
1266 
1267  delete data;
1268 
1269  return 0;
1270 }
1271 
1273 {
1274  timeval now;
1275  char buffer[32];
1276  char *b = buffer;
1277  vrpn_int32 bl = 32;
1278 
1279  vrpn_gettimeofday(&now, NULL);
1280  vrpn_buffer(&b, &bl, d_myIP);
1281  vrpn_buffer(&b, &bl, d_myPort);
1282  c->pack_message(32 - bl, now, c->register_message_type(requestMutex_type),
1283  c->register_sender(d_mutexName), buffer,
1285 }
1286 
1288 {
1289  timeval now;
1290  char buffer[32];
1291  char *b = buffer;
1292  vrpn_int32 bl = 32;
1293 
1294  vrpn_gettimeofday(&now, NULL);
1295  vrpn_buffer(&b, &bl, d_myIP);
1296  vrpn_buffer(&b, &bl, d_myPort);
1297  c->pack_message(32 - bl, now, c->register_message_type(release_type),
1298  c->register_sender(d_mutexName), buffer,
1300 }
1301 
1303  vrpn_uint32 port)
1304 {
1305  timeval now;
1306  char buffer[32];
1307  char *b = buffer;
1308  vrpn_int32 bl = 32;
1309 
1310  vrpn_gettimeofday(&now, NULL);
1311  vrpn_buffer(&b, &bl, IP);
1312  vrpn_buffer(&b, &bl, port);
1313  c->pack_message(32 - bl, now, c->register_message_type(grantRequest_type),
1314  c->register_sender(d_mutexName), buffer,
1316 }
1317 
1319  vrpn_uint32 port)
1320 {
1321  timeval now;
1322  char buffer[32];
1323  char *b = buffer;
1324  vrpn_int32 bl = 32;
1325 
1326  vrpn_gettimeofday(&now, NULL);
1327  vrpn_buffer(&b, &bl, IP);
1328  vrpn_buffer(&b, &bl, port);
1329  c->pack_message(32 - bl, now, c->register_message_type(denyRequest_type),
1330  c->register_sender(d_mutexName), buffer,
1332 }
1333 
1335 {
1336  mutexCallback *cb;
1337 
1338  // trigger callbacks
1339  for (cb = d_reqGrantedCB; cb; cb = cb->next) {
1340  (cb->f)(cb->userdata);
1341  }
1342 }
1343 
1345 {
1346  mutexCallback *cb;
1347 
1348  // trigger callbacks
1349  for (cb = d_reqDeniedCB; cb; cb = cb->next) {
1350  (cb->f)(cb->userdata);
1351  }
1352 }
1353 
1355 {
1356  mutexCallback *cb;
1357 
1358  // trigger callbacks
1359  for (cb = d_takeCB; cb; cb = cb->next) {
1360  (cb->f)(cb->userdata);
1361  }
1362 }
1363 
1365 {
1366  mutexCallback *cb;
1367 
1368  // trigger callbacks
1369  for (cb = d_releaseCB; cb; cb = cb->next) {
1370  (cb->f)(cb->userdata);
1371  }
1372 }
1373 
1375 {
1376 
1378  d_state = OURS;
1379 
1382  }
1383 }
1384 
1385 void vrpn_PeerMutex::init(const char *name)
1386 {
1387 
1388  d_mutexName = new char[1 + strlen(name)];
1389  if (!d_mutexName) {
1390  fprintf(stderr, "vrpn_PeerMutex::init: Out of memory.\n");
1391  return;
1392  }
1393  strncpy(d_mutexName, name, strlen(name));
1394 
1395  d_myId = d_server->register_sender(name);
1396  d_request_type = d_server->register_message_type(requestMutex_type);
1398  d_grantRequest_type = d_server->register_message_type(grantRequest_type);
1399  d_denyRequest_type = d_server->register_message_type(denyRequest_type);
1400 
1404  d_myId);
1406  d_myId);
1407 }
vrpn_int32 d_holderPort
Definition: vrpn_Mutex.h:273
vrpn_int32 d_denyRequest_type
Definition: vrpn_Mutex.h:37
static int VRPN_CALLBACK handle_requestIndex(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:304
vrpn_int32 d_denyRequest_type
Definition: vrpn_Mutex.h:279
virtual int mainloop(const struct timeval *timeout=NULL)=0
Call each time through program main loop to handle receiving any incoming messages and sending any pa...
void triggerGrantCallbacks(void)
Definition: vrpn_Mutex.C:1334
virtual int unregister_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:1202
~vrpn_PeerMutex(void)
If isHeldLocally(), calls release().
Definition: vrpn_Mutex.C:824
void addPeer(const char *stationName)
Takes a VRPN station name of the form "<host>:<port>".
Definition: vrpn_Mutex.C:965
static int VRPN_CALLBACK handle_dropLastConnection(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:344
vrpn_uint32 d_myPort
Definition: vrpn_Mutex.h:271
void triggerTakeCallbacks(void)
Definition: vrpn_Mutex.C:1354
VRPN_API int vrpn_unbuffer(const char **buffer, timeval *t)
Utility routine for taking a struct timeval from a buffer that was sent as a message.
Definition: vrpn_Shared.C:312
vrpn_int32 d_request_type
Definition: vrpn_Mutex.h:276
void sendRelease(vrpn_Connection *)
Definition: vrpn_Mutex.C:1287
vrpn_int32 d_myId
Definition: vrpn_Mutex.h:31
const char * vrpn_dropped_connection
vrpn_int32 d_releaseNotification_type
Definition: vrpn_Mutex.h:35
vrpn_Mutex(const char *name, vrpn_Connection *=NULL)
Definition: vrpn_Mutex.C:116
vrpn_bool isHeldRemotely(void) const
True from when we grant the lock to another process in response to its request message until we recei...
Definition: vrpn_Mutex.C:871
const vrpn_uint32 vrpn_CONNECTION_RELIABLE
Classes of service for messages, specify multiple by ORing them together Priority of satisfying these...
mutexCallback * d_takeCB
Definition: vrpn_Mutex.h:142
static int VRPN_CALLBACK handle_losePeer(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:1234
vrpn_int32 payload_len
virtual vrpn_int32 register_sender(const char *name)
Get a token to use for the string name of the sender or type. Remember to check for -1 meaning failur...
void triggerGrantCallbacks(void)
Definition: vrpn_Mutex.C:696
void sendDenyRequest(vrpn_Connection *, vrpn_uint32 IPnumber, vrpn_uint32 PortNumber)
Definition: vrpn_Mutex.C:1318
void checkGrantMutex(void)
Definition: vrpn_Mutex.C:1374
void request(void)
Request the distributed lock. Does not request the lock if !isAvailable(), instead automatically trig...
Definition: vrpn_Mutex.C:453
vrpn_int32 d_requestMutex_type
Definition: vrpn_Mutex.h:33
void addTakeCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer gets the mutex. (If several peers are competing for the m...
Definition: vrpn_Mutex.C:1050
void triggerDenyCallbacks(void)
Definition: vrpn_Mutex.C:706
mutexCallback * d_releaseCB
Definition: vrpn_Mutex.h:314
int d_numPeersGrantingLock
Counts the number of "grants" we've received after issuing a request; when this reaches d_numPeers,...
Definition: vrpn_Mutex.h:257
const char * buffer
void requestIndex(void)
Definition: vrpn_Mutex.C:428
void init(const char *name)
Definition: vrpn_Mutex.C:1385
vrpn_PeerMutex(const char *name, int port, const char *NICaddress=NULL)
This constructor opens a new connection/port for the mutex.
Definition: vrpn_Mutex.C:752
virtual ~vrpn_Mutex_Server(void)
Definition: vrpn_Mutex.C:241
static int VRPN_CALLBACK handle_requestMutex(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:260
vrpn_uint32 d_myIP
Definition: vrpn_Mutex.h:270
void addReleaseCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer releases the mutex.
Definition: vrpn_Mutex.C:1065
mutexCallback * d_reqDeniedCB
Definition: vrpn_Mutex.h:312
vrpn_Connection * d_connection
Definition: vrpn_Mutex.h:29
static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:289
Generic connection class not specific to the transport mechanism.
vrpn_bool isHeldRemotely(void) const
True from when we grant the lock to another process in response to its request message until we recei...
Definition: vrpn_Mutex.C:423
mutexCallback * d_takeCB
Definition: vrpn_Mutex.h:313
void release(void)
Release the distributed lock. Does nothing if !isHeldLocally() and there isn't a request pending.
Definition: vrpn_Mutex.C:481
void sendRequest(vrpn_int32 index)
Definition: vrpn_Mutex.C:157
void triggerReleaseCallbacks(void)
Definition: vrpn_Mutex.C:726
vrpn_int32 d_release_type
Definition: vrpn_Mutex.h:277
virtual int register_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
Set up (or remove) a handler for a message of a given type. Optionally, specify which sender to handl...
vrpn_bool d_requestBeforeInit
Definition: vrpn_Mutex.h:118
int numPeers(void) const
Definition: vrpn_Mutex.C:876
const char * vrpn_dropped_last_connection
vrpn_Connection ** d_peer
Send on these connections to other Mutex's well-known-ports.
Definition: vrpn_Mutex.h:263
void addReleaseCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer releases the mutex.
Definition: vrpn_Mutex.C:544
static int VRPN_CALLBACK handle_initialize(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:625
vrpn_int32 d_initialize_type
Definition: vrpn_Mutex.h:38
This structure is what is passed to a vrpn_Connection message callback.
void sendDenyRequest(vrpn_int32 index)
Definition: vrpn_Mutex.C:206
virtual int pack_message(vrpn_uint32 len, struct timeval time, vrpn_int32 type, vrpn_int32 sender, const char *buffer, vrpn_uint32 class_of_service)
Pack a message that will be sent the next time mainloop() is called. Turn off the RELIABLE flag if yo...
void setAutoDeleteStatus(bool setvalue)
Specify whether this connection should be deleted automatically when it is no longer need (reference ...
static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:1169
void addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
Definition: vrpn_Mutex.C:1020
virtual ~vrpn_Mutex_Remote(void)
Definition: vrpn_Mutex.C:392
vrpn_int32 d_requestIndex_type
Definition: vrpn_Mutex.h:32
virtual vrpn_bool connected(void) const
Returns vrpn_true if the connection has been established, vrpn_false if not (For a networkless connec...
vrpn_uint32 d_holderIP
Definition: vrpn_Mutex.h:272
void sendGrantRequest(vrpn_Connection *, vrpn_uint32 IPnumber, vrpn_uint32 PortNumber)
Definition: vrpn_Mutex.C:1302
vrpn_bool isHeldLocally(void) const
True from when RequestGranted callbacks are triggered until release() is called.
Definition: vrpn_Mutex.C:866
void triggerTakeCallbacks(void)
Definition: vrpn_Mutex.C:716
const char * vrpn_got_connection
peerData * d_peerData
Needed only to clean up when a peer shuts down (mid-request). It isn't currently feasible to have all...
Definition: vrpn_Mutex.h:322
vrpn_PeerMutex
Definition: vrpn_Mutex.h:196
static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:337
char * vrpn_copy_service_name(const char *fullname)
vrpn_bool isAvailable(void) const
True from when release() is called or we receive a release message from another process until request...
Definition: vrpn_Mutex.C:413
mutexCallback * d_reqDeniedCB
Definition: vrpn_Mutex.h:141
void addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
Definition: vrpn_Mutex.C:512
void addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
Definition: vrpn_Mutex.C:1035
static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:1134
static int VRPN_CALLBACK handle_releaseNotification(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:609
vrpn_int32 d_grantRequest_type
Definition: vrpn_Mutex.h:278
vrpn_bool isAvailable(void) const
True from when release() is called or we receive a release message from another process until request...
Definition: vrpn_Mutex.C:861
char * d_mutexName
Definition: vrpn_Mutex.h:253
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
const char * vrpn_CONTROL
vrpn_CONTROL is the sender used for notification messages sent to the user from the local VRPN implem...
vrpn_Connection * vrpn_get_connection_by_name(const char *cname, const char *local_in_logfile_name, const char *local_out_logfile_name, const char *remote_in_logfile_name, const char *remote_out_logfile_name, const char *NIC_IPaddress, bool force_connection)
Create a client connection of arbitrary type (VRPN UDP/TCP, TCP, File, Loopback, MPI).
vrpn_int32 d_myIndex
Definition: vrpn_Mutex.h:117
static int VRPN_CALLBACK handle_request(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:1081
VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen, const timeval t)
Utility routine for placing a timeval struct into a buffer that is to be sent as a message.
Definition: vrpn_Shared.C:241
mutexCallback * d_reqGrantedCB
Definition: vrpn_Mutex.h:311
void addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
Definition: vrpn_Mutex.C:496
virtual ~vrpn_Mutex(void)=0
Definition: vrpn_Mutex.C:142
void sendRelease(void)
Definition: vrpn_Mutex.C:171
vrpn_int32 d_myId
Definition: vrpn_Mutex.h:275
vrpn_int32 d_release_type
Definition: vrpn_Mutex.h:34
vrpn_Mutex_Remote(const char *name, vrpn_Connection *=NULL)
Definition: vrpn_Mutex.C:360
vrpn_Mutex_Server(const char *name, vrpn_Connection *=NULL)
Definition: vrpn_Mutex.C:220
void release(void)
Release the distributed lock. Does nothing if !isHeldLocally() and there isn't a request pending.
Definition: vrpn_Mutex.C:936
vrpn_Connection * vrpn_create_server_connection(const char *cname, const char *local_in_logfile_name, const char *local_out_logfile_name)
Create a server connection of arbitrary type (VRPN UDP/TCP, TCP, File, Loopback, MPI).
void sendRequest(vrpn_Connection *)
Definition: vrpn_Mutex.C:1272
void triggerDenyCallbacks(void)
Definition: vrpn_Mutex.C:1344
vrpn_bool isHeldLocally(void) const
True from when RequestGranted callbacks are triggered until release() is called.
Definition: vrpn_Mutex.C:418
void sendReleaseNotification(void)
Definition: vrpn_Mutex.C:182
void addReference()
Counting references to this connection.
void mainloop(void)
Definition: vrpn_Mutex.C:878
mutexCallback * d_reqGrantedCB
Definition: vrpn_Mutex.h:140
virtual vrpn_int32 register_message_type(const char *name)
void mainloop(void)
Definition: vrpn_Mutex.C:149
void sendGrantRequest(vrpn_int32 index)
Definition: vrpn_Mutex.C:192
vrpn_Connection * d_server
Receive on this connection.
Definition: vrpn_Mutex.h:261
void request(void)
Request the distributed lock. Does not request the lock if !isAvailable(), instead automatically trig...
Definition: vrpn_Mutex.C:890
void addTakeCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer gets the mutex.
Definition: vrpn_Mutex.C:528
static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:687
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
static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:586
vrpn_int32 d_remoteIndex
Counts remotes who have had IDs issued to them.
Definition: vrpn_Mutex.h:58
static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:560
void triggerReleaseCallbacks(void)
Definition: vrpn_Mutex.C:1364