AERA
utils.cpp
1 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
2 //_/_/
3 //_/_/ AERA
4 //_/_/ Autocatalytic Endogenous Reflective Architecture
5 //_/_/
6 //_/_/ Copyright (c) 2018-2021 Jeff Thompson
7 //_/_/ Copyright (c) 2018-2021 Kristinn R. Thorisson
8 //_/_/ Copyright (c) 2018-2021 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::New(const char *fileName) {
154 
155  SharedLibrary *sl = new SharedLibrary();
156  if (sl->load(fileName))
157  return sl;
158  else {
159 
160  delete sl;
161  return NULL;
162  }
163 }
164 
165 SharedLibrary::SharedLibrary() : library_(NULL) {
166 }
167 
168 SharedLibrary::~SharedLibrary() {
169 #if defined WINDOWS
170  if (library_)
171  FreeLibrary(library_);
172 #elif defined LINUX
173  if (library_)
174  dlclose(library_);
175 #endif
176 }
177 
178 SharedLibrary *SharedLibrary::load(const char *fileName) {
179 #if defined WINDOWS
180  library_ = LoadLibrary(TEXT(fileName));
181  if (!library_) {
182 
183  DWORD error = GetLastError();
184  std::cerr << "> Error: unable to load shared library " << fileName << " :" << error << std::endl;
185  return NULL;
186  }
187 #elif defined LINUX
188  /*
189  * libraries on Linux are called 'lib<name>.so'
190  * if the passed in fileName does not have those
191  * components add them in.
192  */
193  char *libraryName = (char *)calloc(1, strlen(fileName) + 6 + 1);
194  if (strstr(fileName, "lib") == NULL) {
195  strcat(libraryName, "lib");
196  }
197  strcat(libraryName, fileName);
198  if (strstr(fileName + (strlen(fileName) - 3), ".so") == NULL) {
199  strcat(libraryName, ".so");
200  }
201  library_ = dlopen(libraryName, RTLD_NOW | RTLD_GLOBAL);
202  if (!library_) {
203  std::cout << "> Error: unable to load shared library " << fileName << " :" << dlerror() << std::endl;
204  free(libraryName);
205  return NULL;
206  }
207  free(libraryName);
208 #endif
209  return this;
210 }
211 
213 
214 void Thread::TerminateAndWait(Thread **threads, uint32 threadCount) {
215  if (!threads)
216  return;
217  for (uint32 i = 0; i < threadCount; i++) {
218  threads[i]->terminate();
219  Thread::Wait(threads[i]);
220  }
221 }
222 
223 void Thread::TerminateAndWait(Thread *thread) {
224  if (!thread)
225  return;
226  thread->terminate();
227  Thread::Wait(thread);
228 }
229 
230 void Thread::Wait(Thread **threads, uint32 threadCount) {
231 
232  if (!threads)
233  return;
234 #if defined WINDOWS
235  for (uint32 i = 0; i < threadCount; i++)
236  WaitForSingleObject(threads[i]->thread_, INFINITE);
237 #elif defined LINUX
238  for (uint32 i = 0; i < threadCount; i++)
239  pthread_join(threads[i]->thread_, NULL);
240 #endif
241 }
242 
243 void Thread::Wait(Thread *thread) {
244 
245  if (!thread)
246  return;
247 #if defined WINDOWS
248  WaitForSingleObject(thread->thread_, INFINITE);
249 #elif defined LINUX
250  pthread_join(thread->thread_, NULL);
251 #endif
252 }
253 
254 void Thread::Sleep(milliseconds ms) {
255 #if defined WINDOWS
256  ::Sleep((uint32)ms.count());
257 #elif defined LINUX
258  // we are actually being passed millisecond, so multiply up
259  usleep(ms * 1000);
260 #endif
261 }
262 
263 void Thread::Sleep() {
264 #if defined WINDOWS
265  ::Sleep(INFINITE);
266 #elif defined LINUX
267  while (true)
268  sleep(1000);
269 #endif
270 }
271 
272 Thread::Thread() : is_meaningful_(false) {
273  thread_ = NULL;
274 }
275 
276 Thread::~Thread() {
277 #if defined WINDOWS
278  // ExitThread(0);
279  if (is_meaningful_)
280  CloseHandle(thread_);
281 #elif defined LINUX
282  // delete(thread_);
283 #endif
284 }
285 
286 void Thread::start(thread_function f) {
287 #if defined WINDOWS
288  thread_ = CreateThread(NULL, 65536, f, this, 0, NULL); // 64KB: minimum initial stack size
289 #elif defined LINUX
290  pthread_create(&thread_, NULL, f, this);
291 #endif
292  is_meaningful_ = true;
293 }
294 
295 void Thread::suspend() {
296 #if defined WINDOWS
297  SuspendThread(thread_);
298 #elif defined LINUX
299  pthread_kill(thread_, SIGSTOP);
300 #endif
301 }
302 
303 void Thread::resume() {
304 #if defined WINDOWS
305  ResumeThread(thread_);
306 #elif defined LINUX
307  pthread_kill(thread_, SIGCONT);
308 #endif
309 }
310 
311 void Thread::terminate() {
312 #if defined WINDOWS
313  TerminateThread(thread_, 0);
314 #elif defined LINUX
315  pthread_cancel(thread_);
316 #endif
317 }
318 
320 
321 void TimeProbe::set() {
322 
323  cpu_counts_ = getCounts();
324 }
325 
326 int64 TimeProbe::getCounts() {
327 #if defined WINDOWS
328  LARGE_INTEGER counter;
329  QueryPerformanceCounter(&counter);
330  return counter.QuadPart;
331 #elif defined LINUX
332  static struct timeval tv;
333  static struct timezone tz;
334  gettimeofday(&tv, &tz);
335  return (((int64)tv.tv_sec) * 1000000) + (int64)tv.tv_usec;
336 #endif
337 }
338 
339 void TimeProbe::check() {
340 
341  cpu_counts_ = getCounts() - cpu_counts_;
342 }
343 
345 
346 #if defined WINDOWS
347 typedef LONG NTSTATUS;
348 typedef NTSTATUS(__stdcall *NSTR)(ULONG, BOOLEAN, PULONG);
349 #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
350 bool NtSetTimerResolution(IN ULONG RequestedResolution, IN BOOLEAN Set, OUT PULONG ActualResolution);
351 #elif defined LINUX
352  // TODO
353 #endif
354 
355 float64 Time::Period_;
356 
357 Timestamp Time::InitTime_;
358 
359 void Time::Init(uint32 r) {
360 #if defined WINDOWS
361  NTSTATUS nts;
362  HMODULE NTDll = ::LoadLibrary("NTDLL");
363  ULONG actualResolution = 0;
364  if (NTDll) {
365 
366  NSTR pNSTR = (NSTR)::GetProcAddress(NTDll, "NtSetTimerResolution"); // undocumented win xp sys internals
367  if (pNSTR)
368  nts = (*pNSTR)(10 * r, true, &actualResolution); // in 100 ns units
369  }
370  LARGE_INTEGER f;
371  QueryPerformanceFrequency(&f);
372  Period_ = 1000000.0 / f.QuadPart; // in us
373  struct _timeb local_time;
374  _ftime(&local_time);
375  auto now = Timestamp(microseconds((int64)(local_time.time * 1000 + local_time.millitm) * 1000));
376  // The QueryPerformanceCounter in Get() may not start at zero, so subtract it initially.
377  InitTime_ = Timestamp(seconds(0));
378  InitTime_ = now - Get().time_since_epoch();
379 #elif defined LINUX
380  // The steady_clock in Get() may not start at zero, so subtract it initially.
381  InitTime_ = system_clock::now() - duration_cast<microseconds>(steady_clock::now().time_since_epoch());
382 #endif
383 }
384 
385 Timestamp Time::Get() {
386 #if defined WINDOWS
387  LARGE_INTEGER counter;
388  QueryPerformanceCounter(&counter);
389  return InitTime_ + microseconds((uint64)(counter.QuadPart * Period_));
390 #elif defined LINUX
391  return InitTime_ + duration_cast<microseconds>(steady_clock::now().time_since_epoch());
392 #endif
393 }
394 
395 std::string Time::ToString_seconds(Timestamp::duration duration) {
396  // The compiler doesn't support negative times. Assume durations are positive. Take the absolute value to be sure.
397  uint64 t = abs(duration_cast<microseconds>(duration).count());
398 
399  uint64 us = t % 1000;
400  uint64 ms = t / 1000;
401  uint64 s = ms / 1000;
402  ms = ms % 1000;
403 
404  std::string result;
405  result += std::to_string(s);
406  result += "s:";
407  result += std::to_string(ms);
408  result += "ms:";
409  result += std::to_string(us);
410  result += "us";
411 
412  return result;
413 }
414 
415 std::string Time::ToString_year(Timestamp timestamp) {
416  // For now, assume all times are after the epoch. Take the absolute value to be sure.
417  uint64 t = abs(duration_cast<microseconds>(timestamp.time_since_epoch()).count());
418 
419  uint64 us = t % 1000;
420  uint64 ms = t / 1000;
421  uint64 s = ms / 1000;
422  ms = ms % 1000;
423 
424  time_t _gmt_time = s;
425  struct tm *_t = gmtime(&_gmt_time);
426 
427  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
428  std::string year = _s.substr(_s.length() - 5, 4);
429  _s.erase(_s.length() - 6, 5);
430  std::string hh_mm_ss = _s.substr(_s.length() - 9, 8);
431  hh_mm_ss += ":";
432  hh_mm_ss += std::to_string(ms);
433  hh_mm_ss += ":";
434  hh_mm_ss += std::to_string(us);
435 
436  _s.erase(_s.length() - 9, 9);
437  _s += year;
438  _s += " ";
439  _s += hh_mm_ss;
440  _s += " GMT";
441 
442  return _s;
443 }
444 
446 
447 uint8 Host::Name(char *name) {
448 #if defined WINDOWS
449  DWORD s = 255;
450  GetComputerName(name, &s);
451  return (uint8)s;
452 #elif defined LINUX
453  struct utsname utsname;
454  uname(&utsname);
455  strcpy(name, utsname.nodename);
456  return strlen(name);
457 #endif
458 }
459 
461 
462 #if defined WINDOWS
463 const uint32 Semaphore::Infinite = INFINITE;
464 #elif defined LINUX
465  /*
466  * Normally this should be SEM_VALUE_MAX but apparently the <semaphore.h> header
467  * does not define it. The documents I have read indicate that on Linux it is
468  * always equal to INT_MAX - so use that instead.
469  */
470 const uint32 Semaphore::Infinite = INT_MAX;
471 #endif
472 
473 Semaphore::Semaphore(uint32 initialCount, uint32 maxCount) {
474 #if defined WINDOWS
475  s_ = CreateSemaphore(NULL, initialCount, maxCount, NULL);
476 #elif defined LINUX
477  sem_init(&s_, 0, initialCount);
478 #endif
479 }
480 
481 Semaphore::~Semaphore() {
482 #if defined WINDOWS
483  CloseHandle(s_);
484 #elif defined LINUX
485  sem_destroy(&s_);
486 #endif
487 }
488 
489 bool Semaphore::acquire(uint32 timeout) {
490 #if defined WINDOWS
491  uint32 r = WaitForSingleObject(s_, timeout);
492  return r == WAIT_TIMEOUT;
493 #elif defined LINUX
494  struct timespec t;
495  int r;
496 
497  CalcTimeout(t, timeout);
498  r = sem_timedwait(&s_, &t);
499  return r == 0;
500 #endif
501 }
502 
503 void Semaphore::release(uint32 count) {
504 #if defined WINDOWS
505  ReleaseSemaphore(s_, count, NULL);
506 #elif defined LINUX
507  for (uint32 c = 0; c < count; c++)
508  sem_post(&s_);
509 #endif
510 }
511 
512 void Semaphore::reset() {
513 #if defined WINDOWS
514  bool r;
515  do
516  r = acquire(0);
517  while (!r);
518 #elif defined LINUX
519  bool r;
520  do
521  r = acquire(0);
522  while (!r);
523 #endif
524 }
525 
527 
528 #if defined WINDOWS
529 const uint32 Mutex::Infinite = INFINITE;
530 #elif defined LINUX
531  /*
532  * Normally this should be SEM_VALUE_MAX but apparently the <semaphore.h> header
533  * does not define it. The documents I have read indicate that on Linux it is
534  * always equal to INT_MAX - so use that instead.
535  */
536 const uint32 Mutex::Infinite = INT_MAX;
537 #endif
538 
539 Mutex::Mutex() {
540 #if defined WINDOWS
541  m_ = CreateMutex(NULL, false, NULL);
542 #elif defined LINUX
543  pthread_mutex_init(&m_, NULL);
544 #endif
545 }
546 
547 Mutex::~Mutex() {
548 #if defined WINDOWS
549  CloseHandle(m_);
550 #elif defined LINUX
551  pthread_mutex_destroy(&m_);
552 #endif
553 }
554 
555 bool Mutex::acquire(uint32 timeout) {
556 #if defined WINDOWS
557  uint32 r = WaitForSingleObject(m_, timeout);
558  return r == WAIT_TIMEOUT;
559 #elif defined LINUX
560  int64 start = Time::Get();
561  int64 uTimeout = timeout * 1000;
562 
563  while (pthread_mutex_trylock(&m_) != 0) {
564  Thread::Sleep(10);
565  if (Time::Get() - start >= uTimeout)
566  return false;
567  }
568  return true;
569 
570 #endif
571 }
572 
573 void Mutex::release() {
574 #if defined WINDOWS
575  ReleaseMutex(m_);
576 #elif defined LINUX
577  pthread_mutex_unlock(&m_);
578 #endif
579 }
580 
582 
583 CriticalSection::CriticalSection() {
584 #if defined WINDOWS
585  InitializeCriticalSection(&cs_);
586 #elif defined LINUX
587  pthread_mutex_init(&CS, NULL);
588 #endif
589 }
590 
591 CriticalSection::~CriticalSection() {
592 #if defined WINDOWS
593  DeleteCriticalSection(&cs_);
594 #elif defined LINUX
595  pthread_mutex_destroy(&CS);
596 #endif
597 }
598 
599 void CriticalSection::enter() {
600 #if defined WINDOWS
601  EnterCriticalSection(&cs_);
602 #elif defined LINUX
603  pthread_mutex_lock(&CS);
604 #endif
605 }
606 
607 void CriticalSection::leave() {
608 #if defined WINDOWS
609  LeaveCriticalSection(&cs_);
610 #elif defined LINUX
611  pthread_mutex_unlock(&CS);
612 #endif
613 }
614 
616 
617 #if defined WINDOWS
618 const uint32 Timer::Infinite = INFINITE;
619 #elif defined LINUX
620 const uint32 Timer::Infinite = INT_MAX;
621 
622 static void timer_signal_handler(int sig, siginfo_t *siginfo, void *context) {
623  SemaTex* sematex = (SemaTex*)siginfo->si_value.sival_ptr;
624  if (sematex == NULL)
625  return;
626  pthread_mutex_lock(&sematex->mutex);
627  pthread_cond_broadcast(&sematex->semaphore);
628  pthread_mutex_unlock(&sematex->mutex);
629 }
630 #endif
631 
632 Timer::Timer() {
633 #if defined WINDOWS
634  t_ = CreateWaitableTimer(NULL, false, NULL);
635  if (t_ == NULL) {
636  printf("Error creating timer\n");
637  }
638 #elif defined LINUX
639  pthread_cond_init(&sematex.semaphore, NULL);
640  pthread_mutex_init(&sematex.mutex, NULL);
641 
642  struct sigaction sa;
643  struct sigevent timer_event;
644 
645  sigemptyset(&sa.sa_mask);
646  sa.sa_flags = SA_SIGINFO; /* Real-Time signal */
647  sa.sa_sigaction = timer_signal_handler;
648  sigaction(SIGRTMIN, &sa, NULL);
649 
650  timer_event.sigev_notify = SIGEV_SIGNAL;
651  timer_event.sigev_signo = SIGRTMIN;
652  timer_event.sigev_value.sival_ptr = (void *)&sematex;
653  int ret = timer_create(CLOCK_REALTIME, &timer_event, &timer);
654  if (ret != 0) {
655  printf("Error creating timer: %d\n", ret);
656  }
657 #endif
658 }
659 
660 Timer::~Timer() {
661 #if defined WINDOWS
662  CloseHandle(t_);
663 #elif defined LINUX
664  pthread_cond_destroy(&sematex.semaphore);
665  pthread_mutex_destroy(&sematex.mutex);
666  timer_delete(timer);
667 #endif
668 }
669 
670 void Timer::start(microseconds deadline, milliseconds period) {
671 #if defined WINDOWS
672  LARGE_INTEGER _deadline; // in 100 ns intervals
673  _deadline.QuadPart = -10LL * deadline.count(); // negative means relative
674  bool r = SetWaitableTimer(t_, &_deadline, (long)period.count(), NULL, NULL, 0);
675  if (!r) {
676  printf("Error arming timer\n");
677  }
678 #elif defined LINUX
679  struct itimerspec newtv;
680  sigset_t allsigs;
681 
682  uint64 t = deadline.count();
683  uint64 p = period_ * 1000;
684  newtv.it_interval.tv_sec = p / 1000000;
685  newtv.it_interval.tv_nsec = (p % 1000000) * 1000;
686  newtv.it_value.tv_sec = t / 1000000;
687  newtv.it_value.tv_nsec = (t % 1000000) * 1000;
688 
689  pthread_mutex_lock(&sematex.mutex);
690 
691  int ret = timer_settime(timer, 0, &newtv, NULL);
692  if (ret != 0) {
693  printf("Error arming timer: %d\n", ret);
694  }
695  sigemptyset(&allsigs);
696 
697  pthread_mutex_unlock(&sematex.mutex);
698 #endif
699 }
700 
701 bool Timer::wait(uint32 timeout) {
702 #if defined WINDOWS
703  uint32 r = WaitForSingleObject(t_, timeout);
704  return r == WAIT_TIMEOUT;
705 #elif defined LINUX
706  bool res;
707  struct timespec ttimeout;
708 
709  pthread_mutex_lock(&sematex.mutex);
710  if (timeout == INT_MAX) {
711  res = (pthread_cond_wait(&sematex.semaphore, &sematex.mutex) == 0);
712  }
713  else {
714  CalcTimeout(ttimeout, timeout);
715  res = (pthread_cond_timedwait(&sematex.semaphore, &sematex.mutex, &ttimeout) == 0);
716  }
717  pthread_mutex_unlock(&sematex.mutex);
718  return res;
719 #endif
720 }
721 
723 
724 Event::Event() {
725 #if defined WINDOWS
726  e_ = CreateEvent(NULL, true, false, NULL);
727 #elif defined LINUX
728  // TODO.
729 #endif
730 }
731 
732 Event::~Event() {
733 #if defined WINDOWS
734  CloseHandle(e_);
735 #elif defined LINUX
736  // TODO.
737 #endif
738 }
739 
740 void Event::wait() {
741 #if defined WINDOWS
742  WaitForSingleObject(e_, INFINITE);
743 #elif defined LINUX
744  // TODO.
745 #endif
746 }
747 
748 void Event::fire() {
749 #if defined WINDOWS
750  SetEvent(e_);
751 #elif defined LINUX
752  // TODO.
753 #endif
754 }
755 
756 void Event::reset() {
757 #if defined WINDOWS
758  ResetEvent(e_);
759 #elif defined LINUX
760  // TODO.
761 #endif
762 }
763 
765 
766 void SignalHandler::Add(signal_handler h) {
767 #if defined WINDOWS
768  if (SetConsoleCtrlHandler(h, true) == 0) {
769 
770  int e = GetLastError();
771  std::cerr << "Error: " << e << " failed to add signal handler" << std::endl;
772  return;
773  }
774 #elif defined LINUX
775  signal(SIGABRT, SIG_IGN);
776  signal(SIGPIPE, SIG_IGN);
777  signal(SIGBUS, SIG_IGN);
778  // signal(SIGHUP, h);
779  signal(SIGTERM, h);
780  signal(SIGINT, h);
781  signal(SIGABRT, h);
782  // signal(SIGFPE, h);
783  // signal(SIGILL, h);
784  // signal(SIGSEGV, h);
785 #endif
786 }
787 
788 void SignalHandler::Remove(signal_handler h) {
789 #if defined WINDOWS
790  SetConsoleCtrlHandler(h, false);
791 #elif defined LINUX
792  signal(SIGABRT, SIG_IGN);
793  signal(SIGPIPE, SIG_IGN);
794  signal(SIGBUS, SIG_IGN);
795  // signal(SIGHUP, SIG_DFL);
796  signal(SIGTERM, SIG_DFL);
797  signal(SIGINT, SIG_DFL);
798  signal(SIGABRT, SIG_DFL);
799  // signal(SIGFPE, SIG_DFL);
800  // signal(SIGILL, SIG_DFL);
801  // signal(SIGSEGV, SIG_DFL);
802 #endif
803 }
804 
806 
807 int32 Atomic::Increment32(int32 volatile *v) {
808 #if defined WINDOWS
809  return InterlockedIncrement((long*)v);
810 #elif defined LINUX
811  __sync_add_and_fetch(v, 1);
812  return *v;
813 #endif
814 };
815 
816 int32 Atomic::Decrement32(int32 volatile *v) {
817 #if defined WINDOWS
818  return InterlockedDecrement((long*)v);
819 #elif defined LINUX
820  __sync_add_and_fetch(v, -1);
821  return *v;
822 #endif
823 };
824 
825 int32 Atomic::CompareAndSwap32(int32 volatile *target, int32 v1, int32 v2) {
826 #if defined WINDOWS
827  return _InterlockedCompareExchange((long*)target, v2, v1);
828 #elif defined LINUX
829  // note that v1 and v2 are swapped for Linux!!!
830  return __sync_val_compare_and_swap(target, v1, v2);
831 #endif
832 }
833 
834 int64 Atomic::CompareAndSwap64(int64 volatile *target, int64 v1, int64 v2) {
835 #if defined WINDOWS
836  return _InterlockedCompareExchange64(target, v2, v1);
837 #elif defined LINUX
838  // note that v1 and v2 are swapped for Linux!!!
839  return __sync_val_compare_and_swap(target, v1, v2);
840 #endif
841 }
842 
843 // word Atomic::CompareAndSwap(word volatile *target,word v1,word v2){
844 //#if defined ARCH_32
845 // return CompareAndSwap32(target,v1,v2);
846 //#elif defined ARCH_64
847 // return CompareAndSwap32((uint32*)target,v1,v2);
848 //#endif
849 // }
850 
851 int32 Atomic::Swap32(int32 volatile *target, int32 v) {
852 #if defined WINDOWS
853  return _InterlockedExchange((long*)target, v);
854 #elif defined LINUX
855  return __sync_fetch_and_sub(target, v);
856 #endif
857 }
858 
859 int64 Atomic::Swap64(int64 volatile *target, int64 v) {
860 #if defined WINDOWS
861  return CompareAndSwap64(target, v, v);
862 #elif defined LINUX
863  return __sync_fetch_and_sub(target, v);
864 #endif
865 }
866 
867 // word Atomic::Swap(word volatile *target,word v){
868 //#if defined ARCH_32
869 // return Swap32(target,v);
870 //#elif defined ARCH_64
871 // return Swap32((uint32*)target,v);
872 //#endif
873 // }
874 
876 
877 uint8 BSR(word data) {
878 #if defined WINDOWS
879 #if defined ARCH_32
880  DWORD index;
881  _BitScanReverse(&index, data);
882  return (uint8)index;
883 #elif defined ARCH_64
884  DWORD index;
885  _BitScanReverse64(&index, data);
886  return (uint8)index;
887 #endif
888 #elif defined LINUX
889 #if defined ARCH_32
890  return (uint8)(31 - __builtin_clz((uint32_t)data));
891 #elif defined ARCH_64
892  return (uint8)(63 - __builtin_clzll((uint64_t)data));
893 #endif
894 #endif
895 }
896 
898 
899 FastSemaphore::FastSemaphore(uint32 initialCount, uint32 maxCount) : Semaphore(initialCount > 0 ? 1 : 0, 1), count_(initialCount), maxCount_(maxCount) {
900 }
901 
902 FastSemaphore::~FastSemaphore() {
903 }
904 
905 void FastSemaphore::acquire() {
906 
907  int32 c;
908  while ((c = Atomic::Decrement32(&count_)) >= maxCount_); // release calls can bring count over maxCount_: acquire has to exhaust these extras
909  if (c < 0)
910  Semaphore::acquire();
911 }
912 
913 void FastSemaphore::release() {
914 
915  int32 c = Atomic::Increment32(&count_);
916  if (c <= 0)
917  Semaphore::release();
918 }
919 
921 /*
922  FastMutex::FastMutex(uint32 initialCount):Semaphore(initialCount,1),count_(initialCount){
923  }
924 
925  FastMutex::~FastMutex(){
926  }
927 
928  void FastMutex::acquire(){
929 
930  int32 former=Atomic::Swap32(&count_,0);
931  if(former==0)
932  Semaphore::acquire();
933  }
934 
935  void FastMutex::release(){
936 
937  int32 former=Atomic::Swap32(&count_,1);
938  if(former==0)
939  Semaphore::release();
940  }
941  */
943 
944 bool Error::PrintLastOSErrorMessage(const char* title) {
945  int32 err = Error::GetLastOSErrorNumber();
946  char buf[1024];
947  if (!Error::GetOSErrorMessage(buf, 1024, err))
948  printf("%s: [%d] (could not get error message)\n", title, err);
949  else
950  printf("%s: [%d] %s\n", title, err, buf);
951  return true;
952 }
953 
954 int32 Error::GetLastOSErrorNumber() {
955 #ifdef WINDOWS
956  int32 err = WSAGetLastError();
957  WSASetLastError(0);
958  return err;
959 #else
960  return (int32)errno;
961 #endif
962 }
963 
964 bool Error::GetOSErrorMessage(char* buffer, uint32 buflen, int32 err) {
965  if (buffer == NULL)
966  return false;
967  if (buflen < 512) {
968  strcpy(buffer, "String buffer not large enough");
969  return false;
970  }
971  if (err < 0)
972  err = Error::GetLastOSErrorNumber();
973 
974 #ifdef WINDOWS
975  if (err == WSANOTINITIALISED) {
976  strcpy(buffer, "Cannot initialize WinSock!");
977  }
978  else if (err == WSAENETDOWN) {
979  strcpy(buffer, "The network subsystem or the associated service provider has failed");
980  }
981  else if (err == WSAEAFNOSUPPORT) {
982  strcpy(buffer, "The specified address family is not supported");
983  }
984  else if (err == WSAEINPROGRESS) {
985  strcpy(buffer, "A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function");
986  }
987  else if (err == WSAEMFILE) {
988  strcpy(buffer, "No more socket descriptors are available");
989  }
990  else if (err == WSAENOBUFS) {
991  strcpy(buffer, "No buffer space is available. The socket cannot be created");
992  }
993  else if (err == WSAEPROTONOSUPPORT) {
994  strcpy(buffer, "The specified protocol is not supported");
995  }
996  else if (err == WSAEPROTOTYPE) {
997  strcpy(buffer, "The specified protocol is the wrong type for this socket");
998  }
999  else if (err == WSAESOCKTNOSUPPORT) {
1000  strcpy(buffer, "The specified socket type is not supported in this address family");
1001  }
1002  else if (err == WSAEADDRINUSE) {
1003  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");
1004  }
1005  else if (err == WSAEINVAL) {
1006  strcpy(buffer, "The socket has not been bound with bind");
1007  }
1008  else if (err == WSAEISCONN) {
1009  strcpy(buffer, "The socket is already connected");
1010  }
1011  else if (err == WSAENOTSOCK) {
1012  strcpy(buffer, "The descriptor is not a socket");
1013  }
1014  else if (err == WSAEOPNOTSUPP) {
1015  strcpy(buffer, "The referenced socket is not of a type that supports the listen operation");
1016  }
1017  else if (err == WSAEADDRNOTAVAIL) {
1018  strcpy(buffer, "The specified address is not a valid address for this machine");
1019  }
1020  else if (err == WSAEFAULT) {
1021  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");
1022  }
1023  else if (err == WSAEMFILE) {
1024  strcpy(buffer, "The queue is nonempty upon entry to accept and there are no descriptors available");
1025  }
1026  else if (err == SOCKETWOULDBLOCK) {
1027  strcpy(buffer, "The socket is marked as nonblocking and no connections are present to be accepted");
1028  }
1029  else if (err == WSAETIMEDOUT) {
1030  strcpy(buffer, "Attempt to connect timed out without establishing a connection");
1031  }
1032  else if (err == WSAENETUNREACH) {
1033  strcpy(buffer, "The network cannot be reached from this host at this time");
1034  }
1035  else if (err == WSAEISCONN) {
1036  strcpy(buffer, "The socket is already connected (connection-oriented sockets only)");
1037  }
1038  else if (err == WSAECONNREFUSED) {
1039  strcpy(buffer, "The attempt to connect was forcefully rejected");
1040  }
1041  else if (err == WSAEAFNOSUPPORT) {
1042  strcpy(buffer, "Addresses in the specified family cannot be used with this socket");
1043  }
1044  else if (err == WSAEADDRNOTAVAIL) {
1045  strcpy(buffer, "The remote address is not a valid address (such as ADDR_ANY)");
1046  }
1047  else if (err == WSAEALREADY) {
1048  strcpy(buffer, "A nonblocking connect call is in progress on the specified socket");
1049  }
1050  else if (err == WSAECONNRESET) {
1051  strcpy(buffer, "Connection was reset");
1052  }
1053  else if (err == WSAECONNABORTED) {
1054  strcpy(buffer, "Software caused connection abort");
1055  }
1056  else {
1057  strcpy(buffer, "Socket error with no description");
1058  }
1059 
1060 #else
1061  strcpy(buffer, strerror(err));
1062 #endif
1063 
1064  return true;
1065 }
1066 
1068 
1069 bool WaitForSocketReadability(socket s, int32 timeout) {
1070 
1071  int maxfd = 0;
1072 
1073  struct timeval tv;
1074  tv.tv_sec = 0;
1075  tv.tv_usec = 0;
1076 
1077  fd_set rdds;
1078  // create a list of sockets to check for activity
1079  FD_ZERO(&rdds);
1080  // specify mySocket
1081  FD_SET(s, &rdds);
1082 
1083 #ifdef WINDOWS
1084 #else
1085  maxfd = s + 1;
1086 #endif
1087 
1088  if (timeout > 0) {
1089  ldiv_t d = ldiv(timeout * 1000, 1000000);
1090  tv.tv_sec = d.quot;
1091  tv.tv_usec = d.rem;
1092  }
1093 
1094  // Check for readability
1095  int ret = select(maxfd, &rdds, NULL, NULL, &tv);
1096  return(ret > 0);
1097 }
1098 
1099 bool WaitForSocketWriteability(socket s, int32 timeout) {
1100 
1101  int maxfd = 0;
1102 
1103  struct timeval tv;
1104  tv.tv_sec = 0;
1105  tv.tv_usec = 0;
1106 
1107  fd_set wds;
1108  // create a list of sockets to check for activity
1109  FD_ZERO(&wds);
1110  // specify mySocket
1111  FD_SET(s, &wds);
1112 
1113 #ifdef WINDOWS
1114 #else
1115  maxfd = s + 1;
1116 #endif
1117 
1118  if (timeout > 0) {
1119  ldiv_t d = ldiv(timeout * 1000, 1000000);
1120  tv.tv_sec = d.quot;
1121  tv.tv_usec = d.rem;
1122  }
1123 
1124  // Check for readability
1125  return(select(maxfd, NULL, &wds, NULL, &tv) > 0);
1126 }
1127 
1129 
1130 int32 String::StartsWith(const std::string &s, const std::string &str) {
1131  std::string::size_type pos = s.find_first_of(str);
1132  if (pos == 0)
1133  return 0;
1134  else
1135  return -1;
1136 }
1137 
1138 int32 String::EndsWith(const std::string &s, const std::string &str) {
1139  std::string::size_type pos = s.find_last_of(str);
1140  if (pos == s.size() - str.size())
1141  return pos;
1142  else
1143  return -1;
1144 }
1145 
1146 void String::MakeUpper(std::string &str)
1147 {
1148  std::transform(str.begin(), str.end(), str.begin(), toupper);
1149 }
1150 
1151 void String::MakeLower(std::string &str)
1152 {
1153  std::transform(str.begin(), str.end(), str.begin(), tolower);
1154 }
1155 
1156 void String::Trim(std::string& str, const char* chars2remove)
1157 {
1158  TrimLeft(str, chars2remove);
1159  TrimRight(str, chars2remove);
1160 }
1161 
1162 void String::TrimLeft(std::string& str, const char* chars2remove)
1163 {
1164  if (!str.empty())
1165  {
1166  std::string::size_type pos = str.find_first_not_of(chars2remove);
1167 
1168  if (pos != std::string::npos)
1169  str.erase(0, pos);
1170  else
1171  str.erase(str.begin(), str.end()); // make empty
1172  }
1173 }
1174 
1175 void String::TrimRight(std::string& str, const char* chars2remove)
1176 {
1177  if (!str.empty())
1178  {
1179  std::string::size_type pos = str.find_last_not_of(chars2remove);
1180 
1181  if (pos != std::string::npos)
1182  str.erase(pos + 1);
1183  else
1184  str.erase(str.begin(), str.end()); // make empty
1185  }
1186 }
1187 
1188 
1189 void String::ReplaceLeading(std::string& str, const char* chars2replace, char c)
1190 {
1191  if (!str.empty())
1192  {
1193  std::string::size_type pos = str.find_first_not_of(chars2replace);
1194 
1195  if (pos != std::string::npos)
1196  str.replace(0, pos, pos, c);
1197  else
1198  {
1199  int n = str.size();
1200  str.replace(str.begin(), str.end() - 1, n - 1, c);
1201  }
1202  }
1203 }
1204 
1206 
1207 int32 Random::r250_index_;
1208 int32 Random::r521_index_;
1209 uint32 Random::r250_buffer_[R250_LEN];
1210 uint32 Random::r521_buffer_[R521_LEN];
1211 
1212 void Random::Init() {
1213 
1214  int32 i = R521_LEN;
1215  uint32 mask1 = 1;
1216  uint32 mask2 = 0xFFFFFFFF;
1217 
1218  while (i-- > R250_LEN)
1219  r521_buffer_[i] = rand();
1220  while (i-- > 31) {
1221 
1222  r250_buffer_[i] = rand();
1223  r521_buffer_[i] = rand();
1224  }
1225 
1226  // Establish linear independence of the bit columns
1227  // by setting the diagonal bits and clearing all bits above
1228  while (i-- > 0) {
1229 
1230  r250_buffer_[i] = (rand() | mask1) & mask2;
1231  r521_buffer_[i] = (rand() | mask1) & mask2;
1232  mask2 ^= mask1;
1233  mask1 >>= 1;
1234  }
1235  r250_buffer_[0] = mask1;
1236  r521_buffer_[0] = mask2;
1237  r250_index_ = 0;
1238  r521_index_ = 0;
1239 }
1240 
1241 float32 Random::operator ()(uint32 range) {
1242  /*
1243  I prescale the indices by sizeof(unsigned long) to eliminate
1244  four shlwi instructions in the compiled code. This minor optimization
1245  increased perf by about 12%.
1246 
1247  I also carefully arrange index increments and comparisons to minimize
1248  instructions. gcc 3.3 seems a bit weak on instruction reordering. The
1249  j1/j2 branches are mispredicted, but nevertheless these optimizations
1250  increased perf by another 10%.
1251  */
1252 
1253  int32 i1 = r250_index_;
1254  int32 i2 = r521_index_;
1255  uint8 *b1 = (uint8 *)r250_buffer_;
1256  uint8 *b2 = (uint8 *)r521_buffer_;
1257  uint32 *tmp1, *tmp2;
1258  uint32 r, s;
1259  int32 j1, j2;
1260 
1261  j1 = i1 - R250_IB;
1262  if (j1 < 0)
1263  j1 = i1 + R250_IA;
1264  j2 = i2 - R521_IB;
1265  if (j2 < 0)
1266  j2 = i2 + R521_IA;
1267 
1268  tmp1 = (uint32 *)(b1 + i1);
1269  r = (*(uint32 *)(b1 + j1)) ^ (*tmp1);
1270  *tmp1 = r;
1271  tmp2 = (uint32 *)(b2 + i2);
1272  s = (*(uint32 *)(b2 + j2)) ^ (*tmp2);
1273  *tmp2 = s;
1274 
1275  i1 = (i1 != sizeof(uint32)*(R250_LEN - 1)) ? (i1 + sizeof(uint32)) : 0;
1276  r250_index_ = i1;
1277  i2 = (i2 != sizeof(uint32)*(R521_LEN - 1)) ? (i2 + sizeof(uint32)) : 0;
1278  r521_index_ = i2;
1279 
1280  float32 _r = r ^ s;
1281  //return range*(_r/((float32)ULONG_MAX));
1282  return _r;
1283 }
1284 }