8#define _CRT_SECURE_NO_WARNINGS 1
9#pragma warning(disable : 4996)
14#if defined(__APPLE__) || defined(__ANDROID__)
18#if !(defined(_WIN32) && defined(VRPN_USE_WINSOCK_SOCKETS))
19#include <sys/select.h>
20#include <netinet/in.h>
24 if (a == -1) return -1
26#if defined(VRPN_USE_WINSOCK_SOCKETS)
37static inline void timevalNormalizeInPlace(timeval &in_tv)
39 const long div_77777 = (in_tv.tv_usec / 1000000);
40 in_tv.tv_sec += div_77777;
41 in_tv.tv_usec -= (div_77777 * 1000000);
45 timeval out_tv = in_tv;
46 timevalNormalizeInPlace(out_tv);
58 tvSum.tv_sec += tv2.tv_sec;
59 tvSum.tv_usec += tv2.tv_usec;
63 if (tvSum.tv_sec > 0) {
64 if (tvSum.tv_usec < 0) {
66 tvSum.tv_usec += 1000000;
68 else if (tvSum.tv_usec >= 1000000) {
70 tvSum.tv_usec -= 1000000;
73 else if (tvSum.tv_sec < 0) {
74 if (tvSum.tv_usec > 0) {
76 tvSum.tv_usec -= 1000000;
78 else if (tvSum.tv_usec <= -1000000) {
80 tvSum.tv_usec += 1000000;
85 if (tvSum.tv_usec >= 1000000) {
87 tvSum.tv_usec -= 1000000;
89 else if (tvSum.tv_usec <= -1000000) {
91 tvSum.tv_usec += 1000000;
105 tv.tv_sec = -tv2.tv_sec;
106 tv.tv_usec = -tv2.tv_usec;
114 result.tv_sec = (long)(tv.tv_sec * scale);
116 (long)(tv.tv_usec * scale + fmod(tv.tv_sec * scale, 1.0) * 1000000.0);
117 timevalNormalizeInPlace(result);
124 if (tv1.tv_sec > tv2.tv_sec)
return 1;
125 if ((tv1.tv_sec == tv2.tv_sec) && (tv1.tv_usec > tv2.tv_usec))
return 1;
132 if (tv1.tv_sec == tv2.tv_sec && tv1.tv_usec == tv2.tv_usec)
140 return (endT.tv_usec - startT.tv_usec) +
141 1000000L * (endT.tv_sec - startT.tv_sec);
146 return (endT.tv_usec - startT.tv_usec) / 1000000.0 +
147 (endT.tv_sec - startT.tv_sec);
152 return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
158 tv.tv_sec = (long)floor(dMsecs / 1000.0);
159 tv.tv_usec = (long)((dMsecs / 1000.0 - tv.tv_sec) * 1e6);
169 Sleep((DWORD)dMilliSecs);
174 timeout.tv_sec = (int)(dMilliSecs / 1000.0);
177 dMilliSecs -= timeout.tv_sec * 1000;
180 timeout.tv_usec = (int)(dMilliSecs * 1000);
184 select(0, 0, 0, 0, &timeout);
201 if (!vrpn_big_endian) {
202 vrpn_float64 dSwapped;
203 char *pchSwapped = (
char *)&dSwapped;
204 char *pchOrig = (
char *)&d;
208 for (i = 0; i <
sizeof(vrpn_float64); i++) {
209 pchSwapped[i] = pchOrig[
sizeof(vrpn_float64) - i - 1];
212#if defined(__arm__) && !defined(__ANDROID__)
216#if __FLOAT_WORD_ORDER != __BYTE_ORDER
219 vrpn_uint32 *pwSwapped = (vrpn_uint32 *)&dSwapped;
220 vrpn_uint32 scratch = pwSwapped[0];
221 pwSwapped[0] = pwSwapped[1];
222 pwSwapped[1] = scratch;
252 vrpn_int32 sec, usec;
281 const char *
string, vrpn_int32 length)
283 if (length > *buflen) {
284 fprintf(stderr,
"vrpn_buffer: buffer not long enough for string.\n");
291 if (len > (
unsigned)*buflen) {
293 "vrpn_buffer: buffer not long enough for string.\n");
296 strcpy(*insertPt,
string);
298 *buflen -=
static_cast<vrpn_int32
>(len);
301 memcpy(*insertPt,
string, length);
323 vrpn_int32 sec, usec;
358 if (!
string)
return -1;
363 size_t max_len =
static_cast<size_t>(-length);
364 strncpy(
string, *buffer, max_len);
367 for (i = 0; i < max_len; i++) {
368 if (
string[i] ==
'\0') {
376 *buffer += strlen(*buffer) + 1;
378 memcpy(
string, *buffer, length);
401#ifdef VRPN_USE_STD_CHRONO
426static bool hr_offset_determined =
false;
428static struct timeval hr_offset;
430static struct timeval high_resolution_time_to_system_time(
431 struct timeval hi_res_time
438 if (!hr_offset_determined) {
439 hr_offset_semaphore.
p();
441 if (!hr_offset_determined) {
445 std::chrono::system_clock::time_point pre =
446 std::chrono::system_clock::now();
447 std::chrono::system_clock::time_point post;
452 post = std::chrono::system_clock::now();
453 }
while (pre == post);
457 std::chrono::high_resolution_clock::time_point high =
458 std::chrono::high_resolution_clock::now();
463 std::time_t high_secs =
464 std::chrono::duration_cast<std::chrono::seconds>(
465 high.time_since_epoch())
467 std::chrono::high_resolution_clock::time_point
468 fractional_high_secs = high - std::chrono::seconds(high_secs);
469 struct timeval high_time;
470 high_time.tv_sec =
static_cast<unsigned long>(high_secs);
471 high_time.tv_usec =
static_cast<unsigned long>(
472 std::chrono::duration_cast<std::chrono::microseconds>(
473 fractional_high_secs.time_since_epoch())
476 std::time_t post_secs =
477 std::chrono::duration_cast<std::chrono::seconds>(
478 post.time_since_epoch())
480 std::chrono::system_clock::time_point fractional_post_secs =
481 post - std::chrono::seconds(post_secs);
482 struct timeval post_time;
483 post_time.tv_sec =
static_cast<unsigned long>(post_secs);
484 post_time.tv_usec =
static_cast<unsigned long>(
485 std::chrono::duration_cast<std::chrono::microseconds>(
486 fractional_post_secs.time_since_epoch())
492 hr_offset_determined =
true;
494 hr_offset_semaphore.
v();
507 struct timezone *timeZone =
reinterpret_cast<struct timezone *
>(tzp);
511 std::chrono::high_resolution_clock::time_point now =
512 std::chrono::high_resolution_clock::now();
514 std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch())
519 std::chrono::high_resolution_clock::time_point fractional_secs =
520 now - std::chrono::seconds(secs);
525 struct timeval hi_res_time;
526 hi_res_time.tv_sec =
static_cast<unsigned long>(secs);
527 hi_res_time.tv_usec =
static_cast<unsigned long>(
528 std::chrono::duration_cast<std::chrono::microseconds>(
529 fractional_secs.time_since_epoch())
531 *tp = high_resolution_time_to_system_time(hi_res_time);
534 if (timeZone != NULL) {
535 timeZone->tz_minuteswest = 0;
536 timeZone->tz_dsttime = 0;
558#ifndef VRPN_UNSAFE_WINDOWS_CLOCK
560#if defined(_WIN32) && !defined(__CYGWIN__)
563#pragma optimize("", on)
566void get_time_using_GetLocalTime(
unsigned long &sec,
unsigned long &usec)
572 GetLocalTime(&stime);
573 SystemTimeToFileTime(&stime, &ftime);
576 tics.HighPart = ftime.dwHighDateTime;
577 tics.LowPart = ftime.dwLowDateTime;
583 tics.QuadPart -= 11644473600000000ULL;
586 sec = (
unsigned long)(tics.QuadPart / 1000000UL);
587 usec = (
unsigned long)(tics.QuadPart % 1000000UL);
601 struct timezone *timeZone =
reinterpret_cast<struct timezone *
>(tzp);
605 unsigned long sec, usec;
606 get_time_using_GetLocalTime(sec, usec);
613 tp->tv_usec = (long)t.millitm * 1000;
617 TIME_ZONE_INFORMATION tz;
618 GetTimeZoneInformation(&tz);
619 timeZone->tz_minuteswest = tz.Bias;
620 timeZone->tz_dsttime = (tz.StandardBias != tz.Bias);
634#if defined(_WIN32) && !defined(__CYGWIN__)
644static __int64 VRPN_CLOCK_FREQ = 200000000;
655 _asm _emit 0x0f _asm _emit 0x31 _asm mov li.LowPart, \
656 eax _asm mov li.HighPart, edx \
662#ifndef VRPN_WINDOWS_CLOCK_V2
663#pragma optimize("", off)
664static int vrpn_AdjustFrequency(
void)
667 const int tPerLoop = 500;
668 fprintf(stderr,
"vrpn vrpn_gettimeofday: determining clock frequency...");
670 LARGE_INTEGER startperf, endperf;
671 LARGE_INTEGER perffreq;
676 if (QueryPerformanceFrequency(&perffreq) == 0) {
682 volatile LARGE_INTEGER liStart, liEnd;
684 DWORD dwPriorityClass = GetPriorityClass(GetCurrentProcess());
685 int iThreadPriority = GetThreadPriority(GetCurrentThread());
686 SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
687 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
692 QueryPerformanceCounter(&startperf);
695 QueryPerformanceCounter(&endperf);
697 double freq = perffreq.QuadPart * (liEnd.QuadPart - liStart.QuadPart) /
698 ((
double)(endperf.QuadPart - startperf.QuadPart));
700 if (fabs(perffreq.QuadPart - freq) < 0.05 * freq) {
701 VRPN_CLOCK_FREQ = (__int64)perffreq.QuadPart;
702 fprintf(stderr,
"\nvrpn vrpn_gettimeofday: perf clock is tsc -- using "
703 "perf clock freq ( %lf MHz)\n",
704 perffreq.QuadPart / 1e6);
705 SetPriorityClass(GetCurrentProcess(), dwPriorityClass);
706 SetThreadPriority(GetCurrentThread(), iThreadPriority);
714 fprintf(stderr,
" (this will take %lf seconds)...\n",
715 loops * tPerLoop / 1000.0);
717 for (
int j = 0; j < loops; j++) {
719 QueryPerformanceCounter(&startperf);
722 QueryPerformanceCounter(&endperf);
732 sum += perffreq.QuadPart * (liEnd.QuadPart - liStart.QuadPart) /
733 ((
double)(endperf.QuadPart - startperf.QuadPart));
736 SetPriorityClass(GetCurrentProcess(), dwPriorityClass);
737 SetThreadPriority(GetCurrentThread(), iThreadPriority);
740 freq = (sum / loops);
754 if (fabs(perffreq.QuadPart - freq) < 0.05 * freq) {
755 VRPN_CLOCK_FREQ = perffreq.QuadPart;
756 fprintf(stderr,
"vrpn vrpn_gettimeofday: perf clock is tsc -- using "
757 "perf clock freq ( %lf MHz)\n",
758 perffreq.QuadPart / 1e6);
761 fprintf(stderr,
"vrpn vrpn_gettimeofday: adjusted clock freq to "
762 "measured freq ( %lf MHz )\n",
765 VRPN_CLOCK_FREQ = (__int64)freq;
768#pragma optimize("", on)
790#ifndef VRPN_WINDOWS_CLOCK_V2
793 struct timezone *timeZone =
reinterpret_cast<struct timezone *
>(tzp);
794 static int fFirst = 1;
795 static int fHasPerfCounter = 1;
796 static struct _timeb tbInit;
797 static LARGE_INTEGER liInit;
798 static LARGE_INTEGER liNow;
799 static LARGE_INTEGER liDiff;
802 if (!fHasPerfCounter) {
804 tp->tv_sec = tbInit.time;
805 tp->tv_usec = tbInit.millitm * 1000;
810 LARGE_INTEGER liTemp;
823 memset(&osvi, 0,
sizeof(OSVERSIONINFO));
824 osvi.dwOSVersionInfoSize =
sizeof(OSVERSIONINFO);
827 if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) {
829 "\nvrpn_gettimeofday: disabling hi performance clock "
831 "Defaulting to _ftime (~6 ms resolution) ...\n");
839 if (!(fHasPerfCounter = QueryPerformanceFrequency(&liTemp))) {
841 "\nvrpn_gettimeofday: no hi performance clock available. "
842 "Defaulting to _ftime (~6 ms resolution) ...\n");
848 if (vrpn_AdjustFrequency() < 0) {
850 "\nvrpn_gettimeofday: can't verify clock frequency. "
851 "Defaulting to _ftime (~6 ms resolution) ...\n");
870 liDiff.QuadPart = liNow.QuadPart - liInit.QuadPart;
872 tvDiff.tv_sec = (long)(liDiff.QuadPart / VRPN_CLOCK_FREQ);
874 (long)(1e6 * ((liDiff.QuadPart - VRPN_CLOCK_FREQ * tvDiff.tv_sec) /
875 (double)VRPN_CLOCK_FREQ));
878 tp->tv_sec = tbInit.time + tvDiff.tv_sec;
879 tp->tv_usec = tbInit.millitm * 1000 + tvDiff.tv_usec;
880 while (tp->tv_usec >= 1000000) {
882 tp->tv_usec -= 1000000;
889void get_time_using_GetLocalTime(
unsigned long &sec,
unsigned long &usec)
891 static LARGE_INTEGER first_count = {0, 0};
892 static unsigned long first_sec, first_usec;
893 static LARGE_INTEGER perf_freq;
897 LARGE_INTEGER perf_counter;
902 if (first_count.QuadPart == 0) {
903 QueryPerformanceCounter(&first_count);
907 QueryPerformanceFrequency(&perf_freq);
910 GetLocalTime(&stime);
911 SystemTimeToFileTime(&stime, &ftime);
915 tics.HighPart = ftime.dwHighDateTime;
916 tics.LowPart = ftime.dwLowDateTime;
920 sec = (long)(tics.QuadPart / 10000000L);
921 usec = (long)((tics.QuadPart - (((LONGLONG)(sec)) * 10000000L)) / 10);
926 QueryPerformanceCounter(&perf_counter);
927 if (perf_counter.QuadPart >= first_count.QuadPart) {
928 perf_counter.QuadPart =
929 perf_counter.QuadPart - first_count.QuadPart;
933 perf_counter.QuadPart = 0x7fffffffffffffffLL -
934 first_count.QuadPart +
935 perf_counter.QuadPart;
942 sec = (long)(perf_counter.QuadPart / perf_freq.QuadPart);
943 perf_counter.QuadPart -= perf_freq.QuadPart * sec;
944 perf_counter.QuadPart *= 1000000L;
945 usec = first_usec + (long)(perf_counter.QuadPart / perf_freq.QuadPart);
952 if (usec > 1000000L) {
966 struct timezone *timeZone =
reinterpret_cast<struct timezone *
>(tzp);
967 unsigned long sec, usec;
968 get_time_using_GetLocalTime(sec, usec);
972 TIME_ZONE_INFORMATION tz;
973 GetTimeZoneInformation(&tz);
974 timeZone->tz_minuteswest = tz.Bias;
975 timeZone->tz_dsttime = (tz.StandardBias != tz.Bias);
998 vrpn_float64 dbuffer[256];
1001 vrpn_float64 in_float64 = 42.1;
1002 vrpn_int32 in_int32 = 17;
1003 vrpn_uint16 in_uint16 = 397;
1004 vrpn_uint8 in_uint8 = 1;
1006 vrpn_float64 out_float64;
1007 vrpn_int32 out_int32;
1008 vrpn_uint16 out_uint16;
1009 vrpn_uint8 out_uint8;
1013 char *bufptr = (
char *)dbuffer;
1014 buflen =
sizeof(dbuffer);
1017 "vrpn_test_pack_unpack(): Could not buffer little endian\n");
1022 "vrpn_test_pack_unpack(): Could not buffer little endian\n");
1027 "vrpn_test_pack_unpack(): Could not buffer little endian\n");
1032 "vrpn_test_pack_unpack(): Could not buffer little endian\n");
1037 bufptr = (
char *)dbuffer;
1040 vrpn_unbuffer_from_little_endian<vrpn_float64>(bufptr))) {
1042 "vrpn_test_pack_unpack(): Could not unbuffer little endian\n");
1046 (out_int32 = vrpn_unbuffer_from_little_endian<vrpn_int32>(bufptr))) {
1048 "vrpn_test_pack_unpack(): Could not unbuffer little endian\n");
1052 (out_uint16 = vrpn_unbuffer_from_little_endian<vrpn_uint16>(bufptr))) {
1054 "vrpn_test_pack_unpack(): Could not unbuffer little endian\n");
1058 (out_uint8 = vrpn_unbuffer_from_little_endian<vrpn_uint8>(bufptr))) {
1060 "vrpn_test_pack_unpack(): Could not unbuffer little endian\n");
1065 bufptr = (
char *)dbuffer;
1066 buflen =
sizeof(dbuffer);
1067 if (
vrpn_buffer(&bufptr, &buflen, in_float64) != 0) {
1069 "vrpn_test_pack_unpack(): Could not buffer big endian\n");
1072 if (
vrpn_buffer(&bufptr, &buflen, in_int32) != 0) {
1074 "vrpn_test_pack_unpack(): Could not buffer big endian\n");
1077 if (
vrpn_buffer(&bufptr, &buflen, in_uint16) != 0) {
1079 "vrpn_test_pack_unpack(): Could not buffer big endian\n");
1082 if (
vrpn_buffer(&bufptr, &buflen, in_uint8) != 0) {
1084 "vrpn_test_pack_unpack(): Could not buffer big endian\n");
1089 bufptr = (
char *)dbuffer;
1090 if (in_float64 != (out_float64 = vrpn_unbuffer<vrpn_float64>(bufptr))) {
1092 "vrpn_test_pack_unpack(): Could not unbuffer big endian\n");
1095 if (in_int32 != (out_int32 = vrpn_unbuffer<vrpn_int32>(bufptr))) {
1097 "vrpn_test_pack_unpack(): Could not unbuffer big endian\n");
1100 if (in_uint16 != (out_uint16 = vrpn_unbuffer<vrpn_uint16>(bufptr))) {
1102 "vrpn_test_pack_unpack(): Could not unbuffer big endian\n");
1105 if (in_uint8 != (out_uint8 = vrpn_unbuffer<vrpn_uint8>(bufptr))) {
1107 "vrpn_test_pack_unpack(): Could not unbuffer big endian\n");
1115 bufptr = (
char *)dbuffer;
1116 buflen =
sizeof(dbuffer);
1119 "vrpn_test_pack_unpack(): Could not buffer little endian\n");
1122 bufptr = (
char *)dbuffer;
1123 if (in_float64 == (out_float64 = vrpn_unbuffer<vrpn_float64>(bufptr))) {
1126 "vrpn_test_pack_unpack(): Cross-packing produced same result\n");
int v()
Release of resource. ("up")
int p()
Blocking acquire of resource. ("down")
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.
unsigned long vrpn_TimevalDuration(struct timeval endT, struct timeval startT)
Return number of microseconds between startT and endT.
bool vrpn_test_pack_unpack(void)
double vrpn_TimevalDurationSeconds(struct timeval endT, struct timeval startT)
Return the number of seconds between startT and endT as a floating-point value.
bool vrpn_TimevalGreater(const timeval &tv1, const timeval &tv2)
timeval vrpn_TimevalScale(const timeval &tv, double scale)
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.
vrpn_float64 vrpn_ntohd(vrpn_float64 d)
vrpn_float64 vrpn_htond(vrpn_float64 d)
double vrpn_TimevalMsecs(const timeval &tv)
timeval vrpn_TimevalDiff(const timeval &tv1, const timeval &tv2)
timeval vrpn_TimevalNormalize(const timeval &in_tv)
bool vrpn_TimevalEqual(const timeval &tv1, const timeval &tv2)
void vrpn_SleepMsecs(double dMilliSecs)
timeval vrpn_MsecsTimeval(const double dMsecs)
timeval vrpn_TimevalSum(const timeval &tv1, const timeval &tv2)
#define vrpn_gettimeofday
int vrpn_buffer_to_little_endian(ByteT **insertPt, vrpn_int32 *buflen, const T inVal)
Function template to buffer values to a buffer stored in little- endian order. Specify the type to bu...