vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Shared.h
Go to the documentation of this file.
1 #pragma once
2 
3 // Horrible hack for old HPUX compiler
4 #ifdef hpux
5 #ifndef true
6 #define bool int
7 #define true 1
8 #define false 0
9 #endif
10 #endif
11 
12 #include "vrpn_Configure.h" // for VRPN_API
13 #include "vrpn_Types.h" // for vrpn_int32, vrpn_float64, etc
14 #include <string.h> // for memcpy()
15 #include <stdio.h> // for fprintf()
16 
17 #if defined(__ANDROID__)
18 #include <bitset>
19 #endif
20 
21 // IWYU pragma: no_include <bits/time.h>
22 
23 // Oct 2000: Sang-Uok changed because vrpn code was compiling but giving
24 // runtime errors with cygwin 1.1. I changed the code so it only uses unix
25 // code. I had to change includes in various files.
26 
27 // jan 2000: jeff changing the way sockets are used with cygwin. I made this
28 // change because I realized that we were using winsock stuff in some places,
29 // and cygwin stuff in others. Discovered this when our code wouldn't compile
30 // in cygwin-1.0 (but it did in cygwin-b20.1).
31 
32 // let's start with a clean slate
33 #undef VRPN_USE_WINSOCK_SOCKETS
34 
35 // Does cygwin use winsock sockets or unix sockets
36 //#define VRPN_CYGWIN_USES_WINSOCK_SOCKETS
37 
38 #if defined(_WIN32) && \
39  (!defined(__CYGWIN__) || defined(VRPN_CYGWIN_USES_WINSOCK_SOCKETS))
40 #define VRPN_USE_WINSOCK_SOCKETS
41 #endif
42 
43 #ifndef VRPN_USE_WINSOCK_SOCKETS
44 // On Win32, this constant is defined as ~0 (sockets are unsigned ints)
45 #define INVALID_SOCKET -1
46 #define SOCKET int
47 #endif
48 
49 #if !(defined(_WIN32) && defined(VRPN_USE_WINSOCK_SOCKETS))
50 #include <sys/select.h> // for select
51 #include <netinet/in.h> // for htonl, htons
52 #endif
53 
54 #ifdef _WIN32_WCE
55 #define perror(x) fprintf(stderr, "%s\n", x);
56 #endif
57 
58 // comment from vrpn_Connection.h reads :
59 //
60 // gethostbyname() fails on SOME Windows NT boxes, but not all,
61 // if given an IP octet string rather than a true name.
62 // Until we figure out WHY, we have this extra clause in here.
63 // It probably wouldn't hurt to enable it for non-NT systems
64 // as well.
65 #ifdef _WIN32
66 #define VRPN_USE_WINDOWS_GETHOSTBYNAME_HACK
67 #endif
68 
69 //--------------------------------------------------------------
70 // Timeval defines. These are a bit hairy. The basic problem is
71 // that Windows doesn't implement gettimeofday(), nor does it
72 // define "struct timezone", although Winsock.h does define
73 // "struct timeval". The painful solution has been to define a
74 // vrpn_gettimeofday() function that takes a void * as a second
75 // argument (the timezone) and have all VRPN code call this function
76 // rather than gettimeofday(). On non-WINSOCK implementations,
77 // we alias vrpn_gettimeofday() right back to gettimeofday(), so
78 // that we are calling the system routine. On Windows, we will
79 // be using vrpn_gettimofday(). So far so good, but now user code
80 // would like to not have to know the difference under windows, so
81 // we have an optional VRPN configuration setting in vrpn_Configure.h
82 // that exports vrpn_gettimeofday() as gettimeofday() and also
83 // exports a "struct timezone" definition. Yucky, but it works and
84 // lets user code use the VRPN one as if it were the system call
85 // on Windows.
86 
87 #if (!defined(VRPN_USE_WINSOCK_SOCKETS))
88 #include <sys/time.h> // for timeval, timezone, gettimeofday
89 #define vrpn_gettimeofday gettimeofday
90 #else // winsock sockets
91 
92 // These are a pair of horrible hacks that instruct Windows include
93 // files to (1) not define min() and max() in a way that messes up
94 // standard-library calls to them, and (2) avoids pulling in a large
95 // number of Windows header files. They are not used directly within
96 // the VRPN library, but rather within the Windows include files to
97 // change the way they behave.
98 
99 #ifndef NOMINMAX
100 #define NOMINMAX
101 #endif
102 #ifndef WIN32_LEAN_AND_MEAN
103 #define WIN32_LEAN_AND_MEAN
104 #endif
105 #include <windows.h>
106 #ifndef _WIN32_WCE
107 #include <sys/timeb.h>
108 #endif
109 #ifdef VRPN_USE_WINSOCK2
110 #include <winsock2.h> // struct timeval is defined here
111 #else
112 #include <winsock.h> // struct timeval is defined here
113 #endif
114 
115 // Whether or not we export gettimeofday, we declare the
116 // vrpn_gettimeofday() function.
117 extern "C" VRPN_API int vrpn_gettimeofday(struct timeval *tp, void *tzp);
118 
119 // If compiling under Cygnus Solutions Cygwin then these get defined by
120 // including sys/time.h. So, we will manually define only for _WIN32
121 // Only do this if the Configure file has set VRPN_EXPORT_GETTIMEOFDAY,
122 // so that application code can get at it. All VRPN routines should be
123 // calling vrpn_gettimeofday() directly.
124 
125 #if defined(VRPN_EXPORT_GETTIMEOFDAY) && !defined(_STRUCT_TIMEZONE) && \
126  !defined(_TIMEZONE_DEFINED)
127 #define _TIMEZONE_DEFINED
128 /* from HP-UX */
129 struct timezone {
130  int tz_minuteswest; /* minutes west of Greenwich */
131  int tz_dsttime; /* type of dst correction */
132 };
133 #endif
134 #if defined(VRPN_EXPORT_GETTIMEOFDAY) && !defined(_STRUCT_TIMEZONE)
135 #define _STRUCT_TIMEZONE
136 
137 // manually define this too. _WIN32 sans cygwin doesn't have gettimeofday
138 #define gettimeofday vrpn_gettimeofday
139 
140 #endif
141 #endif
142 
143 //--------------------------------------------------------------
144 // vrpn_* timeval utility functions
145 
146 // IMPORTANT: timevals must be normalized to make any sense
147 //
148 // * normalized means abs(tv_usec) is less than 1,000,000
149 //
150 // * TimevalSum and TimevalDiff do not do the right thing if
151 // their inputs are not normalized
152 //
153 // * TimevalScale now normalizes it's results [9/1999 it didn't before]
154 
155 // make sure tv_usec is less than 1,000,000
156 extern VRPN_API struct timeval vrpn_TimevalNormalize(const struct timeval &tv);
157 
158 extern VRPN_API struct timeval vrpn_TimevalSum(const struct timeval &tv1,
159  const struct timeval &tv2);
160 extern VRPN_API struct timeval vrpn_TimevalDiff(const struct timeval &tv1,
161  const struct timeval &tv2);
162 extern VRPN_API struct timeval vrpn_TimevalScale(const struct timeval &tv,
163  double scale);
164 
166 extern VRPN_API unsigned long vrpn_TimevalDuration(struct timeval endT,
167  struct timeval startT);
168 
171 extern VRPN_API double vrpn_TimevalDurationSeconds(struct timeval endT,
172  struct timeval startT);
173 
174 extern VRPN_API bool vrpn_TimevalGreater(const struct timeval &tv1,
175  const struct timeval &tv2);
176 extern VRPN_API bool vrpn_TimevalEqual(const struct timeval &tv1,
177  const struct timeval &tv2);
178 
179 extern VRPN_API double vrpn_TimevalMsecs(const struct timeval &tv1);
180 
181 extern VRPN_API struct timeval vrpn_MsecsTimeval(const double dMsecs);
182 extern VRPN_API void vrpn_SleepMsecs(double dMsecs);
183 
184 //--------------------------------------------------------------
185 // vrpn_* buffer util functions and endian-ness related
186 // definitions and functions.
187 
188 // xform a double to/from network order -- like htonl and htons
189 extern VRPN_API vrpn_float64 vrpn_htond(vrpn_float64 d);
190 extern VRPN_API vrpn_float64 vrpn_ntohd(vrpn_float64 d);
191 
192 // From this we get the variable "vrpn_big_endian" set to true if the machine we
193 // are
194 // on is big endian and to false if it is little endian. This can be used by
195 // custom packing and unpacking code to bypass the buffer and unbuffer routines
196 // for cases that have to be particularly fast (like video data). It is also
197 // used
198 // internally by the vrpn_htond() function.
199 
200 static const int vrpn_int_data_for_endian_test = 1;
201 static const char *vrpn_char_data_for_endian_test =
202  (char *)(void *)(&vrpn_int_data_for_endian_test);
203 static const bool vrpn_big_endian = (vrpn_char_data_for_endian_test[0] != 1);
204 
205 // Read and write strings (not single items).
206 extern VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen,
207  const char *string, vrpn_int32 length);
208 extern VRPN_API int vrpn_unbuffer(const char **buffer, char *string,
209  vrpn_int32 length);
210 
211 // Read and write timeval.
212 extern VRPN_API int vrpn_unbuffer(const char **buffer, timeval *t);
213 extern VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen,
214  const timeval t);
215 
216 // To read and write the atomic types defined in vrpn_Types, you use the
217 // templated
218 // buffer and unbuffer routines below. These have the same form as the ones for
219 // timeval, but they use types vrpn_int, vrpn_uint, vrpn_int16, vrpn_uint16,
220 // vrpn_int32, vrpn_uint32, vrpn_float32, and vrpn_float64.
221 
236 // Copyright Iowa State University 2011.
237 // Distributed under the Boost Software License, Version 1.0.
238 // (See accompanying file LICENSE_1_0.txt or copy at
239 // http://www.boost.org/LICENSE_1_0.txt)
240 
241 // Tested in the context of vrpn_server and vrpn_print_devices running between
242 // an SGI running Irix 6.5 MIPS 32-bit (big endian) and Mac OSX intel 64-bit
243 // (little endian) machine with a NULL tracker and it worked using the SGI
244 // repaired commits from 3/17/2012.
245 
248 namespace vrpn_byte_order {
249  namespace vrpn_detail {
251  template <int TypeSize> struct uint_traits;
252 
253  template <> struct uint_traits<1> {
254  typedef vrpn_uint8 type;
255  };
256  template <> struct uint_traits<2> {
257  typedef vrpn_uint16 type;
258  };
259  template <> struct uint_traits<4> {
260  typedef vrpn_uint32 type;
261  };
262  } // end of namespace vrpn_detail
263 
265  inline vrpn_uint8 hton(vrpn_uint8 hostval) { return hostval; }
266 
268  inline vrpn_uint8 ntoh(vrpn_uint8 netval) { return netval; }
269 
271  inline vrpn_uint16 hton(vrpn_uint16 hostval) { return htons(hostval); }
272 
274  inline vrpn_uint16 ntoh(vrpn_uint16 netval) { return ntohs(netval); }
275 
277  inline vrpn_uint32 hton(vrpn_uint32 hostval) { return htonl(hostval); }
278 
280  inline vrpn_uint32 ntoh(vrpn_uint32 netval) { return ntohl(netval); }
281 
283  inline vrpn_float64 hton(vrpn_float64 hostval) { return vrpn_htond(hostval); }
284 
286  inline vrpn_float64 ntoh(vrpn_float64 netval) { return vrpn_ntohd(netval); }
287 
290  template <typename T> inline T hton(T input)
291  {
292  union {
293  T asInput;
295  } inVal, outVal;
296  inVal.asInput = input;
297  outVal.asInt = hton(inVal.asInt);
298  return outVal.asInput;
299  }
300 
303  template <typename T> inline T ntoh(T input)
304  {
305  union {
306  T asInput;
308  } inVal, outVal;
309  inVal.asInput = input;
310  outVal.asInt = ntoh(inVal.asInt);
311  return outVal.asInput;
312  }
313 } // end of namespace vrpn_byte_order
314 
315 namespace vrpn_detail {
316  template <typename T> struct remove_const {
317  typedef T type;
318  };
319 
320  template <typename T> struct remove_const<const T> {
321  typedef T type;
322  };
323 
324  template <bool Condition> struct vrpn_static_assert {
325  };
328  template <> struct vrpn_static_assert<true> {
329  enum { SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE };
330  };
331 } // end of namespace vrpn_detail
332 
333 #ifdef VRPN_USE_STATIC_ASSERTIONS
334 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || \
337  (defined(_MSC_VER) && (_MSC_VER >= 1600))
338 #define VRPN_STATIC_ASSERT(CONDITION, MESSAGE) \
339  static_assert(CONDITION, #MESSAGE)
340 #else
341 #define VRPN_STATIC_ASSERT(CONDITION, MESSAGE) \
342  (void)(::vrpn_detail::vrpn_static_assert<CONDITION>::MESSAGE)
343 #endif
344 #else
345 #include <assert.h>
347 #define VRPN_STATIC_ASSERT(CONDITION, MESSAGE) assert((CONDITION) && #MESSAGE)
348 #endif
349 
354 template <typename T, typename ByteT>
355 static inline T vrpn_unbuffer_from_little_endian(ByteT *&input)
356 {
357  using namespace vrpn_byte_order;
358 
359  VRPN_STATIC_ASSERT(sizeof(ByteT) == 1, SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE);
360 
362  union {
363  typename ::vrpn_detail::remove_const<ByteT>::type bytes[sizeof(T)];
364  T typed;
365  } value;
366 
368  for (unsigned int i = 0, j = sizeof(T) - 1; i < sizeof(T); ++i, --j) {
369  value.bytes[i] = input[j];
370  }
371 
373  input += sizeof(T);
374 
376  return ntoh(value.typed);
377 }
378 
383 template <typename T, typename ByteT> inline T vrpn_unbuffer(ByteT *&input)
384 {
385  using namespace vrpn_byte_order;
386 
387  VRPN_STATIC_ASSERT(sizeof(ByteT) == 1, SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE);
388 
390  union {
391  typename ::vrpn_detail::remove_const<ByteT>::type bytes[sizeof(T)];
392  T typed;
393  } value;
394 
396  memcpy(value.bytes, input, sizeof(T));
397 
399  input += sizeof(T);
400 
402  return ntoh(value.typed);
403 }
404 
409 template <typename T, typename ByteT>
410 inline int vrpn_buffer(ByteT **insertPt, vrpn_int32 *buflen, const T inVal)
411 {
412  using namespace vrpn_byte_order;
413 
414  VRPN_STATIC_ASSERT(sizeof(ByteT) == 1, SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE);
415 
416  if ((insertPt == NULL) || (buflen == NULL)) {
417  fprintf(stderr, "vrpn_buffer: NULL pointer\n");
418  return -1;
419  }
420 
421  if (sizeof(T) > static_cast<size_t>(*buflen)) {
422  fprintf(stderr, "vrpn_buffer: buffer not large enough\n");
423  return -1;
424  }
425 
427  union {
428  typename ::vrpn_detail::remove_const<ByteT>::type bytes[sizeof(T)];
429  T typed;
430  } value;
431 
433  value.typed = hton(inVal);
434 
436  memcpy(*insertPt, value.bytes, sizeof(T));
437 
439  *insertPt += sizeof(T);
441  *buflen -= sizeof(T);
442 
443  return 0;
444 }
445 
446 template <typename T, typename ByteT>
447 inline int vrpn_unbuffer(ByteT **input, T *lvalue)
448 {
449  *lvalue = ::vrpn_unbuffer<T, ByteT>(*input);
450  return 0;
451 }
452 
453 // Semaphore and Thread classes derived from Hans Weber's classes from UNC.
454 // Don't let the existence of a Thread class fool you into thinking
455 // that VRPN is thread-safe. This and the Semaphore are included as
456 // building blocks towards making your own code thread-safe. They are
457 // here to enable the vrpn_Imager_Logger class to do its thing.
458 
459 #if defined(sgi) || (defined(_WIN32) && !defined(__CYGWIN__)) || \
460  defined(linux) || defined(__APPLE__)
461 #define vrpn_THREADS_AVAILABLE
462 #else
463 #undef vrpn_THREADS_AVAILABLE
464 #endif
465 
466 // multi process stuff
467 #ifdef sgi
468 #include <task.h>
469 #include <ulocks.h>
470 #elif defined(_WIN32)
471 #include <process.h>
472 #else
473 #include <pthread.h> // for pthread_t
474 #include <semaphore.h> // for sem_t
475 #endif
476 
477 // make the SGI compile without tons of warnings
478 #ifdef sgi
479 #pragma set woff 1110, 1424, 3201
480 #endif
481 
482 // and reset the warnings
483 #ifdef sgi
484 #pragma reset woff 1110, 1424, 3201
485 #endif
486 
488 public:
489  // mutex by default (0 is a sync primitive)
490  vrpn_Semaphore(int cNumResources = 1);
491 
492  // This does not copy the state of the semaphore, just creates
493  // a new one with the same resource count
494  vrpn_Semaphore(const vrpn_Semaphore &s);
495  ~vrpn_Semaphore();
496 
497  // routine to reset it (true on success, false on failure)
498  // (may create new semaphore)
499  bool reset(int cNumResources = 1);
500 
501  // routines to use it (p blocks, condP does not)
502  // p returns 1 when it has acquired the resource, -1 on fail
503  // v returns 0 when it has released the resource, -1 on fail
504  // condP returns 0 if it could not access the resource
505  // and 1 if it could (-1 on fail)
506  int p();
507  int v();
508  int condP();
509 
510  // read values
511  int numResources();
512 
513 protected:
514  // common init and destroy routines
515  bool init();
516  bool destroy();
517 
519 
520 // arch specific details
521 #ifdef sgi
522  // single mem area for dynamically alloced shared mem
523  static usptr_t *ppaArena;
524  static void allocArena();
525 
526  // the semaphore struct in the arena
527  usema_t *ps;
528  ulock_t l;
529  bool fUsingLock;
530 #elif defined(_WIN32)
531  HANDLE hSemaphore;
532 #else
533  sem_t *semaphore; // Posix
534 #endif
535 };
536 
537 // A ptr to this struct will be passed to the
538 // thread function. The user data ptr will be in pvUD.
539 // (There used to be a non-functional semaphore object
540 // also in this structure, but it was removed. This leaves
541 // a struct with only one element, which is a pain but
542 // at least it doesn't break existing code. If we need
543 // to add something else later, there is a place for it.
544 
545 // The user should create and manage any semaphore needed
546 // to handle access control to the userdata.
547 
549  void *pvUD;
550 };
551 
552 typedef void (*vrpn_THREAD_FUNC)(vrpn_ThreadData &threadData);
553 
554 // Don't let the existence of a Thread class fool you into thinking
555 // that VRPN is thread-safe. This and the Semaphore are included as
556 // building blocks towards making your own code thread-safe. They are
557 // here to enable the vrpn_Imager_Stream_Buffer class to do its thing.
559 public:
560  // args are the routine to run in the thread
561  // a ThreadData struct which will be passed into
562  // the thread (it will be passed as a void *).
564  ~vrpn_Thread();
565 
566 #if defined(sgi)
567  typedef unsigned long thread_t;
568 #elif defined(_WIN32)
569  typedef uintptr_t thread_t;
570 #else
571  typedef pthread_t thread_t;
572 #endif
573 
574  // start/kill the thread (true on success, false on failure)
575  bool go();
576  bool kill();
577 
578  // thread info: check if running, get proc id
579  bool running();
580  thread_t pid();
581 
582  // run-time user function to test if threads are available
583  // (same value as #ifdef THREADS_AVAILABLE)
584  static bool available();
585 
586  // Number of processors available on this machine.
587  static unsigned number_of_processors();
588 
589  // This can be used to change the ThreadData user data ptr
590  // between calls to go (ie, when a thread object is used
591  // many times with different args). This will take
592  // effect the next time go() is called.
593  void userData(void *pvNewUserData);
594  void *userData();
595 
596 protected:
597  // user func and data ptrs
598  void (*pfThread)(vrpn_ThreadData &ThreadData);
600 
601  // utility func for calling the specified function.
602  static void threadFuncShell(void *pvThread);
603 
604  // Posix version of the utility function, makes the
605  // function prototype match.
606  static void *threadFuncShellPosix(void *pvThread);
607 
608  // the process id
610 };
611 
612 // Returns true if they work and false if they do not.
613 extern bool vrpn_test_threads_and_semaphores(void);
#define VRPN_STATIC_ASSERT(CONDITION, MESSAGE)
Fall back to normal asserts.
Definition: vrpn_Shared.h:347
VRPN_API bool vrpn_TimevalEqual(const struct timeval &tv1, const struct timeval &tv2)
VRPN_API void vrpn_SleepMsecs(double dMsecs)
Definition: vrpn_Shared.C:157
VRPN_API struct timeval vrpn_MsecsTimeval(const double dMsecs)
Definition: vrpn_Shared.C:146
thread_t threadID
Definition: vrpn_Shared.h:609
VRPN_API unsigned long vrpn_TimevalDuration(struct timeval endT, struct timeval startT)
Return number of microseconds between startT and endT.
Definition: vrpn_Shared.C:129
void(* vrpn_THREAD_FUNC)(vrpn_ThreadData &threadData)
Definition: vrpn_Shared.h:552
vrpn_ThreadData td
Definition: vrpn_Shared.h:599
VRPN_API double vrpn_TimevalDurationSeconds(struct timeval endT, struct timeval startT)
Return the number of seconds between startT and endT as a floating-point value.
Definition: vrpn_Shared.C:135
VRPN_API vrpn_float64 vrpn_ntohd(vrpn_float64 d)
Definition: vrpn_Shared.C:226
bool vrpn_test_threads_and_semaphores(void)
Definition: vrpn_Shared.C:1426
#define VRPN_API
VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen, const char *string, vrpn_int32 length)
Utility routine for placing a character string of given length into a buffer that is to be sent as a ...
Definition: vrpn_Shared.C:271
vrpn_uint8 hton(vrpn_uint8 hostval)
host to network byte order for 8-bit uints is a no-op
Definition: vrpn_Shared.h:265
sem_t * semaphore
Definition: vrpn_Shared.h:533
VRPN_API bool vrpn_TimevalGreater(const struct timeval &tv1, const struct timeval &tv2)
vrpn_uint8 ntoh(vrpn_uint8 netval)
network to host byte order for 8-bit uints is a no-op
Definition: vrpn_Shared.h:268
VRPN_API struct timeval vrpn_TimevalNormalize(const struct timeval &tv)
VRPN_API double vrpn_TimevalMsecs(const struct timeval &tv1)
VRPN_API struct timeval vrpn_TimevalDiff(const struct timeval &tv1, const struct timeval &tv2)
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
VRPN_API vrpn_float64 vrpn_htond(vrpn_float64 d)
Definition: vrpn_Shared.C:190
VRPN_API struct timeval vrpn_TimevalScale(const struct timeval &tv, double scale)
Traits class to get the uint type of a given size.
Definition: vrpn_Shared.h:251
VRPN_API int vrpn_unbuffer(const char **buffer, char *string, vrpn_int32 length)
Utility routine for taking a string of specified length from a buffer that was sent as a message...
Definition: vrpn_Shared.C:348
VRPN_API struct timeval vrpn_TimevalSum(const struct timeval &tv1, const struct timeval &tv2)
Internal header providing unbuffering facilities for a number of types.
Definition: vrpn_Shared.h:248
pthread_t thread_t
Definition: vrpn_Shared.h:571