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_Mutex::d_releaseNotification_type
vrpn_int32 d_releaseNotification_type
Definition: vrpn_Mutex.h:35
vrpn_Mutex_Remote::triggerTakeCallbacks
void triggerTakeCallbacks(void)
Definition: vrpn_Mutex.C:716
vrpn_Connection::setAutoDeleteStatus
void setAutoDeleteStatus(bool setvalue)
Specify whether this connection should be deleted automatically when it is no longer need (reference ...
Definition: vrpn_Connection.h:724
vrpn_Mutex::~vrpn_Mutex
virtual ~vrpn_Mutex(void)=0
Definition: vrpn_Mutex.C:142
vrpn_Mutex_Remote::requestIndex
void requestIndex(void)
Definition: vrpn_Mutex.C:428
vrpn_Connection::pack_message
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...
Definition: vrpn_Connection.C:4632
vrpn_Mutex_Server::handle_release
static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:289
vrpn_PeerMutex::isHeldRemotely
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
vrpn_PeerMutex::d_numConnectionsAllocated
int d_numConnectionsAllocated
Dynamic array size for d_peer and d_peerGrantedLock.
Definition: vrpn_Mutex.h:267
vrpn_Mutex::sendReleaseNotification
void sendReleaseNotification(void)
Definition: vrpn_Mutex.C:182
vrpn_PeerMutex::d_myIP
vrpn_uint32 d_myIP
Definition: vrpn_Mutex.h:270
vrpn_got_connection
const char * vrpn_got_connection
Definition: vrpn_Connection.C:185
vrpn_Mutex_Remote::REQUESTING
Definition: vrpn_Mutex.h:114
vrpn_PeerMutex::d_grantRequest_type
vrpn_int32 d_grantRequest_type
Definition: vrpn_Mutex.h:278
vrpn_PeerMutex::triggerGrantCallbacks
void triggerGrantCallbacks(void)
Definition: vrpn_Mutex.C:1334
vrpn_Mutex_Server::vrpn_Mutex_Server
vrpn_Mutex_Server(const char *name, vrpn_Connection *=NULL)
Definition: vrpn_Mutex.C:220
vrpn_PeerMutex::handle_grantRequest
static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:1169
vrpn_Mutex_Server::handle_gotConnection
static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:337
vrpn_PeerMutex::handle_release
static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:1134
vrpn_PeerMutex::sendDenyRequest
void sendDenyRequest(vrpn_Connection *, vrpn_uint32 IPnumber, vrpn_uint32 PortNumber)
Definition: vrpn_Mutex.C:1318
vrpn_get_connection_by_name
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).
Definition: vrpn_Connection.C:5277
vrpn_Mutex_Remote::isAvailable
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
vrpn_Mutex_Remote::handle_grantRequest
static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:560
vrpn_Mutex_Remote::~vrpn_Mutex_Remote
virtual ~vrpn_Mutex_Remote(void)
Definition: vrpn_Mutex.C:392
vrpn_Mutex::mainloop
void mainloop(void)
Definition: vrpn_Mutex.C:149
vrpn_Connection::connected
virtual vrpn_bool connected(void) const
Returns vrpn_true if the connection has been established, vrpn_false if not (For a networkless connec...
Definition: vrpn_Connection.C:5237
vrpn_dropped_last_connection
const char * vrpn_dropped_last_connection
Definition: vrpn_Connection.C:187
vrpn_PeerMutex::handle_request
static int VRPN_CALLBACK handle_request(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:1081
vrpn_Mutex::d_connection
vrpn_Connection * d_connection
Definition: vrpn_Mutex.h:29
vrpn_Mutex::d_denyRequest_type
vrpn_int32 d_denyRequest_type
Definition: vrpn_Mutex.h:37
vrpn_PeerMutex::d_releaseCB
mutexCallback * d_releaseCB
Definition: vrpn_Mutex.h:314
vrpn_Mutex_Server::handle_dropLastConnection
static int VRPN_CALLBACK handle_dropLastConnection(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:344
vrpn_Mutex_Server::d_remoteIndex
vrpn_int32 d_remoteIndex
Counts remotes who have had IDs issued to them.
Definition: vrpn_Mutex.h:58
vrpn_Mutex_Remote::handle_releaseNotification
static int VRPN_CALLBACK handle_releaseNotification(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:609
vrpn_PeerMutex::sendRelease
void sendRelease(vrpn_Connection *)
Definition: vrpn_Mutex.C:1287
vrpn_Mutex_Remote::AVAILABLE
Definition: vrpn_Mutex.h:114
vrpn_PeerMutex::mainloop
void mainloop(void)
Definition: vrpn_Mutex.C:878
vrpn_Mutex::d_grantRequest_type
vrpn_int32 d_grantRequest_type
Definition: vrpn_Mutex.h:36
vrpn_Mutex_Remote::addReleaseCallback
void addReleaseCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer releases the mutex.
Definition: vrpn_Mutex.C:544
vrpn_PeerMutex::OURS
Definition: vrpn_Mutex.h:251
vrpn_Mutex_Remote::OURS
Definition: vrpn_Mutex.h:114
vrpn_PeerMutex::request
void request(void)
Request the distributed lock. Does not request the lock if !isAvailable(), instead automatically trig...
Definition: vrpn_Mutex.C:890
vrpn_HANDLERPARAM::payload_len
vrpn_int32 payload_len
Definition: vrpn_Connection.h:48
vrpn_Mutex_Server::HELD
Definition: vrpn_Mutex.h:54
vrpn_PeerMutex::d_holderPort
vrpn_int32 d_holderPort
Definition: vrpn_Mutex.h:273
vrpn_PeerMutex::d_denyRequest_type
vrpn_int32 d_denyRequest_type
Definition: vrpn_Mutex.h:279
vrpn_PeerMutex::release
void release(void)
Release the distributed lock. Does nothing if !isHeldLocally() and there isn't a request pending.
Definition: vrpn_Mutex.C:936
vrpn_PeerMutex::numPeers
int numPeers(void) const
Definition: vrpn_Mutex.C:876
vrpn_PeerMutex::sendRequest
void sendRequest(vrpn_Connection *)
Definition: vrpn_Mutex.C:1272
vrpn_Mutex.h
vrpn_Mutex_Server::handle_requestMutex
static int VRPN_CALLBACK handle_requestMutex(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:260
vrpn_Mutex_Remote::vrpn_Mutex_Remote
vrpn_Mutex_Remote(const char *name, vrpn_Connection *=NULL)
Definition: vrpn_Mutex.C:360
vrpn_PeerMutex::d_release_type
vrpn_int32 d_release_type
Definition: vrpn_Mutex.h:277
vrpn_Connection::addReference
void addReference()
Counting references to this connection.
Definition: vrpn_Connection.C:5013
vrpn_unbuffer
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_Mutex_Remote::addRequestDeniedCallback
void addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
Definition: vrpn_Mutex.C:512
vrpn_Mutex_Remote::handle_gotConnection
static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:687
vrpn_Mutex_Remote::d_reqDeniedCB
mutexCallback * d_reqDeniedCB
Definition: vrpn_Mutex.h:141
vrpn_PeerMutex::mutexCallback
Definition: vrpn_Mutex.h:305
vrpn_PeerMutex::d_myPort
vrpn_uint32 d_myPort
Definition: vrpn_Mutex.h:271
vrpn_HANDLERPARAM::buffer
const char * buffer
Definition: vrpn_Connection.h:49
vrpn_PeerMutex::d_peer
vrpn_Connection ** d_peer
Send on these connections to other Mutex's well-known-ports.
Definition: vrpn_Mutex.h:263
vrpn_Mutex_Remote::d_releaseCB
mutexCallback * d_releaseCB
Definition: vrpn_Mutex.h:143
vrpn_Connection::register_message_type
virtual vrpn_int32 register_message_type(const char *name)
Definition: vrpn_Connection.C:5074
vrpn_PeerMutex::addReleaseCallback
void addReleaseCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer releases the mutex.
Definition: vrpn_Mutex.C:1065
vrpn_Mutex_Remote::HELD_REMOTELY
Definition: vrpn_Mutex.h:114
vrpn_Mutex::sendRequest
void sendRequest(vrpn_int32 index)
Definition: vrpn_Mutex.C:157
vrpn_PeerMutex::handle_losePeer
static int VRPN_CALLBACK handle_losePeer(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:1234
vrpn_dropped_connection
const char * vrpn_dropped_connection
Definition: vrpn_Connection.C:186
vrpn_CONNECTION_RELIABLE
const vrpn_uint32 vrpn_CONNECTION_RELIABLE
Classes of service for messages, specify multiple by ORing them together Priority of satisfying these...
Definition: vrpn_Connection.h:120
vrpn_HANDLERPARAM
This structure is what is passed to a vrpn_Connection message callback.
Definition: vrpn_Connection.h:44
vrpn_PeerMutex::addRequestDeniedCallback
void addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
Definition: vrpn_Mutex.C:1035
vrpn_Shared.h
vrpn_PeerMutex::d_state
state d_state
Definition: vrpn_Mutex.h:255
vrpn_Mutex_Remote::d_reqGrantedCB
mutexCallback * d_reqGrantedCB
Definition: vrpn_Mutex.h:140
vrpn_Mutex_Remote::addTakeCallback
void addTakeCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer gets the mutex.
Definition: vrpn_Mutex.C:528
vrpn_Mutex::sendGrantRequest
void sendGrantRequest(vrpn_int32 index)
Definition: vrpn_Mutex.C:192
vrpn_Mutex_Remote::handle_denyRequest
static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:586
vrpn_Mutex::d_myId
vrpn_int32 d_myId
Definition: vrpn_Mutex.h:31
vrpn_Mutex_Remote
Definition: vrpn_Mutex.h:70
vrpn_Connection::unregister_handler
virtual int unregister_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
Definition: vrpn_Connection.C:5206
vrpn_Mutex_Remote::mutexCallback::userdata
void * userdata
Definition: vrpn_Mutex.h:136
vrpn_PeerMutex::triggerReleaseCallbacks
void triggerReleaseCallbacks(void)
Definition: vrpn_Mutex.C:1364
vrpn_PeerMutex::mutexCallback::f
int(* f)(void *)
Definition: vrpn_Mutex.h:306
vrpn_PeerMutex::handle_denyRequest
static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:1202
vrpn_Mutex_Remote::mutexCallback::next
mutexCallback * next
Definition: vrpn_Mutex.h:137
vrpn_Mutex_Server
Definition: vrpn_Mutex.h:47
vrpn_Mutex_Remote::d_requestBeforeInit
vrpn_bool d_requestBeforeInit
Definition: vrpn_Mutex.h:118
vrpn_Connection::mainloop
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...
vrpn_Connection
Generic connection class not specific to the transport mechanism.
Definition: vrpn_Connection.h:510
vrpn_Mutex_Remote::request
void request(void)
Request the distributed lock. Does not request the lock if !isAvailable(), instead automatically trig...
Definition: vrpn_Mutex.C:453
vrpn_Connection.h
vrpn_Mutex::vrpn_Mutex
vrpn_Mutex(const char *name, vrpn_Connection *=NULL)
Definition: vrpn_Mutex.C:116
vrpn_PeerMutex::mutexCallback::userdata
void * userdata
Definition: vrpn_Mutex.h:307
vrpn_PeerMutex::d_peerData
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::d_request_type
vrpn_int32 d_request_type
Definition: vrpn_Mutex.h:276
vrpn_Mutex_Server::d_state
state d_state
Definition: vrpn_Mutex.h:56
vrpn_Mutex_Server::handle_requestIndex
static int VRPN_CALLBACK handle_requestIndex(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:304
vrpn_PeerMutex::triggerDenyCallbacks
void triggerDenyCallbacks(void)
Definition: vrpn_Mutex.C:1344
vrpn_gettimeofday
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
vrpn_PeerMutex::triggerTakeCallbacks
void triggerTakeCallbacks(void)
Definition: vrpn_Mutex.C:1354
vrpn_PeerMutex::checkGrantMutex
void checkGrantMutex(void)
Definition: vrpn_Mutex.C:1374
vrpn_Mutex_Remote::mutexCallback::f
int(* f)(void *)
Definition: vrpn_Mutex.h:135
vrpn_PeerMutex::vrpn_PeerMutex
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
vrpn_Mutex_Remote::d_takeCB
mutexCallback * d_takeCB
Definition: vrpn_Mutex.h:142
vrpn_Mutex::d_initialize_type
vrpn_int32 d_initialize_type
Definition: vrpn_Mutex.h:38
vrpn_Mutex::sendRelease
void sendRelease(void)
Definition: vrpn_Mutex.C:171
vrpn_PeerMutex::isHeldLocally
vrpn_bool isHeldLocally(void) const
True from when RequestGranted callbacks are triggered until release() is called.
Definition: vrpn_Mutex.C:866
vrpn_PeerMutex::addRequestGrantedCallback
void addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
Definition: vrpn_Mutex.C:1020
vrpn_Mutex_Remote::d_myIndex
vrpn_int32 d_myIndex
Definition: vrpn_Mutex.h:117
vrpn_PeerMutex::d_mutexName
char * d_mutexName
Definition: vrpn_Mutex.h:253
vrpn_PeerMutex::d_reqDeniedCB
mutexCallback * d_reqDeniedCB
Definition: vrpn_Mutex.h:312
vrpn_PeerMutex::isAvailable
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
vrpn_Mutex_Remote::addRequestGrantedCallback
void addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
Definition: vrpn_Mutex.C:496
vrpn_Mutex_Remote::triggerGrantCallbacks
void triggerGrantCallbacks(void)
Definition: vrpn_Mutex.C:696
vrpn_Connection::register_sender
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...
Definition: vrpn_Connection.C:5032
vrpn_PeerMutex::d_reqGrantedCB
mutexCallback * d_reqGrantedCB
Definition: vrpn_Mutex.h:311
vrpn_PeerMutex::AVAILABLE
Definition: vrpn_Mutex.h:251
vrpn_PeerMutex::mutexCallback::next
mutexCallback * next
Definition: vrpn_Mutex.h:308
vrpn_Mutex_Remote::d_state
state d_state
Definition: vrpn_Mutex.h:116
vrpn_PeerMutex::addTakeCallback
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
vrpn_Mutex_Remote::release
void release(void)
Release the distributed lock. Does nothing if !isHeldLocally() and there isn't a request pending.
Definition: vrpn_Mutex.C:481
vrpn_Mutex_Remote::isHeldRemotely
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
vrpn_PeerMutex::addPeer
void addPeer(const char *stationName)
Takes a VRPN station name of the form "<host>:<port>".
Definition: vrpn_Mutex.C:965
vrpn_PeerMutex::HELD_REMOTELY
Definition: vrpn_Mutex.h:251
vrpn_Connection::removeReference
void removeReference()
Definition: vrpn_Connection.C:5020
vrpn_Mutex_Remote::handle_initialize
static int VRPN_CALLBACK handle_initialize(void *, vrpn_HANDLERPARAM)
Definition: vrpn_Mutex.C:625
vrpn_buffer
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
vrpn_Mutex_Remote::triggerReleaseCallbacks
void triggerReleaseCallbacks(void)
Definition: vrpn_Mutex.C:726
vrpn_PeerMutex
vrpn_PeerMutex
Definition: vrpn_Mutex.h:196
vrpn_Mutex_Server::~vrpn_Mutex_Server
virtual ~vrpn_Mutex_Server(void)
Definition: vrpn_Mutex.C:241
vrpn_Mutex::d_release_type
vrpn_int32 d_release_type
Definition: vrpn_Mutex.h:34
vrpn_Mutex
Definition: vrpn_Mutex.h:20
vrpn_copy_service_name
char * vrpn_copy_service_name(const char *fullname)
Definition: vrpn_Connection.C:6335
vrpn_Mutex_Remote::mutexCallback
Definition: vrpn_Mutex.h:134
vrpn_PeerMutex::REQUESTING
Definition: vrpn_Mutex.h:251
vrpn_PeerMutex::d_takeCB
mutexCallback * d_takeCB
Definition: vrpn_Mutex.h:313
vrpn_PeerMutex::d_server
vrpn_Connection * d_server
Receive on this connection.
Definition: vrpn_Mutex.h:261
vrpn_Mutex_Remote::isHeldLocally
vrpn_bool isHeldLocally(void) const
True from when RequestGranted callbacks are triggered until release() is called.
Definition: vrpn_Mutex.C:418
vrpn_PeerMutex::d_numPeersGrantingLock
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
vrpn_Mutex_Remote::triggerDenyCallbacks
void triggerDenyCallbacks(void)
Definition: vrpn_Mutex.C:706
vrpn_PeerMutex::d_numPeers
int d_numPeers
Definition: vrpn_Mutex.h:266
vrpn_Connection::register_handler
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...
Definition: vrpn_Connection.C:5199
vrpn_PeerMutex::init
void init(const char *name)
Definition: vrpn_Mutex.C:1385
vrpn_PeerMutex::d_myId
vrpn_int32 d_myId
Definition: vrpn_Mutex.h:275
vrpn_PeerMutex::peerData
Definition: vrpn_Mutex.h:316
vrpn_Mutex::sendDenyRequest
void sendDenyRequest(vrpn_int32 index)
Definition: vrpn_Mutex.C:206
vrpn_Mutex_Server::FREE
Definition: vrpn_Mutex.h:54
vrpn_PeerMutex::~vrpn_PeerMutex
~vrpn_PeerMutex(void)
If isHeldLocally(), calls release().
Definition: vrpn_Mutex.C:824
vrpn_CONTROL
const char * vrpn_CONTROL
vrpn_CONTROL is the sender used for notification messages sent to the user from the local VRPN implem...
Definition: vrpn_Connection.C:190
vrpn_PeerMutex::d_holderIP
vrpn_uint32 d_holderIP
Definition: vrpn_Mutex.h:272
vrpn_PeerMutex::sendGrantRequest
void sendGrantRequest(vrpn_Connection *, vrpn_uint32 IPnumber, vrpn_uint32 PortNumber)
Definition: vrpn_Mutex.C:1302
vrpn_Mutex::d_requestIndex_type
vrpn_int32 d_requestIndex_type
Definition: vrpn_Mutex.h:32
vrpn_Mutex::d_requestMutex_type
vrpn_int32 d_requestMutex_type
Definition: vrpn_Mutex.h:33
vrpn_create_server_connection
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).
Definition: vrpn_Connection.C:5358