36#define ALL_ASSERT(exp, msg) \
38 fprintf(stderr, "\nAssertion failed! \n %s (%s, %d)\n", msg, __FILE__, \
44 : cResources(cNumResources)
50bool vrpn_Semaphore::init()
52 if (vrpn_Semaphore::ppaArena == NULL) {
53 vrpn_Semaphore::allocArena();
55 if (cResources == 1) {
59 if ((l = usnewlock(vrpn_Semaphore::ppaArena)) == NULL) {
60 fprintf(stderr,
"vrpn_Semaphore::vrpn_Semaphore: error allocating "
61 "lock from arena.\n");
68 if ((ps = usnewsema(vrpn_Semaphore::ppaArena, cResources)) == NULL) {
69 fprintf(stderr,
"vrpn_Semaphore::vrpn_Semaphore: error allocating "
70 "semaphore from arena.\n");
77bool vrpn_Semaphore::init()
81 int numMax = cResources;
85 hSemaphore = CreateSemaphore(NULL, cResources, numMax, NULL);
91 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
92 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
94 (LPTSTR)&lpMsgBuf, 0, NULL);
96 "vrpn_Semaphore::vrpn_Semaphore: error creating semaphore, "
97 "WIN32 CreateSemaphore call caused the following error: %s\n",
105#elif defined(__APPLE__)
106bool vrpn_Semaphore::init()
109 int numMax = cResources;
114 sprintf(tempname,
"/tmp/vrpn_sem.XXXXXXX");
115 semaphore = sem_open(mktemp(tempname), O_CREAT, 0600, numMax);
116 if (semaphore == SEM_FAILED) {
117 perror(
"vrpn_Semaphore::vrpn_Semaphore: error opening semaphore");
124bool vrpn_Semaphore::init()
128 int numMax = cResources;
132 try { semaphore =
new sem_t; }
133 catch (...) {
return false; }
134 if (sem_init(semaphore, 0, numMax) != 0) {
135 perror(
"vrpn_Semaphore::vrpn_Semaphore: error initializing semaphore");
143bool vrpn_Semaphore::destroy()
146 usfreelock(l, vrpn_Semaphore::ppaArena);
149 usfreesema(ps, vrpn_Semaphore::ppaArena);
154bool vrpn_Semaphore::destroy()
156 if (!CloseHandle(hSemaphore)) {
161 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
162 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
164 (LPTSTR)&lpMsgBuf, 0, NULL);
166 "vrpn_Semaphore::destroy: error destroying semaphore, "
167 "WIN32 CloseHandle call caused the following error: %s\n",
176bool vrpn_Semaphore::destroy()
180 if (sem_close(semaphore) != 0) {
181 perror(
"vrpn_Semaphore::destroy: error destroying semaphore.");
185 if (sem_destroy(semaphore) != 0) {
187 "vrpn_Semaphore::destroy: error destroying semaphore.\n");
193 fprintf(stderr,
"vrpn_Semaphore::destroy(): delete failed\n");
207 "vrpn_Semaphore::~vrpn_Semaphore: error destroying semaphore.\n");
214 cResources = cNumResources;
219 fprintf(stderr,
"vrpn_Semaphore::reset: error destroying semaphore.\n");
224 "vrpn_Semaphore::reset: error initializing semaphore.\n");
236 if (ussetlock(l) != 1) {
237 perror(
"vrpn_Semaphore::p: ussetlock:");
242 if (uspsema(ps) != 1) {
243 perror(
"vrpn_Semaphore::p: uspsema:");
248 switch (WaitForSingleObject(hSemaphore, INFINITE)) {
253 ALL_ASSERT(0,
"vrpn_Semaphore::p: infinite wait time timed out!");
257 ALL_ASSERT(0,
"vrpn_Semaphore::p: thread holding resource died");
265 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
266 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
268 (LPTSTR)&lpMsgBuf, 0, NULL);
270 "vrpn_Semaphore::p: error waiting for resource, "
271 "WIN32 WaitForSingleObject call caused the following error: %s",
278 ALL_ASSERT(0,
"vrpn_Semaphore::p: unknown return code");
283 if (sem_wait(semaphore) != 0) {
284 perror(
"vrpn_Semaphore::p: ");
296 if (usunsetlock(l)) {
297 perror(
"vrpn_Semaphore::v: usunsetlock:");
303 perror(
"vrpn_Semaphore::v: uspsema:");
308 if (!ReleaseSemaphore(hSemaphore, 1, NULL)) {
313 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
314 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
316 (LPTSTR)&lpMsgBuf, 0, NULL);
318 "vrpn_Semaphore::v: error v'ing semaphore, "
319 "WIN32 ReleaseSemaphore call caused the following error: %s",
327 if (sem_post(semaphore) != 0) {
328 perror(
"vrpn_Semaphore::p: ");
343 iRetVal = uscsetlock(l, 0);
345 perror(
"vrpn_Semaphore::condP: uscsetlock:");
350 iRetVal = uscpsema(ps);
352 perror(
"vrpn_Semaphore::condP: uscpsema:");
357 switch (WaitForSingleObject(hSemaphore, 0)) {
366 ALL_ASSERT(0,
"vrpn_Semaphore::condP: thread holding resource died");
374 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
375 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
377 (LPTSTR)&lpMsgBuf, 0, NULL);
379 "Semaphore::condP: error waiting for resource, "
380 "WIN32 WaitForSingleObject call caused the following error: %s",
387 ALL_ASSERT(0,
"vrpn_Semaphore::p: unknown return code");
392 iRetVal = sem_trywait(semaphore);
396 else if (errno == EAGAIN) {
400 perror(
"vrpn_Semaphore::condP: ");
411usptr_t *vrpn_Semaphore::ppaArena = NULL;
415#include <sys/types.h>
418void vrpn_Semaphore::allocArena()
423 if ((ppaArena = usinit(
"/dev/zero")) == NULL) {
424 perror(
"vrpn_Thread::allocArena: usinit:");
454 int result = sem_.
p();
455 handleLockResult_(result);
464 int result = sem_.
condP();
465 handleLockResult_(result);
473 int result = sem_.
v();
474 ALL_ASSERT(result == 0,
"failed to unlock semaphore!");
478 void SemaphoreGuard::handleLockResult_(
int result)
490 : pfThread(pfThreadparm)
499 fprintf(stderr,
"vrpn_Thread::go: already running\n");
505 ((
unsigned long)-1)) {
506 perror(
"vrpn_Thread::go: sproc");
510#elif defined(_WIN32) && !defined(__CYGWIN__)
513 ((
unsigned long)-1)) {
514 perror(
"vrpn_Thread::go: _beginthread");
520 perror(
"vrpn_Thread::go:pthread_create: ");
530#if defined(sgi) || defined(_WIN32)
534 perror(
"vrpn_Thread::kill: kill:");
539 if (!TerminateThread((HANDLE)
threadID, 1)) {
541 "vrpn_Thread::kill: problem with terminateThread call.\n");
549 if (pthread_detach(
threadID) != 0) {
550 perror(
"vrpn_Thread::kill:pthread_detach: ");
553 if (pthread_kill(
threadID, SIGKILL) != 0) {
554 perror(
"vrpn_Thread::kill:pthread_kill: ");
560 fprintf(stderr,
"vrpn_Thread::kill: thread is not currently alive.\n");
573#ifdef vrpn_THREADS_AVAILABLE
589#if !defined(sgi) && !defined(_WIN32)
591 if (pthread_detach(pth->
threadID) != 0) {
592 perror(
"vrpn_Thread::threadFuncShell:pthread_detach: ");
615#include <sys/param.h>
616#include <sys/sysctl.h>
623 SYSTEM_INFO siSysInfo;
624 GetSystemInfo(&siSysInfo);
625 return siSysInfo.dwNumberOfProcessors;
630 FILE *f = fopen(
"/proc/cpuinfo",
"r");
633 perror(
"vrpn_Thread::number_of_processors:fopen: ");
638 while (fgets(line,
sizeof(line), f) != NULL) {
639 if (strncmp(line,
"processor\t:", strlen(
"processor\t:")) == 0) {
647 "vrpn_Thread::number_of_processors: Found zero, returning 1\n");
654 size_t size =
sizeof(count);
655 if (sysctlbyname(
"hw.ncpu", &count, &size, NULL, 0)) {
659 return static_cast<unsigned>(count);
663 fprintf(stderr,
"vrpn_Thread::number_of_processors: Not yet implemented on "
664 "this architecture.\n");
675 if (threadData.
pvUD == NULL) {
676 fprintf(stderr,
"vrpn_test_thread_body(): pvUD is NULL\n");
695 const unsigned sem_count = 5;
698 for (i = 0; i < sem_count; i++) {
699 if (s.
condP() != 1) {
700 fprintf(stderr,
"vrpn_test_threads_and_semaphores(): Semaphore ran "
705 if (s.
condP() != 0) {
706 fprintf(stderr,
"vrpn_test_threads_and_semaphores(): Semaphore had too "
710 for (i = 0; i < sem_count; i++) {
712 fprintf(stderr,
"vrpn_test_threads_and_semaphores(): Could not "
713 "release Semaphore\n");
717 for (i = 0; i < sem_count; i++) {
718 if (s.
condP() != 1) {
719 fprintf(stderr,
"vrpn_test_threads_and_semaphores(): Semaphore ran "
720 "out of counts, round 2\n");
724 if (s.
condP() != 0) {
725 fprintf(stderr,
"vrpn_test_threads_and_semaphores(): Semaphore had too "
726 "many counts, round 2\n");
747 if (num_procs == 0) {
748 fprintf(stderr,
"vrpn_test_threads_and_semaphores(): "
749 "vrpn_Thread::number_of_processors() returned zero\n");
760 fprintf(stderr,
"vrpn_test_threads_and_semaphores(): thread-test "
761 "Semaphore had no count\n");
764 if (sem.
condP() != 0) {
765 fprintf(stderr,
"vrpn_test_threads_and_semaphores(): thread-test "
766 "Semaphore had too many counts\n");
772 "vrpn_test_threads_and_semaphores(): Could not start thread\n");
775 struct timeval start;
779 if (sem.
condP() == 1) {
788 if (diff.tv_sec >= 3) {
790 "vrpn_test_threads_and_semaphores(): Thread didn't run\n");
bool try_to_lock()
Tries to lock - returns true if we locked it.
void unlock()
Unlocks the resource, if we have locked it.
SemaphoreGuard(vrpn_Semaphore &sem)
Constructor that locks (p) the semaphore.
void lock()
Locks the semaphore, if we haven't locked it already.
~SemaphoreGuard()
Destructor that unlocks if we've locked.
int v()
Release of resource. ("up")
~vrpn_Semaphore()
destructor
vrpn_Semaphore(int cNumResources=1)
constructor - mutex by default (0 is a sync primitive)
bool reset(int cNumResources=1)
routine to reset it (true on success, false on failure) (may create new semaphore)
int numResources()
read values
int condP()
Non-blocking attempt to acquire resource ("down")
int p()
Blocking acquire of resource. ("down")
static void * threadFuncShellPosix(void *pvThread)
static void threadFuncShell(void *pvThread)
static unsigned number_of_processors()
void(* pfThread)(vrpn_ThreadData &ThreadData)
vrpn_Thread(vrpn_THREAD_FUNC pfThread, vrpn_ThreadData td)
void userData(void *pvNewUserData)
timeval vrpn_TimevalDiff(const timeval &tv1, const timeval &tv2)
void vrpn_SleepMsecs(double dMilliSecs)
#define vrpn_gettimeofday
#define ALL_ASSERT(exp, msg)
Header containing vrpn_Thread, vrpn_Semaphore (formerly in vrpn_Shared.h), as well as a lock-guard cl...
bool vrpn_test_threads_and_semaphores(void)