87 using namespace std::chrono;
91 #pragma intrinsic (_InterlockedDecrement)
92 #pragma intrinsic (_InterlockedIncrement)
93 #pragma intrinsic (_InterlockedExchange)
94 #pragma intrinsic (_InterlockedExchange64)
95 #pragma intrinsic (_InterlockedCompareExchange)
96 #pragma intrinsic (_InterlockedCompareExchange64)
105 #define R250_IA (sizeof(uint32)*103)
106 #define R250_IB (sizeof(uint32)*R250_LEN-R250_IA)
107 #define R521_IA (sizeof(uint32)*168)
108 #define R521_IB (sizeof(uint32)*R521_LEN-R521_IA)
113 bool CalcTimeout(
struct timespec &timeout, uint32 ms) {
116 if (gettimeofday(&now, NULL) != 0)
119 timeout.tv_sec = now.tv_sec + ms / 1000;
120 long us = now.tv_usec + ms % 1000;
125 timeout.tv_nsec = us * 1000;
131 if (gettimeofday(&tv, NULL))
133 return (tv.tv_usec + tv.tv_sec * 1000000LL);
137 void Error::PrintBinary(
void* p, uint32 size,
bool asInt,
const char* title) {
139 printf(
"--- %s %u ---\n", title, size);
141 for (uint32 n = 0; n < size; n++) {
142 c = *(((
unsigned char*)p) + n);
144 printf(
"[%u] ", (
unsigned int)c);
147 if ((n > 0) && ((n + 1) % 10 == 0))
153 SharedLibrary::SharedLibrary() : library_(NULL) {
156 SharedLibrary::~SharedLibrary() {
159 FreeLibrary(library_);
166 SharedLibrary *SharedLibrary::load(
const char *fileName) {
168 library_ = LoadLibrary(TEXT(fileName));
171 DWORD error = GetLastError();
172 std::cerr <<
"> Error: unable to load shared library " << fileName <<
" :" << error << std::endl;
181 char *libraryName = (
char *)calloc(1, strlen(fileName) + 6 + 1);
182 if (strstr(fileName,
"lib") == NULL) {
183 strcat(libraryName,
"lib");
185 strcat(libraryName, fileName);
186 if (strstr(fileName + (strlen(fileName) - 3),
".so") == NULL) {
187 strcat(libraryName,
".so");
189 library_ = dlopen(libraryName, RTLD_NOW | RTLD_GLOBAL);
191 std::cout <<
"> Error: unable to load shared library " << fileName <<
" :" << dlerror() << std::endl;
201 void* SharedLibrary::getFunction(
const char* functionName) {
202 void*
function = NULL;
206 function = GetProcAddress(library_, functionName);
209 DWORD error = GetLastError();
210 std::cerr <<
"GetProcAddress > Error: " << error << std::endl;
215 function = dlsym(library_, functionName);
217 std::cout <<
"> Error: unable to find symbol " << functionName <<
" :" << dlerror() << std::endl;
226 void Thread::TerminateAndWait(Thread **threads, uint32 threadCount) {
229 for (uint32 i = 0; i < threadCount; i++) {
230 threads[i]->terminate();
231 Thread::Wait(threads[i]);
235 void Thread::TerminateAndWait(Thread *thread) {
239 Thread::Wait(thread);
242 void Thread::Wait(Thread **threads, uint32 threadCount) {
247 for (uint32 i = 0; i < threadCount; i++)
248 WaitForSingleObject(threads[i]->thread_, INFINITE);
250 for (uint32 i = 0; i < threadCount; i++)
251 pthread_join(threads[i]->thread_, NULL);
255 void Thread::Wait(Thread *thread) {
260 WaitForSingleObject(thread->thread_, INFINITE);
262 pthread_join(thread->thread_, NULL);
266 void Thread::Sleep(milliseconds ms) {
268 ::Sleep((uint32)ms.count());
271 usleep(ms.count() * 1000);
275 void Thread::Sleep() {
284 Thread::Thread() : is_meaningful_(false) {
292 CloseHandle(thread_);
298 void Thread::start(thread_function f) {
300 thread_ = CreateThread(NULL, 65536, f,
this, 0, NULL);
302 pthread_create(&thread_, NULL, f,
this);
304 is_meaningful_ =
true;
307 void Thread::suspend() {
309 SuspendThread(thread_);
311 pthread_kill(thread_, SIGSTOP);
315 void Thread::resume() {
317 ResumeThread(thread_);
319 pthread_kill(thread_, SIGCONT);
323 void Thread::terminate() {
325 TerminateThread(thread_, 0);
327 pthread_cancel(thread_);
333 void TimeProbe::set() {
335 cpu_counts_ = getCounts();
338 int64 TimeProbe::getCounts() {
340 LARGE_INTEGER counter;
341 QueryPerformanceCounter(&counter);
342 return counter.QuadPart;
344 static struct timeval tv;
345 static struct timezone tz;
346 gettimeofday(&tv, &tz);
347 return (((int64)tv.tv_sec) * 1000000) + (int64)tv.tv_usec;
351 void TimeProbe::check() {
353 cpu_counts_ = getCounts() - cpu_counts_;
359 typedef LONG NTSTATUS;
360 typedef NTSTATUS(__stdcall *NSTR)(ULONG, BOOLEAN, PULONG);
361 #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
362 bool NtSetTimerResolution(IN ULONG RequestedResolution, IN BOOLEAN Set, OUT PULONG ActualResolution);
367 float64 Time::Period_;
369 Timestamp Time::InitTime_;
371 void Time::Init(uint32 r) {
374 HMODULE NTDll = ::LoadLibrary(
"NTDLL");
375 ULONG actualResolution = 0;
378 NSTR pNSTR = (NSTR)::GetProcAddress(NTDll,
"NtSetTimerResolution");
380 nts = (*pNSTR)(10 * r,
true, &actualResolution);
383 QueryPerformanceFrequency(&f);
384 Period_ = 1000000.0 / f.QuadPart;
385 struct _timeb local_time;
387 auto now = Timestamp(microseconds((int64)(local_time.time * 1000 + local_time.millitm) * 1000));
389 InitTime_ = Timestamp(seconds(0));
390 InitTime_ = now - Get().time_since_epoch();
393 InitTime_ = system_clock_us::now() - duration_cast<microseconds>(steady_clock::now().time_since_epoch());
397 Timestamp Time::Get() {
399 LARGE_INTEGER counter;
400 QueryPerformanceCounter(&counter);
401 return InitTime_ + microseconds((uint64)(counter.QuadPart * Period_));
403 return InitTime_ + duration_cast<microseconds>(steady_clock::now().time_since_epoch());
407 std::string Time::ToString_year(Timestamp timestamp) {
409 uint64 t = abs(duration_cast<microseconds>(timestamp.time_since_epoch()).count());
411 uint64 us = t % 1000;
412 uint64 ms = t / 1000;
413 uint64 s = ms / 1000;
416 time_t _gmt_time = s;
417 struct tm *_t = gmtime(&_gmt_time);
419 std::string _s = asctime(_t);
420 std::string year = _s.substr(_s.length() - 5, 4);
421 _s.erase(_s.length() - 6, 5);
422 std::string hh_mm_ss = _s.substr(_s.length() - 9, 8);
424 hh_mm_ss += std::to_string(ms);
426 hh_mm_ss += std::to_string(us);
428 _s.erase(_s.length() - 9, 9);
439 uint8 Host::Name(
char *name) {
442 GetComputerName(name, &s);
445 struct utsname utsname;
447 strcpy(name, utsname.nodename);
455 const uint32 Semaphore::Infinite = INFINITE;
462 const uint32 Semaphore::Infinite = INT_MAX;
465 Semaphore::Semaphore(uint32 initialCount, uint32 maxCount) {
467 s_ = CreateSemaphore(NULL, initialCount, maxCount, NULL);
469 sem_init(&s_, 0, initialCount);
473 Semaphore::~Semaphore() {
481 bool Semaphore::acquire(uint32 timeout) {
483 uint32 r = WaitForSingleObject(s_, timeout);
484 return r == WAIT_TIMEOUT;
489 CalcTimeout(t, timeout);
490 r = sem_timedwait(&s_, &t);
495 void Semaphore::release(uint32 count) {
497 ReleaseSemaphore(s_, count, NULL);
499 for (uint32 c = 0; c < count; c++)
504 void Semaphore::reset() {
521 const uint32 Mutex::Infinite = INFINITE;
528 const uint32 Mutex::Infinite = INT_MAX;
533 m_ = CreateMutex(NULL,
false, NULL);
535 pthread_mutex_init(&m_, NULL);
543 pthread_mutex_destroy(&m_);
547 bool Mutex::acquire(uint32 timeout) {
549 uint32 r = WaitForSingleObject(m_, timeout);
550 return r == WAIT_TIMEOUT;
552 auto start = Time::Get();
553 auto uTimeout = microseconds(timeout * 1000);
555 while (pthread_mutex_trylock(&m_) != 0) {
556 Thread::Sleep(milliseconds(10));
557 if (Time::Get() - start >= uTimeout)
565 void Mutex::release() {
569 pthread_mutex_unlock(&m_);
575 CriticalSection::CriticalSection() {
577 InitializeCriticalSection(&cs_);
579 pthread_mutex_init(&cs_, NULL);
583 CriticalSection::~CriticalSection() {
585 DeleteCriticalSection(&cs_);
587 pthread_mutex_destroy(&cs_);
591 void CriticalSection::enter() {
593 EnterCriticalSection(&cs_);
595 pthread_mutex_lock(&cs_);
599 void CriticalSection::leave() {
601 LeaveCriticalSection(&cs_);
603 pthread_mutex_unlock(&cs_);
610 const uint32 Timer::Infinite = INFINITE;
612 const uint32 Timer::Infinite = INT_MAX;
614 static void timer_signal_handler(
int sig, siginfo_t *siginfo,
void *context) {
615 SemaTex* sematex = (SemaTex*)siginfo->si_value.sival_ptr;
618 pthread_mutex_lock(&sematex->mutex);
619 pthread_cond_broadcast(&sematex->semaphore);
620 pthread_mutex_unlock(&sematex->mutex);
626 t_ = CreateWaitableTimer(NULL,
false, NULL);
628 printf(
"Error creating timer\n");
631 pthread_cond_init(&sematex.semaphore, NULL);
632 pthread_mutex_init(&sematex.mutex, NULL);
635 struct sigevent timer_event;
637 sigemptyset(&sa.sa_mask);
638 sa.sa_flags = SA_SIGINFO;
639 sa.sa_sigaction = timer_signal_handler;
640 sigaction(SIGRTMIN, &sa, NULL);
642 timer_event.sigev_notify = SIGEV_SIGNAL;
643 timer_event.sigev_signo = SIGRTMIN;
644 timer_event.sigev_value.sival_ptr = (
void *)&sematex;
645 int ret = timer_create(CLOCK_REALTIME, &timer_event, &timer);
647 printf(
"Error creating timer: %d\n", ret);
656 pthread_cond_destroy(&sematex.semaphore);
657 pthread_mutex_destroy(&sematex.mutex);
662 void Timer::start(microseconds deadline, milliseconds period) {
664 LARGE_INTEGER _deadline;
665 _deadline.QuadPart = -10LL * deadline.count();
666 bool r = SetWaitableTimer(t_, &_deadline, (
long)period.count(), NULL, NULL, 0);
668 printf(
"Error arming timer\n");
671 struct itimerspec newtv;
674 uint64 t = deadline.count();
675 uint64 p = period.count() * 1000;
676 newtv.it_interval.tv_sec = p / 1000000;
677 newtv.it_interval.tv_nsec = (p % 1000000) * 1000;
678 newtv.it_value.tv_sec = t / 1000000;
679 newtv.it_value.tv_nsec = (t % 1000000) * 1000;
681 pthread_mutex_lock(&sematex.mutex);
683 int ret = timer_settime(timer, 0, &newtv, NULL);
685 printf(
"Error arming timer: %d\n", ret);
687 sigemptyset(&allsigs);
689 pthread_mutex_unlock(&sematex.mutex);
693 bool Timer::wait(uint32 timeout) {
695 uint32 r = WaitForSingleObject(t_, timeout);
696 return r == WAIT_TIMEOUT;
699 struct timespec ttimeout;
701 pthread_mutex_lock(&sematex.mutex);
702 if (timeout == INT_MAX) {
703 res = (pthread_cond_wait(&sematex.semaphore, &sematex.mutex) == 0);
706 CalcTimeout(ttimeout, timeout);
707 res = (pthread_cond_timedwait(&sematex.semaphore, &sematex.mutex, &ttimeout) == 0);
709 pthread_mutex_unlock(&sematex.mutex);
718 e_ = CreateEvent(NULL,
true,
false, NULL);
734 WaitForSingleObject(e_, INFINITE);
748 void Event::reset() {
758 void SignalHandler::Add(signal_handler h) {
760 if (SetConsoleCtrlHandler(h,
true) == 0) {
762 int e = GetLastError();
763 std::cerr <<
"Error: " << e <<
" failed to add signal handler" << std::endl;
767 signal(SIGABRT, SIG_IGN);
768 signal(SIGPIPE, SIG_IGN);
769 signal(SIGBUS, SIG_IGN);
780 void SignalHandler::Remove(signal_handler h) {
782 SetConsoleCtrlHandler(h,
false);
784 signal(SIGABRT, SIG_IGN);
785 signal(SIGPIPE, SIG_IGN);
786 signal(SIGBUS, SIG_IGN);
788 signal(SIGTERM, SIG_DFL);
789 signal(SIGINT, SIG_DFL);
790 signal(SIGABRT, SIG_DFL);
799 uint8 BSR(word data) {
803 _BitScanReverse(&index, data);
805 #elif defined ARCH_64
807 _BitScanReverse64(&index, data);
812 return (uint8)(31 - __builtin_clz((uint32_t)data));
813 #elif defined ARCH_64
814 return (uint8)(63 - __builtin_clzll((uint64_t)data));
821 FastSemaphore::FastSemaphore(uint32 initialCount, uint32 maxCount) : Semaphore(initialCount > 0 ? 1 : 0, 1), count_(initialCount), maxCount_(maxCount) {
824 FastSemaphore::~FastSemaphore() {
827 void FastSemaphore::acquire() {
830 while ((c = --count_) >= maxCount_);
832 Semaphore::acquire();
835 void FastSemaphore::release() {
839 Semaphore::release();
866 bool Error::PrintLastOSErrorMessage(
const char* title) {
867 int32 err = Error::GetLastOSErrorNumber();
869 if (!Error::GetOSErrorMessage(buf, 1024, err))
870 printf(
"%s: [%d] (could not get error message)\n", title, err);
872 printf(
"%s: [%d] %s\n", title, err, buf);
876 int32 Error::GetLastOSErrorNumber() {
878 int32 err = WSAGetLastError();
886 bool Error::GetOSErrorMessage(
char* buffer, uint32 buflen, int32 err) {
890 strcpy(buffer,
"String buffer not large enough");
894 err = Error::GetLastOSErrorNumber();
897 if (err == WSANOTINITIALISED) {
898 strcpy(buffer,
"Cannot initialize WinSock!");
900 else if (err == WSAENETDOWN) {
901 strcpy(buffer,
"The network subsystem or the associated service provider has failed");
903 else if (err == WSAEAFNOSUPPORT) {
904 strcpy(buffer,
"The specified address family is not supported");
906 else if (err == WSAEINPROGRESS) {
907 strcpy(buffer,
"A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function");
909 else if (err == WSAEMFILE) {
910 strcpy(buffer,
"No more socket descriptors are available");
912 else if (err == WSAENOBUFS) {
913 strcpy(buffer,
"No buffer space is available. The socket cannot be created");
915 else if (err == WSAEPROTONOSUPPORT) {
916 strcpy(buffer,
"The specified protocol is not supported");
918 else if (err == WSAEPROTOTYPE) {
919 strcpy(buffer,
"The specified protocol is the wrong type for this socket");
921 else if (err == WSAESOCKTNOSUPPORT) {
922 strcpy(buffer,
"The specified socket type is not supported in this address family");
924 else if (err == WSAEADDRINUSE) {
925 strcpy(buffer,
"The socket's local address is already in use and the socket was not marked to allow address reuse with SO_REUSEADDR. This error usually occurs during execution of the bind function, but could be delayed until this function if the bind was to a partially wildcard address (involving ADDR_ANY) and if a specific address needs to be committed at the time of this function");
927 else if (err == WSAEINVAL) {
928 strcpy(buffer,
"The socket has not been bound with bind");
930 else if (err == WSAEISCONN) {
931 strcpy(buffer,
"The socket is already connected");
933 else if (err == WSAENOTSOCK) {
934 strcpy(buffer,
"The descriptor is not a socket");
936 else if (err == WSAEOPNOTSUPP) {
937 strcpy(buffer,
"The referenced socket is not of a type that supports the listen operation");
939 else if (err == WSAEADDRNOTAVAIL) {
940 strcpy(buffer,
"The specified address is not a valid address for this machine");
942 else if (err == WSAEFAULT) {
943 strcpy(buffer,
"The name or namelen parameter is not a valid part of the user address space, the namelen parameter is too small, the name parameter contains an incorrect address format for the associated address family, or the first two bytes of the memory block specified by name does not match the address family associated with the socket descriptor s");
945 else if (err == WSAEMFILE) {
946 strcpy(buffer,
"The queue is nonempty upon entry to accept and there are no descriptors available");
948 else if (err == SOCKETWOULDBLOCK) {
949 strcpy(buffer,
"The socket is marked as nonblocking and no connections are present to be accepted");
951 else if (err == WSAETIMEDOUT) {
952 strcpy(buffer,
"Attempt to connect timed out without establishing a connection");
954 else if (err == WSAENETUNREACH) {
955 strcpy(buffer,
"The network cannot be reached from this host at this time");
957 else if (err == WSAEISCONN) {
958 strcpy(buffer,
"The socket is already connected (connection-oriented sockets only)");
960 else if (err == WSAECONNREFUSED) {
961 strcpy(buffer,
"The attempt to connect was forcefully rejected");
963 else if (err == WSAEAFNOSUPPORT) {
964 strcpy(buffer,
"Addresses in the specified family cannot be used with this socket");
966 else if (err == WSAEADDRNOTAVAIL) {
967 strcpy(buffer,
"The remote address is not a valid address (such as ADDR_ANY)");
969 else if (err == WSAEALREADY) {
970 strcpy(buffer,
"A nonblocking connect call is in progress on the specified socket");
972 else if (err == WSAECONNRESET) {
973 strcpy(buffer,
"Connection was reset");
975 else if (err == WSAECONNABORTED) {
976 strcpy(buffer,
"Software caused connection abort");
979 strcpy(buffer,
"Socket error with no description");
983 strcpy(buffer, strerror(err));
991 bool WaitForSocketReadability(socket s, int32 timeout) {
1011 ldiv_t d = ldiv(timeout * 1000, 1000000);
1017 int ret = select(maxfd, &rdds, NULL, NULL, &tv);
1021 bool WaitForSocketWriteability(socket s, int32 timeout) {
1041 ldiv_t d = ldiv(timeout * 1000, 1000000);
1047 return(select(maxfd, NULL, &wds, NULL, &tv) > 0);
1052 int32 String::StartsWith(
const std::string &s,
const std::string &str) {
1053 std::string::size_type pos = s.find_first_of(str);
1060 int32 String::EndsWith(
const std::string &s,
const std::string &str) {
1061 std::string::size_type pos = s.find_last_of(str);
1062 if (pos == s.size() - str.size())
1068 void String::MakeUpper(std::string &str)
1070 std::transform(str.begin(), str.end(), str.begin(), toupper);
1073 void String::MakeLower(std::string &str)
1075 std::transform(str.begin(), str.end(), str.begin(), tolower);
1078 void String::Trim(std::string& str,
const char* chars2remove)
1080 TrimLeft(str, chars2remove);
1081 TrimRight(str, chars2remove);
1084 void String::TrimLeft(std::string& str,
const char* chars2remove)
1088 std::string::size_type pos = str.find_first_not_of(chars2remove);
1090 if (pos != std::string::npos)
1093 str.erase(str.begin(), str.end());
1097 void String::TrimRight(std::string& str,
const char* chars2remove)
1101 std::string::size_type pos = str.find_last_not_of(chars2remove);
1103 if (pos != std::string::npos)
1106 str.erase(str.begin(), str.end());
1111 void String::ReplaceLeading(std::string& str,
const char* chars2replace,
char c)
1115 std::string::size_type pos = str.find_first_not_of(chars2replace);
1117 if (pos != std::string::npos)
1118 str.replace(0, pos, pos, c);
1122 str.replace(str.begin(), str.end() - 1, n - 1, c);
1129 int32 Random::r250_index_;
1130 int32 Random::r521_index_;
1131 uint32 Random::r250_buffer_[R250_LEN];
1132 uint32 Random::r521_buffer_[R521_LEN];
1134 void Random::Init() {
1138 uint32 mask2 = 0xFFFFFFFF;
1140 while (i-- > R250_LEN)
1141 r521_buffer_[i] = rand();
1144 r250_buffer_[i] = rand();
1145 r521_buffer_[i] = rand();
1152 r250_buffer_[i] = (rand() | mask1) & mask2;
1153 r521_buffer_[i] = (rand() | mask1) & mask2;
1157 r250_buffer_[0] = mask1;
1158 r521_buffer_[0] = mask2;
1163 float32 Random::operator ()(uint32 range) {
1175 int32 i1 = r250_index_;
1176 int32 i2 = r521_index_;
1177 uint8 *b1 = (uint8 *)r250_buffer_;
1178 uint8 *b2 = (uint8 *)r521_buffer_;
1179 uint32 *tmp1, *tmp2;
1190 tmp1 = (uint32 *)(b1 + i1);
1191 r = (*(uint32 *)(b1 + j1)) ^ (*tmp1);
1193 tmp2 = (uint32 *)(b2 + i2);
1194 s = (*(uint32 *)(b2 + j2)) ^ (*tmp2);
1197 i1 = (i1 !=
sizeof(uint32)*(R250_LEN - 1)) ? (i1 +
sizeof(uint32)) : 0;
1199 i2 = (i2 !=
sizeof(uint32)*(R521_LEN - 1)) ? (i2 +
sizeof(uint32)) : 0;