vrpn 07.35
Virtual Reality Peripheral Network
Loading...
Searching...
No Matches
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";
54static const char *requestIndex_type = "vrpn_Mutex Request Index";
55static const char *requestMutex_type = "vrpn_Mutex Request Mutex";
56static const char *release_type = "vrpn_Mutex Release";
57static const char *releaseNotification_type = "vrpn_Mutex Release_Notification";
58static const char *grantRequest_type = "vrpn_Mutex Grant_Request";
59static const char *denyRequest_type = "vrpn_Mutex Deny_Request";
60// static const char * losePeer_type = "vrpn_Mutex Lose_Peer";
61static const char *initialize_type = "vrpn_Mutex Initialize";
62
63struct 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.
71static 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 try {
138 delete[] servicename;
139 } catch (...) {
140 fprintf(stderr, "vrpn_Mutex::vrpn_Mutex(): delete failed\n");
141 return;
142 }
143 }
144}
145
146// virtual
148{
149 if (d_connection) {
150 d_connection->removeReference(); // possibly destroy connection.
151 }
152}
153
155{
156
157 if (d_connection) {
159 }
160}
161
162void vrpn_Mutex::sendRequest(vrpn_int32 index)
163{
164 timeval now;
165 char buffer[32];
166 char *b = buffer;
167 vrpn_int32 bl = 32;
168
169 if (!d_connection) return;
170 vrpn_gettimeofday(&now, NULL);
171 vrpn_buffer(&b, &bl, index);
174}
175
177{
178 timeval now;
179
180 if (!d_connection) return;
181
182 vrpn_gettimeofday(&now, NULL);
185}
186
188{
189 timeval now;
190
191 if (!d_connection) return;
192 vrpn_gettimeofday(&now, NULL);
195}
196
197void vrpn_Mutex::sendGrantRequest(vrpn_int32 index)
198{
199 timeval now;
200 char buffer[32];
201 char *b = buffer;
202 vrpn_int32 bl = 32;
203
204 if (!d_connection) return;
205 vrpn_gettimeofday(&now, NULL);
206 vrpn_buffer(&b, &bl, index);
209}
210
211void vrpn_Mutex::sendDenyRequest(vrpn_int32 index)
212{
213 timeval now;
214 char buffer[32];
215 char *b = buffer;
216 vrpn_int32 bl = 32;
217
218 if (!d_connection) return;
219 vrpn_gettimeofday(&now, NULL);
220 vrpn_buffer(&b, &bl, index);
221 d_connection->pack_message(32 - bl, now, d_denyRequest_type, d_myId, buffer,
223}
224
226 : vrpn_Mutex(name, c)
227 , d_state(FREE)
228 , d_remoteIndex(0)
229{
230 vrpn_int32 got;
231 vrpn_int32 droppedLast;
232
233 if (c) {
237
241 c->register_handler(droppedLast, handle_dropLastConnection, this);
242 }
243}
244
245// virtual
247{
248 if (d_connection) {
249 vrpn_int32 got, droppedLast;
251 droppedLast =
254 handle_requestIndex, this);
256 handle_requestMutex, this);
260 this);
261 }
262}
263
264// static
266{
267 vrpn_Mutex_Server *me = (vrpn_Mutex_Server *)userdata;
268 const char *b = p.buffer;
269 vrpn_int32 remoteId;
270
271 vrpn_unbuffer(&b, &remoteId);
272
273#ifdef VERBOSE
274 fprintf(stderr, "vrpn_Mutex_Server::handle_request from %d.\n", remoteId);
275#endif
276
277 if (me->d_state == FREE) {
278 me->d_state = HELD;
279
280 // BUG BUG BUG - how does the Mutex_Remote recognize that this grant
281 // is for it, not for some other?
282 me->sendGrantRequest(remoteId);
283
284 return 0;
285 }
286 else {
287 me->sendDenyRequest(remoteId);
288
289 return 0;
290 }
291}
292
293// static
295{
296 vrpn_Mutex_Server *me = (vrpn_Mutex_Server *)userdata;
297
298#ifdef VERBOSE
299 fprintf(stderr, "vrpn_Mutex_Server::handle_release.\n");
300#endif
301
302 me->d_state = FREE;
304
305 return 0;
306}
307
308// static
310{
311 vrpn_Mutex_Server *me = (vrpn_Mutex_Server *)userdata;
312
313 timeval now;
314 vrpn_int32 msg_len = sizeof(vrpn_int32) + p.payload_len;
315 char *buffer = NULL;
316 try { buffer = new char[msg_len]; }
317 catch (...) { return -1; }
318 char *b = buffer;
319 vrpn_int32 bl = msg_len;
320
321#ifdef VERBOSE
322 fprintf(stderr, "vrpn_Mutex_Server::handle_requestIndex: "
323 "Initializing client %d (%lu %d).\n",
324 me->d_remoteIndex, ntohl(*(vrpn_uint32 *)p.buffer),
325 ntohl(*(vrpn_int32 *)(p.buffer + sizeof(vrpn_uint32))));
326#endif
327
328 if (me->d_connection) {
329 vrpn_gettimeofday(&now, NULL);
330 // echo back whatever the client gave us as a unique identifier
331 vrpn_buffer(&b, &bl, p.buffer, p.payload_len);
332 vrpn_buffer(&b, &bl, (me->d_remoteIndex));
333 me->d_connection->pack_message(msg_len, now, me->d_initialize_type,
334 me->d_myId, buffer,
336 }
337
338 me->d_remoteIndex++;
339 try {
340 delete[] buffer;
341 } catch (...) {
342 fprintf(stderr, "vrpn_Mutex_Server::handle_requestIndex(): delete failed\n");
343 return -1;
344 }
345 return 0;
346}
347
348// static
350{
351 return 0;
352 // return handle_requestIndex(userdata, p);
353}
354
355// static
358{
359 vrpn_Mutex_Server *me = (vrpn_Mutex_Server *)userdata;
360
361 // Force the lock to release, to avoid deadlock.
362 if (me->d_state == HELD) {
363 fprintf(stderr, "vrpn_Mutex_Server::handle_dropLastConnection: "
364 "Forcing the state to FREE to avoid deadlock.\n");
365 }
366
367 me->d_state = FREE;
368
369 return 0;
370}
371
373 : vrpn_Mutex(name, c ? c : ((strcmp(name, "null") == 0)
374 ? (vrpn_Connection *)NULL
376 , d_state(AVAILABLE)
377 , d_myIndex(-1)
378 , d_requestBeforeInit(vrpn_FALSE)
379 , d_reqGrantedCB(NULL)
380 , d_reqDeniedCB(NULL)
381 , d_takeCB(NULL)
382 , d_releaseCB(NULL)
383{
384
385 if (d_connection) {
387 this);
389 this);
393 this);
394 if (d_connection->connected()) {
395 requestIndex();
396 }
397 vrpn_int32 got =
400 }
401}
402
403// virtual
405{
406
407 // Make sure we don't deadlock things
408 release();
409
410 if (d_connection) {
412 handle_grantRequest, this);
414 this);
418 this);
419 vrpn_int32 got =
422 }
423}
424
426{
427 return (d_state == AVAILABLE);
428}
429
431{
432 return (d_state == OURS);
433}
434
436{
437 return (d_state == HELD_REMOTELY);
438}
439
441{
442 timeval now;
443 vrpn_int32 buflen = sizeof(vrpn_int32) + sizeof(vrpn_uint32);
444 char *buf = NULL;
445 try { buf = new char[buflen]; }
446 catch (...) { return; }
447 char *bufptr = buf;
448 vrpn_int32 len = buflen;
449 vrpn_uint32 ip_addr = getmyIP();
450#ifdef _WIN32
451 vrpn_int32 pid = _getpid();
452#else
453 vrpn_int32 pid = getpid();
454#endif
455 vrpn_buffer(&bufptr, &len, ip_addr);
456 vrpn_buffer(&bufptr, &len, pid);
457#ifdef VERBOSE
458 printf("requesting index for %lu, %d\n", ip_addr, pid);
459#endif
460 vrpn_gettimeofday(&now, NULL);
463 try {
464 delete[] buf;
465 } catch (...) {
466 fprintf(stderr, "vrpn_Mutex_Remote::requestIndex(): delete failed\n");
467 return;
468 }
469 return;
470}
471
473{
474 if (!isAvailable()) {
475
476#ifdef VERBOSE
477 fprintf(stderr, "Requested unavailable mutex.\n");
478#endif
480 return;
481 }
482 else if (d_myIndex == -1) {
483#ifdef VERBOSE
484 fprintf(stderr, "Requested mutex before initialization; deferring.\n");
485#endif
486 d_requestBeforeInit = vrpn_TRUE;
487 return;
488 }
489
490#ifdef VERBOSE
491 fprintf(stderr, "Requesting mutex\n");
492#endif
493
496
497 return;
498}
499
501{
502 if (!isHeldLocally()) {
503 return;
504 }
505
506#ifdef VERBOSE
507 fprintf(stderr, "Releasing mutex.\n");
508#endif
509
511 sendRelease();
513}
514
516 int (*f)(void *))
517{
518 mutexCallback *cb = NULL;
519 try { cb = new mutexCallback; }
520 catch (...) {
521 fprintf(stderr, "vrpn_Mutex_Remote::addRequestGrantedCallback: "
522 "Out of memory.\n");
523 return false;
524 }
525
526 cb->userdata = userdata;
527 cb->f = f;
528 cb->next = d_reqGrantedCB;
529 d_reqGrantedCB = cb;
530 return true;
531}
532
534 int (*f)(void *))
535{
536 mutexCallback *cb = NULL;
537 try { cb = new mutexCallback; }
538 catch (...) {
539 fprintf(stderr, "vrpn_Mutex_Remote::addRequestDeniedCallback: "
540 "Out of memory.\n");
541 return false;
542 }
543
544 cb->userdata = userdata;
545 cb->f = f;
546 cb->next = d_reqDeniedCB;
547 d_reqDeniedCB = cb;
548 return true;
549}
550
551vrpn_bool vrpn_Mutex_Remote::addTakeCallback(void *userdata, int (*f)(void *))
552{
553 mutexCallback *cb = NULL;
554 try { cb = new mutexCallback; }
555 catch (...) {
556 fprintf(stderr,
557 "vrpn_Mutex_Remote::addTakeCallback: Out of memory.\n");
558 return false;
559 }
560
561 cb->userdata = userdata;
562 cb->f = f;
563 cb->next = d_takeCB;
564 d_takeCB = cb;
565 return true;
566}
567
568// static
569vrpn_bool vrpn_Mutex_Remote::addReleaseCallback(void *userdata, int (*f)(void *))
570{
571 mutexCallback *cb = NULL;
572 try { cb = new mutexCallback; }
573 catch (...) {
574 fprintf(stderr, "vrpn_Mutex_Remote::addReleaseCallback: "
575 "Out of memory.\n");
576 return false;
577 }
578
579 cb->userdata = userdata;
580 cb->f = f;
581 cb->next = d_releaseCB;
582 d_releaseCB = cb;
583 return true;
584}
585
586// static
588{
589 vrpn_Mutex_Remote *me = (vrpn_Mutex_Remote *)userdata;
590 const char *b = p.buffer;
591 vrpn_int32 index;
592
593 vrpn_unbuffer(&b, &index);
594
595#ifdef VERBOSE
596 fprintf(stderr, "vrpn_Mutex_Remote::handle_grantRequest for %d.\n", index);
597#endif
598
599 if (me->d_myIndex != index) {
602 return 0;
603 }
604
605 me->d_state = OURS;
608
609 return 0;
610}
611
612// static
614{
615 vrpn_Mutex_Remote *me = (vrpn_Mutex_Remote *)userdata;
616 const char *b = p.buffer;
617 vrpn_int32 index;
618
619 vrpn_unbuffer(&b, &index);
620
621#ifdef VERBOSE
622 fprintf(stderr, "vrpn_Mutex_Remote::handle_denyRequest for %d.\n", index);
623#endif
624
625 if (me->d_myIndex != index) {
626 return 0;
627 }
628
631
632 return 0;
633}
634
635// static
638{
639 vrpn_Mutex_Remote *me = (vrpn_Mutex_Remote *)userdata;
640
641#ifdef VERBOSE
642 fprintf(stderr, "vrpn_Mutex_Remote::handle_releaseNotification.\n");
643#endif
644
645 me->d_state = AVAILABLE;
647
648 return 0;
649}
650
651// static
653{
654 vrpn_Mutex_Remote *me = (vrpn_Mutex_Remote *)userdata;
655 const char *b = p.buffer;
656
657 // Only pay attention to the first initialize() message we get
658 // after startup.
659 if (me->d_myIndex != -1) {
660 return 0;
661 }
662
663 vrpn_int32 expected_payload_len =
664 2 * sizeof(vrpn_int32) + sizeof(vrpn_uint32);
665 if (p.payload_len != expected_payload_len) {
666 fprintf(stderr,
667 "vrpn_Mutex_Remote::handle_initialize: "
668 "Warning: Ignoring message with length %d, expected %d\n",
669 p.payload_len, expected_payload_len);
670 return 0;
671 }
672
673 vrpn_uint32 ip_addr;
674 vrpn_int32 pid;
675 vrpn_unbuffer(&b, &ip_addr);
676 vrpn_unbuffer(&b, &pid);
677 vrpn_int32 my_pid = 0;
678#ifdef _WIN32
679 my_pid = _getpid();
680#else
681 my_pid = getpid();
682#endif
683 if ((ip_addr != getmyIP()) || (pid != my_pid)) {
684 fprintf(
685 stderr,
686 "vrpn_Mutex_Remote::handle_initialize: "
687 "Warning: Ignoring message that doesn't match ip/pid identifier\n");
688#ifdef VERBOSE
689 fprintf(stderr, "Got %lu %d, expected %lu %d.\n", ip_addr, pid,
690 getmyIP(), my_pid);
691#endif
692 return 0;
693 }
694 vrpn_unbuffer(&b, &(me->d_myIndex));
695
696#ifdef VERBOSE
697 fprintf(stderr, "vrpn_Mutex_Remote::handle_initialize: "
698 "Got assigned index %d.\n",
699 me->d_myIndex);
700#endif
701
702 if (me->d_requestBeforeInit) {
703#ifdef VERBOSE
704 fprintf(stderr, "vrpn_Mutex_Remote::handle_initialize: "
705 "Sending request\n");
706#endif
707 me->request();
708 }
709
710 return 0;
711}
712
713// static
715{
716 vrpn_Mutex_Remote *me = (vrpn_Mutex_Remote *)userdata;
717 if (me->d_myIndex == -1) {
718 me->requestIndex();
719 }
720 return 0;
721}
722
724{
725 mutexCallback *cb;
726
727 // trigger callbacks
728 for (cb = d_reqGrantedCB; cb; cb = cb->next) {
729 (cb->f)(cb->userdata);
730 }
731}
732
734{
735 mutexCallback *cb;
736
737 // trigger callbacks
738 for (cb = d_reqDeniedCB; cb; cb = cb->next) {
739 (cb->f)(cb->userdata);
740 }
741}
742
744{
745 mutexCallback *cb;
746
747 // trigger callbacks
748 for (cb = d_takeCB; cb; cb = cb->next) {
749 (cb->f)(cb->userdata);
750 }
751}
752
754{
755 mutexCallback *cb;
756
757 // trigger callbacks
758 for (cb = d_releaseCB; cb; cb = cb->next) {
759 (cb->f)(cb->userdata);
760 }
761}
762
763// Implementation notes:
764//
765// We broadcast messages over d_peer[] tagged with our IP number in
766// network format.
767// We broadcast REPLIES over d_peer[] tagged with the sender's IP number
768// in network format. When we get a reply, we check the IP number it
769// contains against our own and discard it if it doesn't match.
770//
771// This is an ugly n^2 implementation, when we could do it in 2n, but the
772// data structures would be a little more complex - we'd have to have a
773// mapping from IP numbers to vrpn_Connections in d_peer[]. What I'd probably
774// do would be abandon IP numbers and ports and just use lexographical
775// ordering of station names. But then we'd have to ensure that every
776// instance used the same station name (evans vs. evans.cs.unc.edu vs.
777// evans.cs.unc.edu:4500) for each peer, which is ugly.
778
779vrpn_PeerMutex::vrpn_PeerMutex(const char *name, int port,
780 const char *NICaddress)
781 : d_state(AVAILABLE)
782 , d_server(NULL)
783 , d_peer(NULL)
784 , d_numPeers(0)
785 , d_numConnectionsAllocated(0)
786 , d_myIP(getmyIP(NICaddress))
787 , d_myPort(port)
788 , d_holderIP(0)
789 , d_holderPort(-1)
790 , d_reqGrantedCB(NULL)
791 , d_reqDeniedCB(NULL)
792 , d_takeCB(NULL)
793 , d_releaseCB(NULL)
794 , d_peerData(NULL)
795{
796
797 if (!name) {
798 fprintf(stderr, "vrpn_PeerMutex: NULL name!\n");
799 return;
800 }
801 // XXX Won't work with non-IP connections (MPI, for example)
802 char con_name[512];
803 sprintf(con_name, "%s:%d", NICaddress, port);
805 if (d_server) {
808 }
809 else {
810 fprintf(stderr, "vrpn_PeerMutex: "
811 "Couldn't open connection on port %d!\n",
812 port);
813 return;
814 }
815
816 init(name);
817}
818
820 : d_state(AVAILABLE)
821 , d_server(server)
822 , d_peer(NULL)
823 , d_numPeers(0)
824 , d_numConnectionsAllocated(0)
825 , d_myIP(getmyIP(NULL))
826 , d_myPort(0)
827 , d_holderIP(0)
828 , d_holderPort(-1)
829 , d_reqGrantedCB(NULL)
830 , d_reqDeniedCB(NULL)
831 , d_takeCB(NULL)
832 , d_releaseCB(NULL)
833 , d_peerData(NULL)
834{
835
836 if (!name) {
837 fprintf(stderr, "vrpn_PeerMutex: NULL name!\n");
838 return;
839 }
840 if (server) {
842 }
843 else {
844 fprintf(stderr, "vrpn_PeerMutex: NULL connection!\n");
845 return;
846 }
847
848 init(name);
849}
850
852{
853
854 // Send an explicit message so they know we're shutting down, not
855 // just disconnecting temporarily and will be back.
856
857 // Probably a safer way to do it would be to do addPeer and losePeer
858 // implicitly through dropped_connection/got_connection on d_server
859 // and d_peer?
860
861 // There is no good solution!
862
863 // Possible improvement: if we lose our connection and regain it,
864 // send some sort of announcement message to everybody who used to
865 // be our peer so they add us back into their tables.
866
867 if (isHeldLocally()) {
868 release();
869 }
870
871 if (d_mutexName) {
872 try {
873 delete[] d_mutexName;
874 } catch (...) {
875 fprintf(stderr, "vrpn_PeerMutex::~vrpn_PeerMutex(): delete failed\n");
876 return;
877 }
878 }
879 for (int i = 0; i < d_numPeers; ++i) {
880 if (d_peer[i]) {
882 }
883 }
884 if (d_peer) {
885 try {
886 delete[] d_peer;
887 } catch (...) {
888 fprintf(stderr, "vrpn_PeerMutex::~vrpn_PeerMutex(): delete failed\n");
889 return;
890 }
891 }
892
893 if (d_server) {
895 }
896}
897
898vrpn_bool vrpn_PeerMutex::isAvailable(void) const
899{
900 return (d_state == AVAILABLE);
901}
902
903vrpn_bool vrpn_PeerMutex::isHeldLocally(void) const
904{
905 return (d_state == OURS);
906}
907
909{
910 return (d_state == HELD_REMOTELY);
911}
912
913int vrpn_PeerMutex::numPeers(void) const { return d_numPeers; }
914
916{
917 int i;
918
920 for (i = 0; i < d_numPeers; i++) {
921 d_peer[i]->mainloop();
922 }
923
925}
926
928{
929 int i;
930
931 // No point in sending requests if it's not currently available.
932 // However, we need to trigger any local denial callbacks; otherwise
933 // this looks like a silent failure.
934 if (!isAvailable()) {
936
937#ifdef VERBOSE
938 fprintf(stderr,
939 "vrpn_PeerMutex::request: the mutex isn't available.\n");
940#endif
941
942 return;
943 }
944
947 for (i = 0; i < d_numPeers; i++) {
948 // d_peerData[i].grantedLock = VRPN_FALSE;
950 }
951
952 // If somebody else sends a request before we get all our grants,
953 // and their IP/port# is lower than ours, we have to yield to them.
954
957
958 // We used to wait until the next pass through mainloop() to check
959 // this (our request could be trivially granted if we have no
960 // peers), but that leads to bad things (TM), like having to
961 // insert extra calls to mainloop() in client code just to guarantee
962 // that we have the mutex.
963
965
966#ifdef VERBOSE
967 fprintf(stderr, "vrpn_PeerMutex::request: requested the mutex "
968 "(from %d peers).\n",
969 d_numPeers);
970#endif
971}
972
974{
975 int i;
976
977 // Can't release it if we don't already have it.
978 // There aren't any appropriate callbacks to trigger here. :)
979 if (!isHeldLocally()) {
980
981#ifdef VERBOSE
982 fprintf(stderr, "vrpn_PeerMutex::release: we don't hold the mutex.\n");
983#endif
984
985 return;
986 }
987
989 d_holderIP = 0;
990 d_holderPort = -1;
991 for (i = 0; i < d_numPeers; i++) {
993 }
994
996
997#ifdef VERBOSE
998 fprintf(stderr, "vrpn_PeerMutex::release: released the mutex.\n");
999#endif
1000}
1001
1002vrpn_bool vrpn_PeerMutex::addPeer(const char *stationName)
1003{
1004 vrpn_Connection **newc;
1005 peerData *newg;
1006 losePeerData *d;
1007 int i;
1008
1009 // complex
1011
1012 // reallocate arrays
1014 try {
1017 } catch (...) {
1018 fprintf(stderr, "vrpn_PeerMutex::addPeer: Out of memory.\n");
1019 return false;
1020 }
1021 for (i = 0; i < d_numPeers; i++) {
1022 newc[i] = d_peer[i];
1023 newg[i] = d_peerData[i];
1024 }
1025 if (d_peer) {
1026 try {
1027 delete[] d_peer;
1028 } catch (...) {
1029 fprintf(stderr, "vrpn_PeerMutex::addPeer(): delete failed\n");
1030 return false;
1031 }
1032 }
1033 if (d_peerData) {
1034 try {
1035 delete[] d_peerData;
1036 } catch (...) {
1037 fprintf(stderr, "vrpn_PeerMutex::addPeer(): delete failed\n");
1038 return false;
1039 }
1040 }
1041 d_peer = newc;
1042 d_peerData = newg;
1043 }
1045 // d_peerData[d_numPeers].grantedLock = vrpn_false;
1046
1047 try { d = new losePeerData; }
1048 catch (...) {
1049 fprintf(stderr, "vrpn_PeerMutex::addPeer: Out of memory.\n");
1050 return false;
1051 }
1052 d->connection = d_peer[d_numPeers];
1053 d->mutex = this;
1054 vrpn_int32 control;
1055 vrpn_int32 drop;
1059
1060#ifdef VERBOSE
1061 fprintf(stderr, "vrpn_PeerMutex::addPeer: added peer named %s.\n",
1062 stationName);
1063#endif
1064
1065 d_numPeers++;
1066 return true;
1067}
1068
1069vrpn_bool vrpn_PeerMutex::addRequestGrantedCallback(void *ud, int (*f)(void *))
1070{
1071 mutexCallback *cb = NULL;
1072 try { cb = new mutexCallback; }
1073 catch (...) {
1074 fprintf(stderr, "vrpn_PeerMutex::addRequestGrantedCallback: "
1075 "Out of memory.\n");
1076 return false;
1077 }
1078
1079 cb->userdata = ud;
1080 cb->f = f;
1081 cb->next = d_reqGrantedCB;
1082 d_reqGrantedCB = cb;
1083 return true;
1084}
1085
1086vrpn_bool vrpn_PeerMutex::addRequestDeniedCallback(void *ud, int (*f)(void *))
1087{
1088 mutexCallback *cb = NULL;
1089 try { cb = new mutexCallback; }
1090 catch (...) {
1091 fprintf(stderr, "vrpn_PeerMutex::addRequestDeniedCallback: "
1092 "Out of memory.\n");
1093 return false;
1094 }
1095
1096 cb->userdata = ud;
1097 cb->f = f;
1098 cb->next = d_reqDeniedCB;
1099 d_reqDeniedCB = cb;
1100 return true;
1101}
1102
1103vrpn_bool vrpn_PeerMutex::addTakeCallback(void *ud, int (*f)(void *))
1104{
1105 mutexCallback *cb = NULL;
1106 try { cb = new mutexCallback; }
1107 catch (...) {
1108 fprintf(stderr, "vrpn_PeerMutex::addTakeCallback: Out of memory.\n");
1109 return false;
1110 }
1111
1112 cb->userdata = ud;
1113 cb->f = f;
1114 cb->next = d_takeCB;
1115 d_takeCB = cb;
1116 return true;
1117}
1118
1119// static
1120vrpn_bool vrpn_PeerMutex::addReleaseCallback(void *ud, int (*f)(void *))
1121{
1122 mutexCallback *cb = NULL;
1123 try { cb = new mutexCallback; }
1124 catch (...) {
1125 fprintf(stderr, "vrpn_PeerMutex::addReleaseCallback: "
1126 "Out of memory.\n");
1127 return false;
1128 }
1129
1130 cb->userdata = ud;
1131 cb->f = f;
1132 cb->next = d_releaseCB;
1133 d_releaseCB = cb;
1134 return true;
1135}
1136
1137// static
1139{
1140 vrpn_PeerMutex *me = (vrpn_PeerMutex *)userdata;
1141 const char *b = p.buffer;
1142 vrpn_uint32 senderIP;
1143 vrpn_uint32 senderPort;
1144 int i;
1145
1146 vrpn_unbuffer(&b, &senderIP);
1147 vrpn_unbuffer(&b, &senderPort);
1148
1149// This function is where we're n^2. If we could look up the peer
1150// given their IP number we could be 2n instead.
1151
1152#ifdef VERBOSE
1153 in_addr nad;
1154 nad.s_addr = htonl(senderIP);
1155 fprintf(stderr,
1156 "vrpn_PeerMutex::handle_request: got one from %s port %d.\n",
1157 inet_ntoa(nad), senderPort);
1158#endif
1159
1160 // If several nodes request the lock at once, ties are broken in favor
1161 // of the node with the lowest IP number & port.
1162
1163 if ((me->d_state == AVAILABLE) ||
1164 (((me->d_state == HELD_REMOTELY) || (me->d_state == REQUESTING)) &&
1165 ((senderIP < me->d_holderIP) ||
1166 ((senderIP == me->d_holderIP) &&
1167 ((vrpn_int32)senderPort < me->d_holderPort))))) {
1168
1169 me->d_holderIP = senderIP;
1170 me->d_holderPort = senderPort;
1171
1172 if (me->d_state != HELD_REMOTELY) {
1174 }
1175
1176 me->d_state = HELD_REMOTELY;
1177 for (i = 0; i < me->d_numPeers; i++) {
1178 me->sendGrantRequest(me->d_peer[i], senderIP, senderPort);
1179 }
1180 return 0;
1181 }
1182
1183 for (i = 0; i < me->d_numPeers; i++) {
1184 me->sendDenyRequest(me->d_peer[i], senderIP, senderPort);
1185 }
1186
1187 return 0;
1188}
1189
1190// static
1192{
1193 vrpn_PeerMutex *me = (vrpn_PeerMutex *)userdata;
1194 const char *b = p.buffer;
1195 vrpn_uint32 senderIP;
1196 vrpn_uint32 senderPort;
1197
1198 vrpn_unbuffer(&b, &senderIP);
1199 vrpn_unbuffer(&b, &senderPort);
1200
1201#ifdef VERBOSE
1202 in_addr nad;
1203
1204 nad.s_addr = senderIP;
1205 fprintf(stderr,
1206 "vrpn_PeerMutex::handle_release: got one from %s port %d.\n",
1207 inet_ntoa(nad), senderPort);
1208#endif
1209
1210 if ((senderIP != me->d_holderIP) ||
1211 ((vrpn_int32)senderPort != me->d_holderPort)) {
1212 fprintf(stderr, "vrpn_PeerMutex::handle_release: Got a release from "
1213 "somebody who didn't have the lock!?\n");
1214 }
1215
1216 me->d_state = AVAILABLE;
1217 me->d_holderIP = 0;
1218 me->d_holderPort = -1;
1219
1221
1222 return 0;
1223}
1224
1225// static
1227{
1228 vrpn_PeerMutex *me = (vrpn_PeerMutex *)userdata;
1229 const char *b = p.buffer;
1230 vrpn_uint32 senderIP;
1231 vrpn_uint32 senderPort;
1232
1233 vrpn_unbuffer(&b, &senderIP);
1234 vrpn_unbuffer(&b, &senderPort);
1235
1236#ifdef VERBOSE
1237 in_addr nad;
1238 nad.s_addr = senderIP;
1239 fprintf(stderr, "vrpn_PeerMutex::handle_grantRequest: "
1240 "got one for %s port %d.\n",
1241 inet_ntoa(nad), senderPort);
1242#endif
1243
1244 if ((senderIP != me->d_myIP) || (senderPort != me->d_myPort)) {
1245 // we can treat this as a denial -
1246 // but we'll get a denial eventually,
1247 // so we need not do so.
1248 return 0;
1249 }
1250
1252
1253 me->checkGrantMutex();
1254
1255 return 0;
1256}
1257
1258// static
1260{
1261 vrpn_PeerMutex *me = (vrpn_PeerMutex *)userdata;
1262 const char *b = p.buffer;
1263 vrpn_uint32 senderIP;
1264 vrpn_uint32 senderPort;
1265
1266 vrpn_unbuffer(&b, &senderIP);
1267 vrpn_unbuffer(&b, &senderPort);
1268
1269#ifdef VERBOSE
1270 in_addr nad;
1271 nad.s_addr = senderIP;
1272 fprintf(stderr, "vrpn_PeerMutex::handle_denyRequest: "
1273 "got one for %s port %d.\n",
1274 inet_ntoa(nad), senderPort);
1275#endif
1276
1277 if ((senderIP != me->d_myIP) || (senderPort != me->d_myPort)) {
1278 return 0;
1279 }
1280
1281 me->d_numPeersGrantingLock = 0;
1282
1284
1285 me->d_state = HELD_REMOTELY;
1286
1287 return 0;
1288}
1289
1290// static
1292{
1293 losePeerData *data = (losePeerData *)userdata;
1294 vrpn_PeerMutex *me = data->mutex;
1295 vrpn_Connection *c = data->connection;
1296 int i;
1297
1298 // Need to abort a request since we don't have enough data to correctly
1299 // compensate for losing a peer mid-request.
1300
1301 if (me->d_state == REQUESTING) {
1302 me->release();
1303 }
1304
1305 for (i = 0; i < me->d_numPeers; i++) {
1306 if (c == me->d_peer[i]) {
1307 break;
1308 }
1309 }
1310 if (i == me->d_numPeers) {
1311 fprintf(stderr,
1312 "vrpn_PeerMutex::handle_losePeer: Can't find lost peer.\n");
1313 return 0; // -1?
1314 }
1315
1316 fprintf(stderr, "vrpn_PeerMutex::handle_losePeer: lost peer #%d.\n", i);
1317
1318 if (me->d_peer[i]) {
1319 me->d_peer[i]->removeReference();
1320 }
1321 me->d_numPeers--;
1322 me->d_peer[i] = me->d_peer[me->d_numPeers];
1323
1324 try {
1325 delete data;
1326 } catch (...) {
1327 fprintf(stderr, "vrpn_PeerMutex::handle_losePeer(): delete failed\n");
1328 return -1;
1329 }
1330
1331 return 0;
1332}
1333
1335{
1336 timeval now;
1337 char buffer[32];
1338 char *b = buffer;
1339 vrpn_int32 bl = 32;
1340
1341 vrpn_gettimeofday(&now, NULL);
1342 vrpn_buffer(&b, &bl, d_myIP);
1343 vrpn_buffer(&b, &bl, d_myPort);
1344 c->pack_message(32 - bl, now, c->register_message_type(requestMutex_type),
1345 c->register_sender(d_mutexName), buffer,
1347}
1348
1350{
1351 timeval now;
1352 char buffer[32];
1353 char *b = buffer;
1354 vrpn_int32 bl = 32;
1355
1356 vrpn_gettimeofday(&now, NULL);
1357 vrpn_buffer(&b, &bl, d_myIP);
1358 vrpn_buffer(&b, &bl, d_myPort);
1359 c->pack_message(32 - bl, now, c->register_message_type(release_type),
1360 c->register_sender(d_mutexName), buffer,
1362}
1363
1365 vrpn_uint32 port)
1366{
1367 timeval now;
1368 char buffer[32];
1369 char *b = buffer;
1370 vrpn_int32 bl = 32;
1371
1372 vrpn_gettimeofday(&now, NULL);
1373 vrpn_buffer(&b, &bl, IP);
1374 vrpn_buffer(&b, &bl, port);
1375 c->pack_message(32 - bl, now, c->register_message_type(grantRequest_type),
1376 c->register_sender(d_mutexName), buffer,
1378}
1379
1381 vrpn_uint32 port)
1382{
1383 timeval now;
1384 char buffer[32];
1385 char *b = buffer;
1386 vrpn_int32 bl = 32;
1387
1388 vrpn_gettimeofday(&now, NULL);
1389 vrpn_buffer(&b, &bl, IP);
1390 vrpn_buffer(&b, &bl, port);
1391 c->pack_message(32 - bl, now, c->register_message_type(denyRequest_type),
1392 c->register_sender(d_mutexName), buffer,
1394}
1395
1397{
1398 mutexCallback *cb;
1399
1400 // trigger callbacks
1401 for (cb = d_reqGrantedCB; cb; cb = cb->next) {
1402 (cb->f)(cb->userdata);
1403 }
1404}
1405
1407{
1408 mutexCallback *cb;
1409
1410 // trigger callbacks
1411 for (cb = d_reqDeniedCB; cb; cb = cb->next) {
1412 (cb->f)(cb->userdata);
1413 }
1414}
1415
1417{
1418 mutexCallback *cb;
1419
1420 // trigger callbacks
1421 for (cb = d_takeCB; cb; cb = cb->next) {
1422 (cb->f)(cb->userdata);
1423 }
1424}
1425
1427{
1428 mutexCallback *cb;
1429
1430 // trigger callbacks
1431 for (cb = d_releaseCB; cb; cb = cb->next) {
1432 (cb->f)(cb->userdata);
1433 }
1434}
1435
1437{
1438
1440 d_state = OURS;
1441
1444 }
1445}
1446
1447void vrpn_PeerMutex::init(const char *name)
1448{
1449 d_mutexName = NULL;
1450 try {
1451 size_t n = 1 + strlen(name);
1452 d_mutexName = new char[n];
1453 // This is guaranteed to fit because of the new allocation above.
1454 strncpy(d_mutexName, name, n);
1455 } catch (...) {
1456 fprintf(stderr, "vrpn_PeerMutex::init: Out of memory.\n");
1457 }
1458
1460 d_request_type = d_server->register_message_type(requestMutex_type);
1464
1468 d_myId);
1470 d_myId);
1471}
Generic connection class not specific to the transport mechanism.
void addReference()
Counting references to this connection.
virtual vrpn_int32 register_message_type(const char *name)
virtual vrpn_bool connected(void) const
Returns vrpn_true if the connection has been established, vrpn_false if not (For a networkless connec...
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...
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...
virtual int unregister_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
void setAutoDeleteStatus(bool setvalue)
Specify whether this connection should be deleted automatically when it is no longer need (reference ...
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...
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...
void triggerTakeCallbacks(void)
Definition vrpn_Mutex.C:743
static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM)
Definition vrpn_Mutex.C:587
static int VRPN_CALLBACK handle_initialize(void *, vrpn_HANDLERPARAM)
Definition vrpn_Mutex.C:652
vrpn_bool d_requestBeforeInit
Definition vrpn_Mutex.h:118
vrpn_bool addTakeCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer gets the mutex.
Definition vrpn_Mutex.C:551
virtual ~vrpn_Mutex_Remote(void)
Definition vrpn_Mutex.C:404
static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM)
Definition vrpn_Mutex.C:613
vrpn_bool addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
Definition vrpn_Mutex.C:515
void requestIndex(void)
Definition vrpn_Mutex.C:440
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:425
mutexCallback * d_reqGrantedCB
Definition vrpn_Mutex.h:140
void triggerReleaseCallbacks(void)
Definition vrpn_Mutex.C:753
mutexCallback * d_reqDeniedCB
Definition vrpn_Mutex.h:141
mutexCallback * d_takeCB
Definition vrpn_Mutex.h:142
void triggerDenyCallbacks(void)
Definition vrpn_Mutex.C:733
mutexCallback * d_releaseCB
Definition vrpn_Mutex.h:143
vrpn_bool isHeldLocally(void) const
True from when RequestGranted callbacks are triggered until release() is called.
Definition vrpn_Mutex.C:430
void triggerGrantCallbacks(void)
Definition vrpn_Mutex.C:723
void request(void)
Request the distributed lock. Does not request the lock if !isAvailable(), instead automatically trig...
Definition vrpn_Mutex.C:472
static int VRPN_CALLBACK handle_releaseNotification(void *, vrpn_HANDLERPARAM)
Definition vrpn_Mutex.C:636
static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM)
Definition vrpn_Mutex.C:714
vrpn_int32 d_myIndex
Definition vrpn_Mutex.h:117
vrpn_bool addReleaseCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer releases the mutex.
Definition vrpn_Mutex.C:569
vrpn_bool addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
Definition vrpn_Mutex.C:533
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:435
vrpn_Mutex_Remote(const char *name, vrpn_Connection *=NULL)
Definition vrpn_Mutex.C:372
void release(void)
Release the distributed lock. Does nothing if !isHeldLocally() and there isn't a request pending.
Definition vrpn_Mutex.C:500
static int VRPN_CALLBACK handle_requestMutex(void *, vrpn_HANDLERPARAM)
Definition vrpn_Mutex.C:265
static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM)
Definition vrpn_Mutex.C:294
virtual ~vrpn_Mutex_Server(void)
Definition vrpn_Mutex.C:246
static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM)
Definition vrpn_Mutex.C:349
vrpn_int32 d_remoteIndex
Counts remotes who have had IDs issued to them.
Definition vrpn_Mutex.h:58
static int VRPN_CALLBACK handle_requestIndex(void *, vrpn_HANDLERPARAM)
Definition vrpn_Mutex.C:309
vrpn_Mutex_Server(const char *name, vrpn_Connection *=NULL)
Definition vrpn_Mutex.C:225
static int VRPN_CALLBACK handle_dropLastConnection(void *, vrpn_HANDLERPARAM)
Definition vrpn_Mutex.C:356
vrpn_int32 d_requestMutex_type
Definition vrpn_Mutex.h:33
void sendRelease(void)
Definition vrpn_Mutex.C:176
vrpn_Connection * d_connection
Definition vrpn_Mutex.h:29
vrpn_int32 d_release_type
Definition vrpn_Mutex.h:34
vrpn_int32 d_initialize_type
Definition vrpn_Mutex.h:38
vrpn_int32 d_requestIndex_type
Definition vrpn_Mutex.h:32
void sendDenyRequest(vrpn_int32 index)
Definition vrpn_Mutex.C:211
vrpn_int32 d_denyRequest_type
Definition vrpn_Mutex.h:37
vrpn_Mutex(const char *name, vrpn_Connection *=NULL)
Definition vrpn_Mutex.C:116
void mainloop(void)
Definition vrpn_Mutex.C:154
void sendRequest(vrpn_int32 index)
Definition vrpn_Mutex.C:162
vrpn_int32 d_myId
Definition vrpn_Mutex.h:31
void sendReleaseNotification(void)
Definition vrpn_Mutex.C:187
void sendGrantRequest(vrpn_int32 index)
Definition vrpn_Mutex.C:197
vrpn_int32 d_grantRequest_type
Definition vrpn_Mutex.h:36
virtual ~vrpn_Mutex(void)=0
Definition vrpn_Mutex.C:147
vrpn_int32 d_releaseNotification_type
Definition vrpn_Mutex.h:35
vrpn_PeerMutex
Definition vrpn_Mutex.h:196
vrpn_Connection * d_server
Receive on this connection.
Definition vrpn_Mutex.h:261
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_int32 d_holderPort
Definition vrpn_Mutex.h:273
mutexCallback * d_releaseCB
Definition vrpn_Mutex.h:314
void triggerTakeCallbacks(void)
void triggerReleaseCallbacks(void)
static int VRPN_CALLBACK handle_losePeer(void *, vrpn_HANDLERPARAM)
void init(const char *name)
vrpn_bool addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
vrpn_bool addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
vrpn_bool addPeer(const char *stationName)
Takes a VRPN station name of the form "<host>:<port>".
static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM)
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_uint32 d_holderIP
Definition vrpn_Mutex.h:272
vrpn_Connection ** d_peer
Send on these connections to other Mutex's well-known-ports.
Definition vrpn_Mutex.h:263
vrpn_bool addReleaseCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer releases the mutex.
void triggerDenyCallbacks(void)
char * d_mutexName
Definition vrpn_Mutex.h:253
void release(void)
Release the distributed lock. Does nothing if !isHeldLocally() and there isn't a request pending.
Definition vrpn_Mutex.C:973
static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM)
vrpn_bool isHeldLocally(void) const
True from when RequestGranted callbacks are triggered until release() is called.
Definition vrpn_Mutex.C:903
void sendGrantRequest(vrpn_Connection *, vrpn_uint32 IPnumber, vrpn_uint32 PortNumber)
void triggerGrantCallbacks(void)
static int VRPN_CALLBACK handle_request(void *, vrpn_HANDLERPARAM)
mutexCallback * d_reqDeniedCB
Definition vrpn_Mutex.h:312
vrpn_int32 d_release_type
Definition vrpn_Mutex.h:277
~vrpn_PeerMutex(void)
If isHeldLocally(), calls release().
Definition vrpn_Mutex.C:851
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:908
vrpn_int32 d_denyRequest_type
Definition vrpn_Mutex.h:279
void sendRequest(vrpn_Connection *)
vrpn_uint32 d_myIP
Definition vrpn_Mutex.h:270
vrpn_uint32 d_myPort
Definition vrpn_Mutex.h:271
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:898
mutexCallback * d_takeCB
Definition vrpn_Mutex.h:313
vrpn_int32 d_grantRequest_type
Definition vrpn_Mutex.h:278
void sendDenyRequest(vrpn_Connection *, vrpn_uint32 IPnumber, vrpn_uint32 PortNumber)
void sendRelease(vrpn_Connection *)
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:779
static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM)
vrpn_int32 d_myId
Definition vrpn_Mutex.h:275
void checkGrantMutex(void)
void request(void)
Request the distributed lock. Does not request the lock if !isAvailable(), instead automatically trig...
Definition vrpn_Mutex.C:927
void mainloop(void)
Definition vrpn_Mutex.C:915
int numPeers(void) const
Definition vrpn_Mutex.C:913
int d_numConnectionsAllocated
Dynamic array size for d_peer and d_peerGrantedLock.
Definition vrpn_Mutex.h:267
vrpn_int32 d_request_type
Definition vrpn_Mutex.h:276
vrpn_bool addTakeCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer gets the mutex. (If several peers are competing for the m...
mutexCallback * d_reqGrantedCB
Definition vrpn_Mutex.h:311
This structure is what is passed to a vrpn_Connection message callback.
const char * buffer
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_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).
char * vrpn_copy_service_name(const char *fullname)
const char * vrpn_dropped_last_connection
const char * vrpn_dropped_connection
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).
const char * vrpn_got_connection
const vrpn_uint32 vrpn_CONNECTION_RELIABLE
Classes of service for messages, specify multiple by ORing them together Priority of satisfying these...
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.
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.
#define vrpn_gettimeofday
Definition vrpn_Shared.h:99