AERA
utils.cpp
1 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
2 //_/_/
3 //_/_/ AERA
4 //_/_/ Autocatalytic Endogenous Reflective Architecture
5 //_/_/
6 //_/_/ Copyright (c) 2018-2025 Jeff Thompson
7 //_/_/ Copyright (c) 2018-2025 Kristinn R. Thorisson
8 //_/_/ Copyright (c) 2018-2025 Icelandic Institute for Intelligent Machines
9 //_/_/ http://www.iiim.is
10 //_/_/
11 //_/_/ Copyright (c) 2010-2012 Eric Nivel, Thor List
12 //_/_/ Center for Analysis and Design of Intelligent Agents
13 //_/_/ Reykjavik University, Menntavegur 1, 102 Reykjavik, Iceland
14 //_/_/ http://cadia.ru.is
15 //_/_/
16 //_/_/ Part of this software was developed by Eric Nivel
17 //_/_/ in the HUMANOBS EU research project, which included
18 //_/_/ the following parties:
19 //_/_/
20 //_/_/ Autonomous Systems Laboratory
21 //_/_/ Technical University of Madrid, Spain
22 //_/_/ http://www.aslab.org/
23 //_/_/
24 //_/_/ Communicative Machines
25 //_/_/ Edinburgh, United Kingdom
26 //_/_/ http://www.cmlabs.com/
27 //_/_/
28 //_/_/ Istituto Dalle Molle di Studi sull'Intelligenza Artificiale
29 //_/_/ University of Lugano and SUPSI, Switzerland
30 //_/_/ http://www.idsia.ch/
31 //_/_/
32 //_/_/ Institute of Cognitive Sciences and Technologies
33 //_/_/ Consiglio Nazionale delle Ricerche, Italy
34 //_/_/ http://www.istc.cnr.it/
35 //_/_/
36 //_/_/ Dipartimento di Ingegneria Informatica
37 //_/_/ University of Palermo, Italy
38 //_/_/ http://diid.unipa.it/roboticslab/
39 //_/_/
40 //_/_/
41 //_/_/ --- HUMANOBS Open-Source BSD License, with CADIA Clause v 1.0 ---
42 //_/_/
43 //_/_/ Redistribution and use in source and binary forms, with or without
44 //_/_/ modification, is permitted provided that the following conditions
45 //_/_/ are met:
46 //_/_/ - Redistributions of source code must retain the above copyright
47 //_/_/ and collaboration notice, this list of conditions and the
48 //_/_/ following disclaimer.
49 //_/_/ - Redistributions in binary form must reproduce the above copyright
50 //_/_/ notice, this list of conditions and the following disclaimer
51 //_/_/ in the documentation and/or other materials provided with
52 //_/_/ the distribution.
53 //_/_/
54 //_/_/ - Neither the name of its copyright holders nor the names of its
55 //_/_/ contributors may be used to endorse or promote products
56 //_/_/ derived from this software without specific prior
57 //_/_/ written permission.
58 //_/_/
59 //_/_/ - CADIA Clause: The license granted in and to the software
60 //_/_/ under this agreement is a limited-use license.
61 //_/_/ The software may not be used in furtherance of:
62 //_/_/ (i) intentionally causing bodily injury or severe emotional
63 //_/_/ distress to any person;
64 //_/_/ (ii) invading the personal privacy or violating the human
65 //_/_/ rights of any person; or
66 //_/_/ (iii) committing or preparing for any act of war.
67 //_/_/
68 //_/_/ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
69 //_/_/ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
70 //_/_/ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
71 //_/_/ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
72 //_/_/ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
73 //_/_/ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
74 //_/_/ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
75 //_/_/ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
76 //_/_/ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
77 //_/_/ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
78 //_/_/ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
79 //_/_/ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
80 //_/_/ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
81 //_/_/ OF SUCH DAMAGE.
82 //_/_/
83 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
84 
85 #include "utils.h"
86 
87 using namespace std::chrono;
88 
89 #if defined WINDOWS
90 #include <intrin.h>
91 #pragma intrinsic (_InterlockedDecrement)
92 #pragma intrinsic (_InterlockedIncrement)
93 #pragma intrinsic (_InterlockedExchange)
94 #pragma intrinsic (_InterlockedExchange64)
95 #pragma intrinsic (_InterlockedCompareExchange)
96 #pragma intrinsic (_InterlockedCompareExchange64)
97 #elif defined LINUX
98 #endif
99 
100 #include <algorithm>
101 #include <cctype>
102 #include <ctime>
103 
104 
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)
109 
110 namespace core {
111 
112 #if defined LINUX
113 bool CalcTimeout(struct timespec &timeout, uint32 ms) {
114 
115  struct timeval now;
116  if (gettimeofday(&now, NULL) != 0)
117  return false;
118 
119  timeout.tv_sec = now.tv_sec + ms / 1000;
120  long us = now.tv_usec + ms % 1000;
121  if (us >= 1000000) {
122  timeout.tv_sec++;
123  us -= 1000000;
124  }
125  timeout.tv_nsec = us * 1000; // usec -> nsec
126  return true;
127 }
128 
129 uint64 GetTime() {
130  struct timeval tv;
131  if (gettimeofday(&tv, NULL))
132  return 0;
133  return (tv.tv_usec + tv.tv_sec * 1000000LL);
134 }
135 #endif
136 
137 void Error::PrintBinary(void* p, uint32 size, bool asInt, const char* title) {
138  if (title != NULL)
139  printf("--- %s %u ---\n", title, size);
140  unsigned char c;
141  for (uint32 n = 0; n < size; n++) {
142  c = *(((unsigned char*)p) + n);
143  if (asInt)
144  printf("[%u] ", (unsigned int)c);
145  else
146  printf("[%c] ", c);
147  if ((n > 0) && ((n + 1) % 10 == 0))
148  printf("\n");
149  }
150  printf("\n");
151 }
152 
153 SharedLibrary::SharedLibrary() : library_(NULL) {
154 }
155 
156 SharedLibrary::~SharedLibrary() {
157 #if defined WINDOWS
158  if (library_)
159  FreeLibrary(library_);
160 #elif defined LINUX
161  if (library_)
162  dlclose(library_);
163 #endif
164 }
165 
166 SharedLibrary *SharedLibrary::load(const char *fileName) {
167 #if defined WINDOWS
168  library_ = LoadLibrary(TEXT(fileName));
169  if (!library_) {
170 
171  DWORD error = GetLastError();
172  std::cerr << "> Error: unable to load shared library " << fileName << " :" << error << std::endl;
173  return NULL;
174  }
175 #elif defined LINUX
176  /*
177  * libraries on Linux are called 'lib<name>.so'
178  * if the passed in fileName does not have those
179  * components add them in.
180  */
181  char *libraryName = (char *)calloc(1, strlen(fileName) + 6 + 1);
182  if (strstr(fileName, "lib") == NULL) {
183  strcat(libraryName, "lib");
184  }
185  strcat(libraryName, fileName);
186  if (strstr(fileName + (strlen(fileName) - 3), ".so") == NULL) {
187  strcat(libraryName, ".so");
188  }
189  library_ = dlopen(libraryName, RTLD_NOW | RTLD_GLOBAL);
190  if (!library_) {
191  std::cout << "> Error: unable to load shared library " << fileName << " :" << dlerror() << std::endl;
192  free(libraryName);
193  return NULL;
194  }
195  free(libraryName);
196 #endif
197  return this;
198 }
199 
200 
201 void* SharedLibrary::getFunction(const char* functionName) {
202  void* function = NULL;
203 #if defined WINDOWS
204  if (library_) {
205 
206  function = GetProcAddress(library_, functionName);
207  if (!function) {
208 
209  DWORD error = GetLastError();
210  std::cerr << "GetProcAddress > Error: " << error << std::endl;
211  }
212  }
213 #elif defined LINUX
214  if (library_) {
215  function = dlsym(library_, functionName);
216  if (!function) {
217  std::cout << "> Error: unable to find symbol " << functionName << " :" << dlerror() << std::endl;
218  }
219  }
220 #endif
221  return function;
222 }
223 
225 
226 void Thread::TerminateAndWait(Thread **threads, uint32 threadCount) {
227  if (!threads)
228  return;
229  for (uint32 i = 0; i < threadCount; i++) {
230  threads[i]->terminate();
231  Thread::Wait(threads[i]);
232  }
233 }
234 
235 void Thread::TerminateAndWait(Thread *thread) {
236  if (!thread)
237  return;
238  thread->terminate();
239  Thread::Wait(thread);
240 }
241 
242 void Thread::Wait(Thread **threads, uint32 threadCount) {
243 
244  if (!threads)
245  return;
246 #if defined WINDOWS
247  for (uint32 i = 0; i < threadCount; i++)
248  WaitForSingleObject(threads[i]->thread_, INFINITE);
249 #elif defined LINUX
250  for (uint32 i = 0; i < threadCount; i++)
251  pthread_join(threads[i]->thread_, NULL);
252 #endif
253 }
254 
255 void Thread::Wait(Thread *thread) {
256 
257  if (!thread)
258  return;
259 #if defined WINDOWS
260  WaitForSingleObject(thread->thread_, INFINITE);
261 #elif defined LINUX
262  pthread_join(thread->thread_, NULL);
263 #endif
264 }
265 
266 void Thread::Sleep(milliseconds ms) {
267 #if defined WINDOWS
268  ::Sleep((uint32)ms.count());
269 #elif defined LINUX
270  // we are actually being passed millisecond, so multiply up
271  usleep(ms.count() * 1000);
272 #endif
273 }
274 
275 void Thread::Sleep() {
276 #if defined WINDOWS
277  ::Sleep(INFINITE);
278 #elif defined LINUX
279  while (true)
280  sleep(1000);
281 #endif
282 }
283 
284 Thread::Thread() : is_meaningful_(false) {
285  thread_ = 0;
286 }
287 
288 Thread::~Thread() {
289 #if defined WINDOWS
290  // ExitThread(0);
291  if (is_meaningful_)
292  CloseHandle(thread_);
293 #elif defined LINUX
294  // delete(thread_);
295 #endif
296 }
297 
298 void Thread::start(thread_function f) {
299 #if defined WINDOWS
300  thread_ = CreateThread(NULL, 65536, f, this, 0, NULL); // 64KB: minimum initial stack size
301 #elif defined LINUX
302  pthread_create(&thread_, NULL, f, this);
303 #endif
304  is_meaningful_ = true;
305 }
306 
307 void Thread::suspend() {
308 #if defined WINDOWS
309  SuspendThread(thread_);
310 #elif defined LINUX
311  pthread_kill(thread_, SIGSTOP);
312 #endif
313 }
314 
315 void Thread::resume() {
316 #if defined WINDOWS
317  ResumeThread(thread_);
318 #elif defined LINUX
319  pthread_kill(thread_, SIGCONT);
320 #endif
321 }
322 
323 void Thread::terminate() {
324 #if defined WINDOWS
325  TerminateThread(thread_, 0);
326 #elif defined LINUX
327  pthread_cancel(thread_);
328 #endif
329 }
330 
332 
333 void TimeProbe::set() {
334 
335  cpu_counts_ = getCounts();
336 }
337 
338 int64 TimeProbe::getCounts() {
339 #if defined WINDOWS
340  LARGE_INTEGER counter;
341  QueryPerformanceCounter(&counter);
342  return counter.QuadPart;
343 #elif defined LINUX
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;
348 #endif
349 }
350 
351 void TimeProbe::check() {
352 
353  cpu_counts_ = getCounts() - cpu_counts_;
354 }
355 
357 
358 #if defined WINDOWS
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);
363 #elif defined LINUX
364  // TODO
365 #endif
366 
367 float64 Time::Period_;
368 
369 Timestamp Time::InitTime_;
370 
371 void Time::Init(uint32 r) {
372 #if defined WINDOWS
373  NTSTATUS nts;
374  HMODULE NTDll = ::LoadLibrary("NTDLL");
375  ULONG actualResolution = 0;
376  if (NTDll) {
377 
378  NSTR pNSTR = (NSTR)::GetProcAddress(NTDll, "NtSetTimerResolution"); // undocumented win xp sys internals
379  if (pNSTR)
380  nts = (*pNSTR)(10 * r, true, &actualResolution); // in 100 ns units
381  }
382  LARGE_INTEGER f;
383  QueryPerformanceFrequency(&f);
384  Period_ = 1000000.0 / f.QuadPart; // in us
385  struct _timeb local_time;
386  _ftime(&local_time);
387  auto now = Timestamp(microseconds((int64)(local_time.time * 1000 + local_time.millitm) * 1000));
388  // The QueryPerformanceCounter in Get() may not start at zero, so subtract it initially.
389  InitTime_ = Timestamp(seconds(0));
390  InitTime_ = now - Get().time_since_epoch();
391 #elif defined LINUX
392  // The steady_clock in Get() may not start at zero, so subtract it initially.
393  InitTime_ = system_clock_us::now() - duration_cast<microseconds>(steady_clock::now().time_since_epoch());
394 #endif
395 }
396 
397 Timestamp Time::Get() {
398 #if defined WINDOWS
399  LARGE_INTEGER counter;
400  QueryPerformanceCounter(&counter);
401  return InitTime_ + microseconds((uint64)(counter.QuadPart * Period_));
402 #elif defined LINUX
403  return InitTime_ + duration_cast<microseconds>(steady_clock::now().time_since_epoch());
404 #endif
405 }
406 
407 std::string Time::ToString_year(Timestamp timestamp) {
408  // For now, assume all times are after the epoch. Take the absolute value to be sure.
409  uint64 t = abs(duration_cast<microseconds>(timestamp.time_since_epoch()).count());
410 
411  uint64 us = t % 1000;
412  uint64 ms = t / 1000;
413  uint64 s = ms / 1000;
414  ms = ms % 1000;
415 
416  time_t _gmt_time = s;
417  struct tm *_t = gmtime(&_gmt_time);
418 
419  std::string _s = asctime(_t); // _s is: Www Mmm dd hh:mm:ss yyyy but we want: Www Mmm dd yyyy hh:mm:ss:msmsms:ususus
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);
423  hh_mm_ss += ":";
424  hh_mm_ss += std::to_string(ms);
425  hh_mm_ss += ":";
426  hh_mm_ss += std::to_string(us);
427 
428  _s.erase(_s.length() - 9, 9);
429  _s += year;
430  _s += " ";
431  _s += hh_mm_ss;
432  _s += " GMT";
433 
434  return _s;
435 }
436 
438 
439 uint8 Host::Name(char *name) {
440 #if defined WINDOWS
441  DWORD s = 255;
442  GetComputerName(name, &s);
443  return (uint8)s;
444 #elif defined LINUX
445  struct utsname utsname;
446  uname(&utsname);
447  strcpy(name, utsname.nodename);
448  return strlen(name);
449 #endif
450 }
451 
453 
454 #if defined WINDOWS
455 const uint32 Semaphore::Infinite = INFINITE;
456 #elif defined LINUX
457  /*
458  * Normally this should be SEM_VALUE_MAX but apparently the <semaphore.h> header
459  * does not define it. The documents I have read indicate that on Linux it is
460  * always equal to INT_MAX - so use that instead.
461  */
462 const uint32 Semaphore::Infinite = INT_MAX;
463 #endif
464 
465 Semaphore::Semaphore(uint32 initialCount, uint32 maxCount) {
466 #if defined WINDOWS
467  s_ = CreateSemaphore(NULL, initialCount, maxCount, NULL);
468 #elif defined LINUX
469  sem_init(&s_, 0, initialCount);
470 #endif
471 }
472 
473 Semaphore::~Semaphore() {
474 #if defined WINDOWS
475  CloseHandle(s_);
476 #elif defined LINUX
477  sem_destroy(&s_);
478 #endif
479 }
480 
481 bool Semaphore::acquire(uint32 timeout) {
482 #if defined WINDOWS
483  uint32 r = WaitForSingleObject(s_, timeout);
484  return r == WAIT_TIMEOUT;
485 #elif defined LINUX
486  struct timespec t;
487  int r;
488 
489  CalcTimeout(t, timeout);
490  r = sem_timedwait(&s_, &t);
491  return r == 0;
492 #endif
493 }
494 
495 void Semaphore::release(uint32 count) {
496 #if defined WINDOWS
497  ReleaseSemaphore(s_, count, NULL);
498 #elif defined LINUX
499  for (uint32 c = 0; c < count; c++)
500  sem_post(&s_);
501 #endif
502 }
503 
504 void Semaphore::reset() {
505 #if defined WINDOWS
506  bool r;
507  do
508  r = acquire(0);
509  while (!r);
510 #elif defined LINUX
511  bool r;
512  do
513  r = acquire(0);
514  while (!r);
515 #endif
516 }
517 
519 
520 #if defined WINDOWS
521 const uint32 Mutex::Infinite = INFINITE;
522 #elif defined LINUX
523  /*
524  * Normally this should be SEM_VALUE_MAX but apparently the <semaphore.h> header
525  * does not define it. The documents I have read indicate that on Linux it is
526  * always equal to INT_MAX - so use that instead.
527  */
528 const uint32 Mutex::Infinite = INT_MAX;
529 #endif
530 
531 Mutex::Mutex() {
532 #if defined WINDOWS
533  m_ = CreateMutex(NULL, false, NULL);
534 #elif defined LINUX
535  pthread_mutex_init(&m_, NULL);
536 #endif
537 }
538 
539 Mutex::~Mutex() {
540 #if defined WINDOWS
541  CloseHandle(m_);
542 #elif defined LINUX
543  pthread_mutex_destroy(&m_);
544 #endif
545 }
546 
547 bool Mutex::acquire(uint32 timeout) {
548 #if defined WINDOWS
549  uint32 r = WaitForSingleObject(m_, timeout);
550  return r == WAIT_TIMEOUT;
551 #elif defined LINUX
552  auto start = Time::Get();
553  auto uTimeout = microseconds(timeout * 1000);
554 
555  while (pthread_mutex_trylock(&m_) != 0) {
556  Thread::Sleep(milliseconds(10));
557  if (Time::Get() - start >= uTimeout)
558  return false;
559  }
560  return true;
561 
562 #endif
563 }
564 
565 void Mutex::release() {
566 #if defined WINDOWS
567  ReleaseMutex(m_);
568 #elif defined LINUX
569  pthread_mutex_unlock(&m_);
570 #endif
571 }
572 
574 
575 CriticalSection::CriticalSection() {
576 #if defined WINDOWS
577  InitializeCriticalSection(&cs_);
578 #elif defined LINUX
579  pthread_mutex_init(&cs_, NULL);
580 #endif
581 }
582 
583 CriticalSection::~CriticalSection() {
584 #if defined WINDOWS
585  DeleteCriticalSection(&cs_);
586 #elif defined LINUX
587  pthread_mutex_destroy(&cs_);
588 #endif
589 }
590 
591 void CriticalSection::enter() {
592 #if defined WINDOWS
593  EnterCriticalSection(&cs_);
594 #elif defined LINUX
595  pthread_mutex_lock(&cs_);
596 #endif
597 }
598 
599 void CriticalSection::leave() {
600 #if defined WINDOWS
601  LeaveCriticalSection(&cs_);
602 #elif defined LINUX
603  pthread_mutex_unlock(&cs_);
604 #endif
605 }
606 
608 
609 #if defined WINDOWS
610 const uint32 Timer::Infinite = INFINITE;
611 #elif defined LINUX
612 const uint32 Timer::Infinite = INT_MAX;
613 
614 static void timer_signal_handler(int sig, siginfo_t *siginfo, void *context) {
615  SemaTex* sematex = (SemaTex*)siginfo->si_value.sival_ptr;
616  if (sematex == NULL)
617  return;
618  pthread_mutex_lock(&sematex->mutex);
619  pthread_cond_broadcast(&sematex->semaphore);
620  pthread_mutex_unlock(&sematex->mutex);
621 }
622 #endif
623 
624 Timer::Timer() {
625 #if defined WINDOWS
626  t_ = CreateWaitableTimer(NULL, false, NULL);
627  if (t_ == NULL) {
628  printf("Error creating timer\n");
629  }
630 #elif defined LINUX
631  pthread_cond_init(&sematex.semaphore, NULL);
632  pthread_mutex_init(&sematex.mutex, NULL);
633 
634  struct sigaction sa;
635  struct sigevent timer_event;
636 
637  sigemptyset(&sa.sa_mask);
638  sa.sa_flags = SA_SIGINFO; /* Real-Time signal */
639  sa.sa_sigaction = timer_signal_handler;
640  sigaction(SIGRTMIN, &sa, NULL);
641 
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);
646  if (ret != 0) {
647  printf("Error creating timer: %d\n", ret);
648  }
649 #endif
650 }
651 
652 Timer::~Timer() {
653 #if defined WINDOWS
654  CloseHandle(t_);
655 #elif defined LINUX
656  pthread_cond_destroy(&sematex.semaphore);
657  pthread_mutex_destroy(&sematex.mutex);
658  timer_delete(timer);
659 #endif
660 }
661 
662 void Timer::start(microseconds deadline, milliseconds period) {
663 #if defined WINDOWS
664  LARGE_INTEGER _deadline; // in 100 ns intervals
665  _deadline.QuadPart = -10LL * deadline.count(); // negative means relative
666  bool r = SetWaitableTimer(t_, &_deadline, (long)period.count(), NULL, NULL, 0);
667  if (!r) {
668  printf("Error arming timer\n");
669  }
670 #elif defined LINUX
671  struct itimerspec newtv;
672  sigset_t allsigs;
673 
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;
680 
681  pthread_mutex_lock(&sematex.mutex);
682 
683  int ret = timer_settime(timer, 0, &newtv, NULL);
684  if (ret != 0) {
685  printf("Error arming timer: %d\n", ret);
686  }
687  sigemptyset(&allsigs);
688 
689  pthread_mutex_unlock(&sematex.mutex);
690 #endif
691 }
692 
693 bool Timer::wait(uint32 timeout) {
694 #if defined WINDOWS
695  uint32 r = WaitForSingleObject(t_, timeout);
696  return r == WAIT_TIMEOUT;
697 #elif defined LINUX
698  bool res;
699  struct timespec ttimeout;
700 
701  pthread_mutex_lock(&sematex.mutex);
702  if (timeout == INT_MAX) {
703  res = (pthread_cond_wait(&sematex.semaphore, &sematex.mutex) == 0);
704  }
705  else {
706  CalcTimeout(ttimeout, timeout);
707  res = (pthread_cond_timedwait(&sematex.semaphore, &sematex.mutex, &ttimeout) == 0);
708  }
709  pthread_mutex_unlock(&sematex.mutex);
710  return res;
711 #endif
712 }
713 
715 
716 Event::Event() {
717 #if defined WINDOWS
718  e_ = CreateEvent(NULL, true, false, NULL);
719 #elif defined LINUX
720  // TODO.
721 #endif
722 }
723 
724 Event::~Event() {
725 #if defined WINDOWS
726  CloseHandle(e_);
727 #elif defined LINUX
728  // TODO.
729 #endif
730 }
731 
732 void Event::wait() {
733 #if defined WINDOWS
734  WaitForSingleObject(e_, INFINITE);
735 #elif defined LINUX
736  // TODO.
737 #endif
738 }
739 
740 void Event::fire() {
741 #if defined WINDOWS
742  SetEvent(e_);
743 #elif defined LINUX
744  // TODO.
745 #endif
746 }
747 
748 void Event::reset() {
749 #if defined WINDOWS
750  ResetEvent(e_);
751 #elif defined LINUX
752  // TODO.
753 #endif
754 }
755 
757 
758 void SignalHandler::Add(signal_handler h) {
759 #if defined WINDOWS
760  if (SetConsoleCtrlHandler(h, true) == 0) {
761 
762  int e = GetLastError();
763  std::cerr << "Error: " << e << " failed to add signal handler" << std::endl;
764  return;
765  }
766 #elif defined LINUX
767  signal(SIGABRT, SIG_IGN);
768  signal(SIGPIPE, SIG_IGN);
769  signal(SIGBUS, SIG_IGN);
770  // signal(SIGHUP, h);
771  signal(SIGTERM, h);
772  signal(SIGINT, h);
773  signal(SIGABRT, h);
774  // signal(SIGFPE, h);
775  // signal(SIGILL, h);
776  // signal(SIGSEGV, h);
777 #endif
778 }
779 
780 void SignalHandler::Remove(signal_handler h) {
781 #if defined WINDOWS
782  SetConsoleCtrlHandler(h, false);
783 #elif defined LINUX
784  signal(SIGABRT, SIG_IGN);
785  signal(SIGPIPE, SIG_IGN);
786  signal(SIGBUS, SIG_IGN);
787  // signal(SIGHUP, SIG_DFL);
788  signal(SIGTERM, SIG_DFL);
789  signal(SIGINT, SIG_DFL);
790  signal(SIGABRT, SIG_DFL);
791  // signal(SIGFPE, SIG_DFL);
792  // signal(SIGILL, SIG_DFL);
793  // signal(SIGSEGV, SIG_DFL);
794 #endif
795 }
796 
798 
799 uint8 BSR(word data) {
800 #if defined WINDOWS
801 #if defined ARCH_32
802  DWORD index;
803  _BitScanReverse(&index, data);
804  return (uint8)index;
805 #elif defined ARCH_64
806  DWORD index;
807  _BitScanReverse64(&index, data);
808  return (uint8)index;
809 #endif
810 #elif defined LINUX
811 #if defined ARCH_32
812  return (uint8)(31 - __builtin_clz((uint32_t)data));
813 #elif defined ARCH_64
814  return (uint8)(63 - __builtin_clzll((uint64_t)data));
815 #endif
816 #endif
817 }
818 
820 
821 FastSemaphore::FastSemaphore(uint32 initialCount, uint32 maxCount) : Semaphore(initialCount > 0 ? 1 : 0, 1), count_(initialCount), maxCount_(maxCount) {
822 }
823 
824 FastSemaphore::~FastSemaphore() {
825 }
826 
827 void FastSemaphore::acquire() {
828 
829  int32 c;
830  while ((c = --count_) >= maxCount_); // release calls can bring count over maxCount_: acquire has to exhaust these extras
831  if (c < 0)
832  Semaphore::acquire();
833 }
834 
835 void FastSemaphore::release() {
836 
837  int32 c = ++count_;
838  if (c <= 0)
839  Semaphore::release();
840 }
841 
843 /*
844  FastMutex::FastMutex(uint32 initialCount):Semaphore(initialCount,1),count_(initialCount){
845  }
846 
847  FastMutex::~FastMutex(){
848  }
849 
850  void FastMutex::acquire(){
851 
852  int32 former=Atomic::Swap32(&count_,0);
853  if(former==0)
854  Semaphore::acquire();
855  }
856 
857  void FastMutex::release(){
858 
859  int32 former=Atomic::Swap32(&count_,1);
860  if(former==0)
861  Semaphore::release();
862  }
863  */
865 
866 bool Error::PrintLastOSErrorMessage(const char* title) {
867  int32 err = Error::GetLastOSErrorNumber();
868  char buf[1024];
869  if (!Error::GetOSErrorMessage(buf, 1024, err))
870  printf("%s: [%d] (could not get error message)\n", title, err);
871  else
872  printf("%s: [%d] %s\n", title, err, buf);
873  return true;
874 }
875 
876 int32 Error::GetLastOSErrorNumber() {
877 #ifdef WINDOWS
878  int32 err = WSAGetLastError();
879  WSASetLastError(0);
880  return err;
881 #else
882  return (int32)errno;
883 #endif
884 }
885 
886 bool Error::GetOSErrorMessage(char* buffer, uint32 buflen, int32 err) {
887  if (buffer == NULL)
888  return false;
889  if (buflen < 512) {
890  strcpy(buffer, "String buffer not large enough");
891  return false;
892  }
893  if (err < 0)
894  err = Error::GetLastOSErrorNumber();
895 
896 #ifdef WINDOWS
897  if (err == WSANOTINITIALISED) {
898  strcpy(buffer, "Cannot initialize WinSock!");
899  }
900  else if (err == WSAENETDOWN) {
901  strcpy(buffer, "The network subsystem or the associated service provider has failed");
902  }
903  else if (err == WSAEAFNOSUPPORT) {
904  strcpy(buffer, "The specified address family is not supported");
905  }
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");
908  }
909  else if (err == WSAEMFILE) {
910  strcpy(buffer, "No more socket descriptors are available");
911  }
912  else if (err == WSAENOBUFS) {
913  strcpy(buffer, "No buffer space is available. The socket cannot be created");
914  }
915  else if (err == WSAEPROTONOSUPPORT) {
916  strcpy(buffer, "The specified protocol is not supported");
917  }
918  else if (err == WSAEPROTOTYPE) {
919  strcpy(buffer, "The specified protocol is the wrong type for this socket");
920  }
921  else if (err == WSAESOCKTNOSUPPORT) {
922  strcpy(buffer, "The specified socket type is not supported in this address family");
923  }
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");
926  }
927  else if (err == WSAEINVAL) {
928  strcpy(buffer, "The socket has not been bound with bind");
929  }
930  else if (err == WSAEISCONN) {
931  strcpy(buffer, "The socket is already connected");
932  }
933  else if (err == WSAENOTSOCK) {
934  strcpy(buffer, "The descriptor is not a socket");
935  }
936  else if (err == WSAEOPNOTSUPP) {
937  strcpy(buffer, "The referenced socket is not of a type that supports the listen operation");
938  }
939  else if (err == WSAEADDRNOTAVAIL) {
940  strcpy(buffer, "The specified address is not a valid address for this machine");
941  }
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");
944  }
945  else if (err == WSAEMFILE) {
946  strcpy(buffer, "The queue is nonempty upon entry to accept and there are no descriptors available");
947  }
948  else if (err == SOCKETWOULDBLOCK) {
949  strcpy(buffer, "The socket is marked as nonblocking and no connections are present to be accepted");
950  }
951  else if (err == WSAETIMEDOUT) {
952  strcpy(buffer, "Attempt to connect timed out without establishing a connection");
953  }
954  else if (err == WSAENETUNREACH) {
955  strcpy(buffer, "The network cannot be reached from this host at this time");
956  }
957  else if (err == WSAEISCONN) {
958  strcpy(buffer, "The socket is already connected (connection-oriented sockets only)");
959  }
960  else if (err == WSAECONNREFUSED) {
961  strcpy(buffer, "The attempt to connect was forcefully rejected");
962  }
963  else if (err == WSAEAFNOSUPPORT) {
964  strcpy(buffer, "Addresses in the specified family cannot be used with this socket");
965  }
966  else if (err == WSAEADDRNOTAVAIL) {
967  strcpy(buffer, "The remote address is not a valid address (such as ADDR_ANY)");
968  }
969  else if (err == WSAEALREADY) {
970  strcpy(buffer, "A nonblocking connect call is in progress on the specified socket");
971  }
972  else if (err == WSAECONNRESET) {
973  strcpy(buffer, "Connection was reset");
974  }
975  else if (err == WSAECONNABORTED) {
976  strcpy(buffer, "Software caused connection abort");
977  }
978  else {
979  strcpy(buffer, "Socket error with no description");
980  }
981 
982 #else
983  strcpy(buffer, strerror(err));
984 #endif
985 
986  return true;
987 }
988 
990 
991 bool WaitForSocketReadability(socket s, int32 timeout) {
992 
993  int maxfd = 0;
994 
995  struct timeval tv;
996  tv.tv_sec = 0;
997  tv.tv_usec = 0;
998 
999  fd_set rdds;
1000  // create a list of sockets to check for activity
1001  FD_ZERO(&rdds);
1002  // specify mySocket
1003  FD_SET(s, &rdds);
1004 
1005 #ifdef WINDOWS
1006 #else
1007  maxfd = s + 1;
1008 #endif
1009 
1010  if (timeout > 0) {
1011  ldiv_t d = ldiv(timeout * 1000, 1000000);
1012  tv.tv_sec = d.quot;
1013  tv.tv_usec = d.rem;
1014  }
1015 
1016  // Check for readability
1017  int ret = select(maxfd, &rdds, NULL, NULL, &tv);
1018  return(ret > 0);
1019 }
1020 
1021 bool WaitForSocketWriteability(socket s, int32 timeout) {
1022 
1023  int maxfd = 0;
1024 
1025  struct timeval tv;
1026  tv.tv_sec = 0;
1027  tv.tv_usec = 0;
1028 
1029  fd_set wds;
1030  // create a list of sockets to check for activity
1031  FD_ZERO(&wds);
1032  // specify mySocket
1033  FD_SET(s, &wds);
1034 
1035 #ifdef WINDOWS
1036 #else
1037  maxfd = s + 1;
1038 #endif
1039 
1040  if (timeout > 0) {
1041  ldiv_t d = ldiv(timeout * 1000, 1000000);
1042  tv.tv_sec = d.quot;
1043  tv.tv_usec = d.rem;
1044  }
1045 
1046  // Check for readability
1047  return(select(maxfd, NULL, &wds, NULL, &tv) > 0);
1048 }
1049 
1051 
1052 int32 String::StartsWith(const std::string &s, const std::string &str) {
1053  std::string::size_type pos = s.find_first_of(str);
1054  if (pos == 0)
1055  return 0;
1056  else
1057  return -1;
1058 }
1059 
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())
1063  return pos;
1064  else
1065  return -1;
1066 }
1067 
1068 void String::MakeUpper(std::string &str)
1069 {
1070  std::transform(str.begin(), str.end(), str.begin(), toupper);
1071 }
1072 
1073 void String::MakeLower(std::string &str)
1074 {
1075  std::transform(str.begin(), str.end(), str.begin(), tolower);
1076 }
1077 
1078 void String::Trim(std::string& str, const char* chars2remove)
1079 {
1080  TrimLeft(str, chars2remove);
1081  TrimRight(str, chars2remove);
1082 }
1083 
1084 void String::TrimLeft(std::string& str, const char* chars2remove)
1085 {
1086  if (!str.empty())
1087  {
1088  std::string::size_type pos = str.find_first_not_of(chars2remove);
1089 
1090  if (pos != std::string::npos)
1091  str.erase(0, pos);
1092  else
1093  str.erase(str.begin(), str.end()); // make empty
1094  }
1095 }
1096 
1097 void String::TrimRight(std::string& str, const char* chars2remove)
1098 {
1099  if (!str.empty())
1100  {
1101  std::string::size_type pos = str.find_last_not_of(chars2remove);
1102 
1103  if (pos != std::string::npos)
1104  str.erase(pos + 1);
1105  else
1106  str.erase(str.begin(), str.end()); // make empty
1107  }
1108 }
1109 
1110 
1111 void String::ReplaceLeading(std::string& str, const char* chars2replace, char c)
1112 {
1113  if (!str.empty())
1114  {
1115  std::string::size_type pos = str.find_first_not_of(chars2replace);
1116 
1117  if (pos != std::string::npos)
1118  str.replace(0, pos, pos, c);
1119  else
1120  {
1121  int n = str.size();
1122  str.replace(str.begin(), str.end() - 1, n - 1, c);
1123  }
1124  }
1125 }
1126 
1128 
1129 int32 Random::r250_index_;
1130 int32 Random::r521_index_;
1131 uint32 Random::r250_buffer_[R250_LEN];
1132 uint32 Random::r521_buffer_[R521_LEN];
1133 
1134 void Random::Init() {
1135 
1136  int32 i = R521_LEN;
1137  uint32 mask1 = 1;
1138  uint32 mask2 = 0xFFFFFFFF;
1139 
1140  while (i-- > R250_LEN)
1141  r521_buffer_[i] = rand();
1142  while (i-- > 31) {
1143 
1144  r250_buffer_[i] = rand();
1145  r521_buffer_[i] = rand();
1146  }
1147 
1148  // Establish linear independence of the bit columns
1149  // by setting the diagonal bits and clearing all bits above
1150  while (i-- > 0) {
1151 
1152  r250_buffer_[i] = (rand() | mask1) & mask2;
1153  r521_buffer_[i] = (rand() | mask1) & mask2;
1154  mask2 ^= mask1;
1155  mask1 >>= 1;
1156  }
1157  r250_buffer_[0] = mask1;
1158  r521_buffer_[0] = mask2;
1159  r250_index_ = 0;
1160  r521_index_ = 0;
1161 }
1162 
1163 float32 Random::operator ()(uint32 range) {
1164  /*
1165  I prescale the indices by sizeof(unsigned long) to eliminate
1166  four shlwi instructions in the compiled code. This minor optimization
1167  increased perf by about 12%.
1168 
1169  I also carefully arrange index increments and comparisons to minimize
1170  instructions. gcc 3.3 seems a bit weak on instruction reordering. The
1171  j1/j2 branches are mispredicted, but nevertheless these optimizations
1172  increased perf by another 10%.
1173  */
1174 
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;
1180  uint32 r, s;
1181  int32 j1, j2;
1182 
1183  j1 = i1 - R250_IB;
1184  if (j1 < 0)
1185  j1 = i1 + R250_IA;
1186  j2 = i2 - R521_IB;
1187  if (j2 < 0)
1188  j2 = i2 + R521_IA;
1189 
1190  tmp1 = (uint32 *)(b1 + i1);
1191  r = (*(uint32 *)(b1 + j1)) ^ (*tmp1);
1192  *tmp1 = r;
1193  tmp2 = (uint32 *)(b2 + i2);
1194  s = (*(uint32 *)(b2 + j2)) ^ (*tmp2);
1195  *tmp2 = s;
1196 
1197  i1 = (i1 != sizeof(uint32)*(R250_LEN - 1)) ? (i1 + sizeof(uint32)) : 0;
1198  r250_index_ = i1;
1199  i2 = (i2 != sizeof(uint32)*(R521_LEN - 1)) ? (i2 + sizeof(uint32)) : 0;
1200  r521_index_ = i2;
1201 
1202  float32 _r = r ^ s;
1203  //return range*(_r/((float32)ULONG_MAX));
1204  return _r;
1205 }
1206 }