1 /*************************************************************************************************
2  * Threading devices
3  *                                                      Copyright (C) 2009-2012 Mikio Hirabayashi
4  * This file is part of Kyoto Cabinet.
5  * This program is free software: you can redistribute it and/or modify it under the terms of
6  * the GNU General Public License as published by the Free Software Foundation, either version
7  * 3 of the License, or any later version.
8  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along with this program.
12  * If not, see <http://www.gnu.org/licenses/>.
13  *************************************************************************************************/
14 
15 
16 #include "kcthread.h"
17 #include "myconf.h"
18 
19 namespace kyotocabinet {                 // common namespace
20 
21 
22 /**
23  * Constants for implementation.
24  */
25 namespace {
26 const uint32_t LOCKBUSYLOOP = 8192;      ///< threshold of busy loop and sleep for locking
27 const size_t LOCKSEMNUM = 256;           ///< number of semaphores for locking
28 }
29 
30 
31 /**
32  * Thread internal.
33  */
34 struct ThreadCore {
35 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
36   ::HANDLE th;                           ///< handle
37 #else
38   ::pthread_t th;                        ///< identifier
39   bool alive;                            ///< alive flag
40 #endif
41 };
42 
43 
44 /**
45  * CondVar internal.
46  */
47 struct CondVarCore {
48 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
49   ::CRITICAL_SECTION mutex;              ///< mutex
50   uint32_t wait;                         ///< wait count
51   uint32_t wake;                         ///< wake count
52   ::HANDLE sev;                          ///< signal event handle
53   ::HANDLE fev;                          ///< finish event handle
54 #else
55   ::pthread_cond_t cond;                 ///< condition
56 #endif
57 };
58 
59 
60 /**
61  * Call the running thread.
62  * @param arg the thread.
63  * @return always NULL.
64  */
65 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
66 static ::DWORD threadrun(::LPVOID arg);
67 #else
68 static void* threadrun(void* arg);
69 #endif
70 
71 
72 /**
73  * Default constructor.
74  */
Thread()75 Thread::Thread() : opq_(NULL) {
76 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
77   _assert_(true);
78   ThreadCore* core = new ThreadCore;
79   core->th = NULL;
80   opq_ = (void*)core;
81 #else
82   _assert_(true);
83   ThreadCore* core = new ThreadCore;
84   core->alive = false;
85   opq_ = (void*)core;
86 #endif
87 }
88 
89 
90 /**
91  * Destructor.
92  */
~Thread()93 Thread::~Thread() {
94 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
95   _assert_(true);
96   ThreadCore* core = (ThreadCore*)opq_;
97   if (core->th) join();
98   delete core;
99 #else
100   _assert_(true);
101   ThreadCore* core = (ThreadCore*)opq_;
102   if (core->alive) join();
103   delete core;
104 #endif
105 }
106 
107 
108 /**
109  * Start the thread.
110  */
start()111 void Thread::start() {
112 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
113   _assert_(true);
114   ThreadCore* core = (ThreadCore*)opq_;
115   if (core->th) throw std::invalid_argument("already started");
116   ::DWORD id;
117   core->th = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadrun, this, 0, &id);
118   if (!core->th) throw std::runtime_error("CreateThread");
119 #else
120   _assert_(true);
121   ThreadCore* core = (ThreadCore*)opq_;
122   if (core->alive) throw std::invalid_argument("already started");
123   if (::pthread_create(&core->th, NULL, threadrun, this) != 0)
124     throw std::runtime_error("pthread_create");
125   core->alive = true;
126 #endif
127 }
128 
129 
130 /**
131  * Wait for the thread to finish.
132  */
join()133 void Thread::join() {
134 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
135   _assert_(true);
136   ThreadCore* core = (ThreadCore*)opq_;
137   if (!core->th) throw std::invalid_argument("not alive");
138   if (::WaitForSingleObject(core->th, INFINITE) == WAIT_FAILED)
139     throw std::runtime_error("WaitForSingleObject");
140   ::CloseHandle(core->th);
141   core->th = NULL;
142 #else
143   _assert_(true);
144   ThreadCore* core = (ThreadCore*)opq_;
145   if (!core->alive) throw std::invalid_argument("not alive");
146   core->alive = false;
147   if (::pthread_join(core->th, NULL) != 0) throw std::runtime_error("pthread_join");
148 #endif
149 }
150 
151 
152 /**
153  * Put the thread in the detached state.
154  */
detach()155 void Thread::detach() {
156 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
157   _assert_(true);
158 #else
159   _assert_(true);
160   ThreadCore* core = (ThreadCore*)opq_;
161   if (!core->alive) throw std::invalid_argument("not alive");
162   core->alive = false;
163   if (::pthread_detach(core->th) != 0) throw std::runtime_error("pthread_detach");
164 #endif
165 }
166 
167 
168 /**
169  * Terminate the running thread.
170  */
exit()171 void Thread::exit() {
172 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
173   _assert_(true);
174   ::ExitThread(0);
175 #else
176   _assert_(true);
177   ::pthread_exit(NULL);
178 #endif
179 }
180 
181 
182 /**
183  * Yield the processor from the current thread.
184  */
yield()185 void Thread::yield() {
186 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
187   _assert_(true);
188   ::Sleep(0);
189 #else
190   _assert_(true);
191   ::sched_yield();
192 #endif
193 }
194 
195 
196 /**
197  * Chill the processor by suspending execution for a quick moment.
198  */
chill()199 void Thread::chill() {
200 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
201   _assert_(true);
202   ::Sleep(21);
203 #else
204   _assert_(true);
205   struct ::timespec req;
206   req.tv_sec = 0;
207   req.tv_nsec = 21 * 1000 * 1000;
208   ::nanosleep(&req, NULL);
209 #endif
210 }
211 
212 
213 
214 /**
215  * Suspend execution of the current thread.
216  */
sleep(double sec)217 bool Thread::sleep(double sec) {
218 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
219   _assert_(sec >= 0.0);
220   if (sec <= 0.0) {
221     yield();
222     return true;
223   }
224   if (sec > INT32MAX) sec = INT32MAX;
225   ::Sleep(sec * 1000);
226   return true;
227 #else
228   _assert_(sec >= 0.0);
229   if (sec <= 0.0) {
230     yield();
231     return true;
232   }
233   if (sec > INT32MAX) sec = INT32MAX;
234   double integ, fract;
235   fract = std::modf(sec, &integ);
236   struct ::timespec req, rem;
237   req.tv_sec = (time_t)integ;
238   req.tv_nsec = (long)(fract * 999999000);
239   while (::nanosleep(&req, &rem) != 0) {
240     if (errno != EINTR) return false;
241     req = rem;
242   }
243   return true;
244 #endif
245 }
246 
247 
248 /**
249  * Get the hash value of the current thread.
250  */
hash()251 int64_t Thread::hash() {
252 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
253   _assert_(true);
254   return ::GetCurrentThreadId();
255 #else
256   _assert_(true);
257   pthread_t tid = pthread_self();
258   int64_t num;
259   if (sizeof(tid) == sizeof(num)) {
260     std::memcpy(&num, &tid, sizeof(num));
261   } else if (sizeof(tid) == sizeof(int32_t)) {
262     uint32_t inum;
263     std::memcpy(&inum, &tid, sizeof(inum));
264     num = inum;
265   } else {
266     num = hashmurmur(&tid, sizeof(tid));
267   }
268   return num & INT64MAX;
269 #endif
270 }
271 
272 
273 /**
274  * Call the running thread.
275  */
276 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
threadrun(::LPVOID arg)277 static ::DWORD threadrun(::LPVOID arg) {
278   _assert_(true);
279   Thread* thread = (Thread*)arg;
280   thread->run();
281   return NULL;
282 }
283 #else
threadrun(void * arg)284 static void* threadrun(void* arg) {
285   _assert_(true);
286   Thread* thread = (Thread*)arg;
287   thread->run();
288   return NULL;
289 }
290 #endif
291 
292 
293 /**
294  * Default constructor.
295  */
Mutex()296 Mutex::Mutex() : opq_(NULL) {
297 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
298   _assert_(true);
299   ::CRITICAL_SECTION* mutex = new ::CRITICAL_SECTION;
300   ::InitializeCriticalSection(mutex);
301   opq_ = (void*)mutex;
302 #else
303   _assert_(true);
304   ::pthread_mutex_t* mutex = new ::pthread_mutex_t;
305   if (::pthread_mutex_init(mutex, NULL) != 0) throw std::runtime_error("pthread_mutex_init");
306   opq_ = (void*)mutex;
307 #endif
308 }
309 
310 
311 /**
312  * Constructor with the specifications.
313  */
Mutex(Type type)314 Mutex::Mutex(Type type) {
315 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
316   _assert_(true);
317   ::CRITICAL_SECTION* mutex = new ::CRITICAL_SECTION;
318   ::InitializeCriticalSection(mutex);
319   opq_ = (void*)mutex;
320 #else
321   _assert_(true);
322   ::pthread_mutexattr_t attr;
323   if (::pthread_mutexattr_init(&attr) != 0) throw std::runtime_error("pthread_mutexattr_init");
324   switch (type) {
325     case FAST: {
326       break;
327     }
328     case ERRORCHECK: {
329       if (::pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
330         throw std::runtime_error("pthread_mutexattr_settype");
331       break;
332     }
333     case RECURSIVE: {
334       if (::pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0)
335         throw std::runtime_error("pthread_mutexattr_settype");
336       break;
337     }
338   }
339   ::pthread_mutex_t* mutex = new ::pthread_mutex_t;
340   if (::pthread_mutex_init(mutex, &attr) != 0) throw std::runtime_error("pthread_mutex_init");
341   ::pthread_mutexattr_destroy(&attr);
342   opq_ = (void*)mutex;
343 #endif
344 }
345 
346 
347 /**
348  * Destructor.
349  */
~Mutex()350 Mutex::~Mutex() {
351 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
352   _assert_(true);
353   ::CRITICAL_SECTION* mutex = (::CRITICAL_SECTION*)opq_;
354   ::DeleteCriticalSection(mutex);
355   delete mutex;
356 #else
357   _assert_(true);
358   ::pthread_mutex_t* mutex = (::pthread_mutex_t*)opq_;
359   ::pthread_mutex_destroy(mutex);
360   delete mutex;
361 #endif
362 }
363 
364 
365 /**
366  * Get the lock.
367  */
lock()368 void Mutex::lock() {
369 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
370   _assert_(true);
371   ::CRITICAL_SECTION* mutex = (::CRITICAL_SECTION*)opq_;
372   ::EnterCriticalSection(mutex);
373 #else
374   _assert_(true);
375   ::pthread_mutex_t* mutex = (::pthread_mutex_t*)opq_;
376   if (::pthread_mutex_lock(mutex) != 0) throw std::runtime_error("pthread_mutex_lock");
377 #endif
378 }
379 
380 
381 /**
382  * Try to get the lock.
383  */
lock_try()384 bool Mutex::lock_try() {
385 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
386   _assert_(true);
387   ::CRITICAL_SECTION* mutex = (::CRITICAL_SECTION*)opq_;
388   if (!::TryEnterCriticalSection(mutex)) return false;
389   return true;
390 #else
391   _assert_(true);
392   ::pthread_mutex_t* mutex = (::pthread_mutex_t*)opq_;
393   int32_t ecode = ::pthread_mutex_trylock(mutex);
394   if (ecode == 0) return true;
395   if (ecode != EBUSY) throw std::runtime_error("pthread_mutex_trylock");
396   return false;
397 #endif
398 }
399 
400 
401 /**
402  * Try to get the lock.
403  */
lock_try(double sec)404 bool Mutex::lock_try(double sec) {
405 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || defined(_SYS_CYGWIN_) || defined(_SYS_MACOSX_)
406   _assert_(sec >= 0.0);
407   if (lock_try()) return true;
408   double end = time() + sec;
409   Thread::yield();
410   uint32_t wcnt = 0;
411   while (!lock_try()) {
412     if (time() > end) return false;
413     if (wcnt >= LOCKBUSYLOOP) {
414       Thread::chill();
415     } else {
416       Thread::yield();
417       wcnt++;
418     }
419   }
420   return true;
421 #else
422   _assert_(sec >= 0.0);
423   ::pthread_mutex_t* mutex = (::pthread_mutex_t*)opq_;
424   struct ::timeval tv;
425   struct ::timespec ts;
426   if (::gettimeofday(&tv, NULL) == 0) {
427     double integ;
428     double fract = std::modf(sec, &integ);
429     ts.tv_sec = tv.tv_sec + (time_t)integ;
430     ts.tv_nsec = (long)(tv.tv_usec * 1000.0 + fract * 999999000);
431     if (ts.tv_nsec >= 1000000000) {
432       ts.tv_nsec -= 1000000000;
433       ts.tv_sec++;
434     }
435   } else {
436     ts.tv_sec = std::time(NULL) + 1;
437     ts.tv_nsec = 0;
438   }
439   int32_t ecode = ::pthread_mutex_timedlock(mutex, &ts);
440   if (ecode == 0) return true;
441   if (ecode != ETIMEDOUT) throw std::runtime_error("pthread_mutex_timedlock");
442   return false;
443 #endif
444 }
445 
446 
447 /**
448  * Release the lock.
449  */
unlock()450 void Mutex::unlock() {
451 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
452   _assert_(true);
453   ::CRITICAL_SECTION* mutex = (::CRITICAL_SECTION*)opq_;
454   ::LeaveCriticalSection(mutex);
455 #else
456   _assert_(true);
457   ::pthread_mutex_t* mutex = (::pthread_mutex_t*)opq_;
458   if (::pthread_mutex_unlock(mutex) != 0) throw std::runtime_error("pthread_mutex_unlock");
459 #endif
460 }
461 
462 
463 /**
464  * SlottedMutex internal.
465  */
466 struct SlottedMutexCore {
467 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
468   ::CRITICAL_SECTION* mutexes;           ///< primitives
469   size_t slotnum;                        ///< number of slots
470 #else
471   ::pthread_mutex_t* mutexes;            ///< primitives
472   size_t slotnum;                        ///< number of slots
473 #endif
474 };
475 
476 
477 /**
478  * Constructor.
479  */
SlottedMutex(size_t slotnum)480 SlottedMutex::SlottedMutex(size_t slotnum) : opq_(NULL) {
481 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
482   _assert_(true);
483   SlottedMutexCore* core = new SlottedMutexCore;
484   ::CRITICAL_SECTION* mutexes = new ::CRITICAL_SECTION[slotnum];
485   for (size_t i = 0; i < slotnum; i++) {
486     ::InitializeCriticalSection(mutexes + i);
487   }
488   core->mutexes = mutexes;
489   core->slotnum = slotnum;
490   opq_ = (void*)core;
491 #else
492   _assert_(true);
493   SlottedMutexCore* core = new SlottedMutexCore;
494   ::pthread_mutex_t* mutexes = new ::pthread_mutex_t[slotnum];
495   for (size_t i = 0; i < slotnum; i++) {
496     if (::pthread_mutex_init(mutexes + i, NULL) != 0)
497       throw std::runtime_error("pthread_mutex_init");
498   }
499   core->mutexes = mutexes;
500   core->slotnum = slotnum;
501   opq_ = (void*)core;
502 #endif
503 }
504 
505 
506 /**
507  * Destructor.
508  */
~SlottedMutex()509 SlottedMutex::~SlottedMutex() {
510 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
511   _assert_(true);
512   SlottedMutexCore* core = (SlottedMutexCore*)opq_;
513   ::CRITICAL_SECTION* mutexes = core->mutexes;
514   size_t slotnum = core->slotnum;
515   for (size_t i = 0; i < slotnum; i++) {
516     ::DeleteCriticalSection(mutexes + i);
517   }
518   delete[] mutexes;
519   delete core;
520 #else
521   _assert_(true);
522   SlottedMutexCore* core = (SlottedMutexCore*)opq_;
523   ::pthread_mutex_t* mutexes = core->mutexes;
524   size_t slotnum = core->slotnum;
525   for (size_t i = 0; i < slotnum; i++) {
526     ::pthread_mutex_destroy(mutexes + i);
527   }
528   delete[] mutexes;
529   delete core;
530 #endif
531 }
532 
533 
534 /**
535  * Get the lock of a slot.
536  */
lock(size_t idx)537 void SlottedMutex::lock(size_t idx) {
538 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
539   _assert_(true);
540   SlottedMutexCore* core = (SlottedMutexCore*)opq_;
541   ::EnterCriticalSection(core->mutexes + idx);
542 #else
543   _assert_(true);
544   SlottedMutexCore* core = (SlottedMutexCore*)opq_;
545   if (::pthread_mutex_lock(core->mutexes + idx) != 0)
546     throw std::runtime_error("pthread_mutex_lock");
547 #endif
548 }
549 
550 
551 /**
552  * Release the lock of a slot.
553  */
unlock(size_t idx)554 void SlottedMutex::unlock(size_t idx) {
555 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
556   _assert_(true);
557   SlottedMutexCore* core = (SlottedMutexCore*)opq_;
558   ::LeaveCriticalSection(core->mutexes + idx);
559 #else
560   _assert_(true);
561   SlottedMutexCore* core = (SlottedMutexCore*)opq_;
562   if (::pthread_mutex_unlock(core->mutexes + idx) != 0)
563     throw std::runtime_error("pthread_mutex_unlock");
564 #endif
565 }
566 
567 
568 /**
569  * Get the locks of all slots.
570  */
lock_all()571 void SlottedMutex::lock_all() {
572 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
573   _assert_(true);
574   SlottedMutexCore* core = (SlottedMutexCore*)opq_;
575   ::CRITICAL_SECTION* mutexes = core->mutexes;
576   size_t slotnum = core->slotnum;
577   for (size_t i = 0; i < slotnum; i++) {
578     ::EnterCriticalSection(core->mutexes + i);
579   }
580 #else
581   _assert_(true);
582   SlottedMutexCore* core = (SlottedMutexCore*)opq_;
583   ::pthread_mutex_t* mutexes = core->mutexes;
584   size_t slotnum = core->slotnum;
585   for (size_t i = 0; i < slotnum; i++) {
586     if (::pthread_mutex_lock(mutexes + i) != 0)
587       throw std::runtime_error("pthread_mutex_lock");
588   }
589 #endif
590 }
591 
592 
593 /**
594  * Release the locks of all slots.
595  */
unlock_all()596 void SlottedMutex::unlock_all() {
597 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
598   _assert_(true);
599   SlottedMutexCore* core = (SlottedMutexCore*)opq_;
600   ::CRITICAL_SECTION* mutexes = core->mutexes;
601   size_t slotnum = core->slotnum;
602   for (size_t i = 0; i < slotnum; i++) {
603     ::LeaveCriticalSection(mutexes + i);
604   }
605 #else
606   _assert_(true);
607   SlottedMutexCore* core = (SlottedMutexCore*)opq_;
608   ::pthread_mutex_t* mutexes = core->mutexes;
609   size_t slotnum = core->slotnum;
610   for (size_t i = 0; i < slotnum; i++) {
611     if (::pthread_mutex_unlock(mutexes + i) != 0)
612       throw std::runtime_error("pthread_mutex_unlock");
613   }
614 #endif
615 }
616 
617 
618 /**
619  * Default constructor.
620  */
SpinLock()621 SpinLock::SpinLock() : opq_(NULL) {
622 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
623   _assert_(true);
624 #elif _KC_GCCATOMIC
625   _assert_(true);
626 #else
627   _assert_(true);
628   ::pthread_spinlock_t* spin = new ::pthread_spinlock_t;
629   if (::pthread_spin_init(spin, PTHREAD_PROCESS_PRIVATE) != 0)
630     throw std::runtime_error("pthread_spin_init");
631   opq_ = (void*)spin;
632 #endif
633 }
634 
635 
636 /**
637  * Destructor.
638  */
~SpinLock()639 SpinLock::~SpinLock() {
640 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
641   _assert_(true);
642 #elif _KC_GCCATOMIC
643   _assert_(true);
644 #else
645   _assert_(true);
646   ::pthread_spinlock_t* spin = (::pthread_spinlock_t*)opq_;
647   ::pthread_spin_destroy(spin);
648   delete spin;
649 #endif
650 }
651 
652 
653 /**
654  * Get the lock.
655  */
lock()656 void SpinLock::lock() {
657 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
658   _assert_(true);
659   uint32_t wcnt = 0;
660   while (::InterlockedCompareExchange((LONG*)&opq_, 1, 0) != 0) {
661     if (wcnt >= LOCKBUSYLOOP) {
662       Thread::chill();
663     } else {
664       Thread::yield();
665       wcnt++;
666     }
667   }
668 #elif _KC_GCCATOMIC
669   _assert_(true);
670   uint32_t wcnt = 0;
671   while (!__sync_bool_compare_and_swap(&opq_, 0, 1)) {
672     if (wcnt >= LOCKBUSYLOOP) {
673       Thread::chill();
674     } else {
675       Thread::yield();
676       wcnt++;
677     }
678   }
679 #else
680   _assert_(true);
681   ::pthread_spinlock_t* spin = (::pthread_spinlock_t*)opq_;
682   if (::pthread_spin_lock(spin) != 0) throw std::runtime_error("pthread_spin_lock");
683 #endif
684 }
685 
686 
687 /**
688  * Try to get the lock.
689  */
lock_try()690 bool SpinLock::lock_try() {
691 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
692   _assert_(true);
693   return ::InterlockedCompareExchange((LONG*)&opq_, 1, 0) == 0;
694 #elif _KC_GCCATOMIC
695   _assert_(true);
696   return __sync_bool_compare_and_swap(&opq_, 0, 1);
697 #else
698   _assert_(true);
699   ::pthread_spinlock_t* spin = (::pthread_spinlock_t*)opq_;
700   int32_t ecode = ::pthread_spin_trylock(spin);
701   if (ecode == 0) return true;
702   if (ecode != EBUSY) throw std::runtime_error("pthread_spin_trylock");
703   return false;
704 #endif
705 }
706 
707 
708 /**
709  * Release the lock.
710  */
unlock()711 void SpinLock::unlock() {
712 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
713   _assert_(true);
714   ::InterlockedExchange((LONG*)&opq_, 0);
715 #elif _KC_GCCATOMIC
716   _assert_(true);
717   __sync_lock_release(&opq_);
718 #else
719   _assert_(true);
720   ::pthread_spinlock_t* spin = (::pthread_spinlock_t*)opq_;
721   if (::pthread_spin_unlock(spin) != 0) throw std::runtime_error("pthread_spin_unlock");
722 #endif
723 }
724 
725 
726 /**
727  * SlottedSpinLock internal.
728  */
729 struct SlottedSpinLockCore {
730 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || _KC_GCCATOMIC
731   uint32_t* locks;                       ///< primitives
732   size_t slotnum;                        ///< number of slots
733 #else
734   ::pthread_spinlock_t* spins;           ///< primitives
735   size_t slotnum;                        ///< number of slots
736 #endif
737 };
738 
739 
740 /**
741  * Constructor.
742  */
SlottedSpinLock(size_t slotnum)743 SlottedSpinLock::SlottedSpinLock(size_t slotnum) : opq_(NULL) {
744 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || _KC_GCCATOMIC
745   _assert_(true);
746   SlottedSpinLockCore* core = new SlottedSpinLockCore;
747   uint32_t* locks = new uint32_t[slotnum];
748   for (size_t i = 0; i < slotnum; i++) {
749     locks[i] = 0;
750   }
751   core->locks = locks;
752   core->slotnum = slotnum;
753   opq_ = (void*)core;
754 #else
755   _assert_(true);
756   SlottedSpinLockCore* core = new SlottedSpinLockCore;
757   ::pthread_spinlock_t* spins = new ::pthread_spinlock_t[slotnum];
758   for (size_t i = 0; i < slotnum; i++) {
759     if (::pthread_spin_init(spins + i, PTHREAD_PROCESS_PRIVATE) != 0)
760       throw std::runtime_error("pthread_spin_init");
761   }
762   core->spins = spins;
763   core->slotnum = slotnum;
764   opq_ = (void*)core;
765 #endif
766 }
767 
768 
769 /**
770  * Destructor.
771  */
~SlottedSpinLock()772 SlottedSpinLock::~SlottedSpinLock() {
773 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || _KC_GCCATOMIC
774   _assert_(true);
775   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
776   delete[] core->locks;
777   delete core;
778 #else
779   _assert_(true);
780   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
781   ::pthread_spinlock_t* spins = core->spins;
782   size_t slotnum = core->slotnum;
783   for (size_t i = 0; i < slotnum; i++) {
784     ::pthread_spin_destroy(spins + i);
785   }
786   delete[] spins;
787   delete core;
788 #endif
789 }
790 
791 
792 /**
793  * Get the lock of a slot.
794  */
lock(size_t idx)795 void SlottedSpinLock::lock(size_t idx) {
796 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
797   _assert_(true);
798   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
799   uint32_t* lock = core->locks + idx;
800   uint32_t wcnt = 0;
801   while (::InterlockedCompareExchange((LONG*)lock, 1, 0) != 0) {
802     if (wcnt >= LOCKBUSYLOOP) {
803       Thread::chill();
804     } else {
805       Thread::yield();
806       wcnt++;
807     }
808   }
809 #elif _KC_GCCATOMIC
810   _assert_(true);
811   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
812   uint32_t* lock = core->locks + idx;
813   uint32_t wcnt = 0;
814   while (!__sync_bool_compare_and_swap(lock, 0, 1)) {
815     if (wcnt >= LOCKBUSYLOOP) {
816       Thread::chill();
817     } else {
818       Thread::yield();
819       wcnt++;
820     }
821   }
822 #else
823   _assert_(true);
824   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
825   if (::pthread_spin_lock(core->spins + idx) != 0)
826     throw std::runtime_error("pthread_spin_lock");
827 #endif
828 }
829 
830 
831 /**
832  * Release the lock of a slot.
833  */
unlock(size_t idx)834 void SlottedSpinLock::unlock(size_t idx) {
835 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
836   _assert_(true);
837   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
838   uint32_t* lock = core->locks + idx;
839   ::InterlockedExchange((LONG*)lock, 0);
840 #elif _KC_GCCATOMIC
841   _assert_(true);
842   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
843   uint32_t* lock = core->locks + idx;
844   __sync_lock_release(lock);
845 #else
846   _assert_(true);
847   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
848   if (::pthread_spin_unlock(core->spins + idx) != 0)
849     throw std::runtime_error("pthread_spin_unlock");
850 #endif
851 }
852 
853 
854 /**
855  * Get the locks of all slots.
856  */
lock_all()857 void SlottedSpinLock::lock_all() {
858 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
859   _assert_(true);
860   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
861   uint32_t* locks = core->locks;
862   size_t slotnum = core->slotnum;
863   for (size_t i = 0; i < slotnum; i++) {
864     uint32_t* lock = locks + i;
865     uint32_t wcnt = 0;
866     while (::InterlockedCompareExchange((LONG*)lock, 1, 0) != 0) {
867       if (wcnt >= LOCKBUSYLOOP) {
868         Thread::chill();
869       } else {
870         Thread::yield();
871         wcnt++;
872       }
873     }
874   }
875 #elif _KC_GCCATOMIC
876   _assert_(true);
877   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
878   uint32_t* locks = core->locks;
879   size_t slotnum = core->slotnum;
880   for (size_t i = 0; i < slotnum; i++) {
881     uint32_t* lock = locks + i;
882     uint32_t wcnt = 0;
883     while (!__sync_bool_compare_and_swap(lock, 0, 1)) {
884       if (wcnt >= LOCKBUSYLOOP) {
885         Thread::chill();
886       } else {
887         Thread::yield();
888         wcnt++;
889       }
890     }
891   }
892 #else
893   _assert_(true);
894   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
895   ::pthread_spinlock_t* spins = core->spins;
896   size_t slotnum = core->slotnum;
897   for (size_t i = 0; i < slotnum; i++) {
898     if (::pthread_spin_lock(spins + i) != 0)
899       throw std::runtime_error("pthread_spin_lock");
900   }
901 #endif
902 }
903 
904 
905 /**
906  * Release the locks of all slots.
907  */
unlock_all()908 void SlottedSpinLock::unlock_all() {
909 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
910   _assert_(true);
911   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
912   uint32_t* locks = core->locks;
913   size_t slotnum = core->slotnum;
914   for (size_t i = 0; i < slotnum; i++) {
915     uint32_t* lock = locks + i;
916     ::InterlockedExchange((LONG*)lock, 0);
917   }
918 #elif _KC_GCCATOMIC
919   _assert_(true);
920   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
921   uint32_t* locks = core->locks;
922   size_t slotnum = core->slotnum;
923   for (size_t i = 0; i < slotnum; i++) {
924     uint32_t* lock = locks + i;
925     __sync_lock_release(lock);
926   }
927 #else
928   _assert_(true);
929   SlottedSpinLockCore* core = (SlottedSpinLockCore*)opq_;
930   ::pthread_spinlock_t* spins = core->spins;
931   size_t slotnum = core->slotnum;
932   for (size_t i = 0; i < slotnum; i++) {
933     if (::pthread_spin_unlock(spins + i) != 0)
934       throw std::runtime_error("pthread_spin_unlock");
935   }
936 #endif
937 }
938 
939 
940 /**
941  * Default constructor.
942  */
RWLock()943 RWLock::RWLock() : opq_(NULL) {
944 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
945   _assert_(true);
946   SpinRWLock* rwlock = new SpinRWLock;
947   opq_ = (void*)rwlock;
948 #else
949   _assert_(true);
950   ::pthread_rwlock_t* rwlock = new ::pthread_rwlock_t;
951   if (::pthread_rwlock_init(rwlock, NULL) != 0) throw std::runtime_error("pthread_rwlock_init");
952   opq_ = (void*)rwlock;
953 #endif
954 }
955 
956 
957 /**
958  * Destructor.
959  */
~RWLock()960 RWLock::~RWLock() {
961 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
962   _assert_(true);
963   SpinRWLock* rwlock = (SpinRWLock*)opq_;
964   delete rwlock;
965 #else
966   _assert_(true);
967   ::pthread_rwlock_t* rwlock = (::pthread_rwlock_t*)opq_;
968   ::pthread_rwlock_destroy(rwlock);
969   delete rwlock;
970 #endif
971 }
972 
973 
974 /**
975  * Get the writer lock.
976  */
lock_writer()977 void RWLock::lock_writer() {
978 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
979   _assert_(true);
980   SpinRWLock* rwlock = (SpinRWLock*)opq_;
981   rwlock->lock_writer();
982 #else
983   _assert_(true);
984   ::pthread_rwlock_t* rwlock = (::pthread_rwlock_t*)opq_;
985   if (::pthread_rwlock_wrlock(rwlock) != 0) throw std::runtime_error("pthread_rwlock_lock");
986 #endif
987 }
988 
989 
990 /**
991  * Try to get the writer lock.
992  */
lock_writer_try()993 bool RWLock::lock_writer_try() {
994 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
995   _assert_(true);
996   SpinRWLock* rwlock = (SpinRWLock*)opq_;
997   return rwlock->lock_writer_try();
998 #else
999   _assert_(true);
1000   ::pthread_rwlock_t* rwlock = (::pthread_rwlock_t*)opq_;
1001   int32_t ecode = ::pthread_rwlock_trywrlock(rwlock);
1002   if (ecode == 0) return true;
1003   if (ecode != EBUSY) throw std::runtime_error("pthread_rwlock_trylock");
1004   return false;
1005 #endif
1006 }
1007 
1008 
1009 /**
1010  * Get a reader lock.
1011  */
lock_reader()1012 void RWLock::lock_reader() {
1013 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1014   _assert_(true);
1015   SpinRWLock* rwlock = (SpinRWLock*)opq_;
1016   rwlock->lock_reader();
1017 #else
1018   _assert_(true);
1019   ::pthread_rwlock_t* rwlock = (::pthread_rwlock_t*)opq_;
1020   if (::pthread_rwlock_rdlock(rwlock) != 0) throw std::runtime_error("pthread_rwlock_lock");
1021 #endif
1022 }
1023 
1024 
1025 /**
1026  * Try to get a reader lock.
1027  */
lock_reader_try()1028 bool RWLock::lock_reader_try() {
1029 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1030   _assert_(true);
1031   SpinRWLock* rwlock = (SpinRWLock*)opq_;
1032   return rwlock->lock_reader_try();
1033 #else
1034   _assert_(true);
1035   ::pthread_rwlock_t* rwlock = (::pthread_rwlock_t*)opq_;
1036   int32_t ecode = ::pthread_rwlock_tryrdlock(rwlock);
1037   if (ecode == 0) return true;
1038   if (ecode != EBUSY) throw std::runtime_error("pthread_rwlock_trylock");
1039   return false;
1040 #endif
1041 }
1042 
1043 
1044 /**
1045  * Release the lock.
1046  */
unlock()1047 void RWLock::unlock() {
1048 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1049   _assert_(true);
1050   SpinRWLock* rwlock = (SpinRWLock*)opq_;
1051   rwlock->unlock();
1052 #else
1053   _assert_(true);
1054   ::pthread_rwlock_t* rwlock = (::pthread_rwlock_t*)opq_;
1055   if (::pthread_rwlock_unlock(rwlock) != 0) throw std::runtime_error("pthread_rwlock_unlock");
1056 #endif
1057 }
1058 
1059 
1060 /**
1061  * SlottedRWLock internal.
1062  */
1063 struct SlottedRWLockCore {
1064 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1065   RWLock* rwlocks;                       ///< primitives
1066   size_t slotnum;                        ///< number of slots
1067 #else
1068   ::pthread_rwlock_t* rwlocks;           ///< primitives
1069   size_t slotnum;                        ///< number of slots
1070 #endif
1071 };
1072 
1073 
1074 /**
1075  * Constructor.
1076  */
SlottedRWLock(size_t slotnum)1077 SlottedRWLock::SlottedRWLock(size_t slotnum) : opq_(NULL) {
1078 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1079   _assert_(true);
1080   SlottedRWLockCore* core = new SlottedRWLockCore;
1081   RWLock* rwlocks = new RWLock[slotnum];
1082   core->rwlocks = rwlocks;
1083   core->slotnum = slotnum;
1084   opq_ = (void*)core;
1085 #else
1086   _assert_(true);
1087   SlottedRWLockCore* core = new SlottedRWLockCore;
1088   ::pthread_rwlock_t* rwlocks = new ::pthread_rwlock_t[slotnum];
1089   for (size_t i = 0; i < slotnum; i++) {
1090     if (::pthread_rwlock_init(rwlocks + i, NULL) != 0)
1091       throw std::runtime_error("pthread_rwlock_init");
1092   }
1093   core->rwlocks = rwlocks;
1094   core->slotnum = slotnum;
1095   opq_ = (void*)core;
1096 #endif
1097 }
1098 
1099 
1100 /**
1101  * Destructor.
1102  */
~SlottedRWLock()1103 SlottedRWLock::~SlottedRWLock() {
1104 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1105   _assert_(true);
1106   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1107   delete[] core->rwlocks;
1108   delete core;
1109 #else
1110   _assert_(true);
1111   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1112   ::pthread_rwlock_t* rwlocks = core->rwlocks;
1113   size_t slotnum = core->slotnum;
1114   for (size_t i = 0; i < slotnum; i++) {
1115     ::pthread_rwlock_destroy(rwlocks + i);
1116   }
1117   delete[] rwlocks;
1118   delete core;
1119 #endif
1120 }
1121 
1122 
1123 /**
1124  * Get the writer lock of a slot.
1125  */
lock_writer(size_t idx)1126 void SlottedRWLock::lock_writer(size_t idx) {
1127 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1128   _assert_(true);
1129   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1130   core->rwlocks[idx].lock_writer();
1131 #else
1132   _assert_(true);
1133   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1134   if (::pthread_rwlock_wrlock(core->rwlocks + idx) != 0)
1135     throw std::runtime_error("pthread_rwlock_wrlock");
1136 #endif
1137 }
1138 
1139 
1140 /**
1141  * Get the reader lock of a slot.
1142  */
lock_reader(size_t idx)1143 void SlottedRWLock::lock_reader(size_t idx) {
1144 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1145   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1146   core->rwlocks[idx].lock_reader();
1147 #else
1148   _assert_(true);
1149   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1150   if (::pthread_rwlock_rdlock(core->rwlocks + idx) != 0)
1151     throw std::runtime_error("pthread_rwlock_rdlock");
1152 #endif
1153 }
1154 
1155 
1156 /**
1157  * Release the lock of a slot.
1158  */
unlock(size_t idx)1159 void SlottedRWLock::unlock(size_t idx) {
1160 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1161   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1162   core->rwlocks[idx].unlock();
1163 #else
1164   _assert_(true);
1165   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1166   if (::pthread_rwlock_unlock(core->rwlocks + idx) != 0)
1167     throw std::runtime_error("pthread_rwlock_unlock");
1168 #endif
1169 }
1170 
1171 
1172 /**
1173  * Get the writer locks of all slots.
1174  */
lock_writer_all()1175 void SlottedRWLock::lock_writer_all() {
1176 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1177   _assert_(true);
1178   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1179   RWLock* rwlocks = core->rwlocks;
1180   size_t slotnum = core->slotnum;
1181   for (size_t i = 0; i < slotnum; i++) {
1182     rwlocks[i].lock_writer();
1183   }
1184 #else
1185   _assert_(true);
1186   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1187   ::pthread_rwlock_t* rwlocks = core->rwlocks;
1188   size_t slotnum = core->slotnum;
1189   for (size_t i = 0; i < slotnum; i++) {
1190     if (::pthread_rwlock_wrlock(rwlocks + i) != 0)
1191       throw std::runtime_error("pthread_rwlock_wrlock");
1192   }
1193 #endif
1194 }
1195 
1196 
1197 /**
1198  * Get the reader locks of all slots.
1199  */
lock_reader_all()1200 void SlottedRWLock::lock_reader_all() {
1201 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1202   _assert_(true);
1203   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1204   RWLock* rwlocks = core->rwlocks;
1205   size_t slotnum = core->slotnum;
1206   for (size_t i = 0; i < slotnum; i++) {
1207     rwlocks[i].lock_reader();
1208   }
1209 #else
1210   _assert_(true);
1211   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1212   ::pthread_rwlock_t* rwlocks = core->rwlocks;
1213   size_t slotnum = core->slotnum;
1214   for (size_t i = 0; i < slotnum; i++) {
1215     if (::pthread_rwlock_rdlock(rwlocks + i) != 0)
1216       throw std::runtime_error("pthread_rwlock_rdlock");
1217   }
1218 #endif
1219 }
1220 
1221 
1222 /**
1223  * Release the locks of all slots.
1224  */
unlock_all()1225 void SlottedRWLock::unlock_all() {
1226 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1227   _assert_(true);
1228   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1229   RWLock* rwlocks = core->rwlocks;
1230   size_t slotnum = core->slotnum;
1231   for (size_t i = 0; i < slotnum; i++) {
1232     rwlocks[i].unlock();
1233   }
1234 #else
1235   _assert_(true);
1236   SlottedRWLockCore* core = (SlottedRWLockCore*)opq_;
1237   ::pthread_rwlock_t* rwlocks = core->rwlocks;
1238   size_t slotnum = core->slotnum;
1239   for (size_t i = 0; i < slotnum; i++) {
1240     if (::pthread_rwlock_unlock(rwlocks + i) != 0)
1241       throw std::runtime_error("pthread_rwlock_unlock");
1242   }
1243 #endif
1244 }
1245 
1246 
1247 /**
1248  * SpinRWLock internal.
1249  */
1250 struct SpinRWLockCore {
1251 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1252   LONG sem;                              ///< semaphore
1253   uint32_t cnt;                          ///< count of threads
1254 #elif _KC_GCCATOMIC
1255   int32_t sem;                           ///< semaphore
1256   uint32_t cnt;                          ///< count of threads
1257 #else
1258   ::pthread_spinlock_t sem;              ///< semaphore
1259   uint32_t cnt;                          ///< count of threads
1260 #endif
1261 };
1262 
1263 
1264 /**
1265  * Lock the semephore of SpinRWLock.
1266  * @param core the internal fields.
1267  */
1268 static void spinrwlocklock(SpinRWLockCore* core);
1269 
1270 
1271 /**
1272  * Unlock the semephore of SpinRWLock.
1273  * @param core the internal fields.
1274  */
1275 static void spinrwlockunlock(SpinRWLockCore* core);
1276 
1277 
1278 /**
1279  * Default constructor.
1280  */
SpinRWLock()1281 SpinRWLock::SpinRWLock() : opq_(NULL) {
1282 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || _KC_GCCATOMIC
1283   _assert_(true);
1284   SpinRWLockCore* core = new SpinRWLockCore;
1285   core->sem = 0;
1286   core->cnt = 0;
1287   opq_ = (void*)core;
1288 #else
1289   _assert_(true);
1290   SpinRWLockCore* core = new SpinRWLockCore;
1291   if (::pthread_spin_init(&core->sem, PTHREAD_PROCESS_PRIVATE) != 0)
1292     throw std::runtime_error("pthread_spin_init");
1293   core->cnt = 0;
1294   opq_ = (void*)core;
1295 #endif
1296 }
1297 
1298 
1299 /**
1300  * Destructor.
1301  */
~SpinRWLock()1302 SpinRWLock::~SpinRWLock() {
1303 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || _KC_GCCATOMIC
1304   _assert_(true);
1305   SpinRWLockCore* core = (SpinRWLockCore*)opq_;
1306   delete core;
1307 #else
1308   _assert_(true);
1309   SpinRWLockCore* core = (SpinRWLockCore*)opq_;
1310   ::pthread_spin_destroy(&core->sem);
1311   delete core;
1312 #endif
1313 }
1314 
1315 
1316 /**
1317  * Get the writer lock.
1318  */
lock_writer()1319 void SpinRWLock::lock_writer() {
1320   _assert_(true);
1321   SpinRWLockCore* core = (SpinRWLockCore*)opq_;
1322   spinrwlocklock(core);
1323   uint32_t wcnt = 0;
1324   while (core->cnt > 0) {
1325     spinrwlockunlock(core);
1326     if (wcnt >= LOCKBUSYLOOP) {
1327       Thread::chill();
1328     } else {
1329       Thread::yield();
1330       wcnt++;
1331     }
1332     spinrwlocklock(core);
1333   }
1334   core->cnt = INT32MAX;
1335   spinrwlockunlock(core);
1336 }
1337 
1338 
1339 /**
1340  * Try to get the writer lock.
1341  */
lock_writer_try()1342 bool SpinRWLock::lock_writer_try() {
1343   _assert_(true);
1344   SpinRWLockCore* core = (SpinRWLockCore*)opq_;
1345   spinrwlocklock(core);
1346   if (core->cnt > 0) {
1347     spinrwlockunlock(core);
1348     return false;
1349   }
1350   core->cnt = INT32MAX;
1351   spinrwlockunlock(core);
1352   return true;
1353 }
1354 
1355 
1356 /**
1357  * Get a reader lock.
1358  */
lock_reader()1359 void SpinRWLock::lock_reader() {
1360   _assert_(true);
1361   SpinRWLockCore* core = (SpinRWLockCore*)opq_;
1362   spinrwlocklock(core);
1363   uint32_t wcnt = 0;
1364   while (core->cnt >= (uint32_t)INT32MAX) {
1365     spinrwlockunlock(core);
1366     if (wcnt >= LOCKBUSYLOOP) {
1367       Thread::chill();
1368     } else {
1369       Thread::yield();
1370       wcnt++;
1371     }
1372     spinrwlocklock(core);
1373   }
1374   core->cnt++;
1375   spinrwlockunlock(core);
1376 }
1377 
1378 
1379 /**
1380  * Try to get a reader lock.
1381  */
lock_reader_try()1382 bool SpinRWLock::lock_reader_try() {
1383   _assert_(true);
1384   SpinRWLockCore* core = (SpinRWLockCore*)opq_;
1385   spinrwlocklock(core);
1386   if (core->cnt >= (uint32_t)INT32MAX) {
1387     spinrwlockunlock(core);
1388     return false;
1389   }
1390   core->cnt++;
1391   spinrwlockunlock(core);
1392   return true;
1393 }
1394 
1395 
1396 /**
1397  * Release the lock.
1398  */
unlock()1399 void SpinRWLock::unlock() {
1400   _assert_(true);
1401   SpinRWLockCore* core = (SpinRWLockCore*)opq_;
1402   spinrwlocklock(core);
1403   if (core->cnt >= (uint32_t)INT32MAX) {
1404     core->cnt = 0;
1405   } else {
1406     core->cnt--;
1407   }
1408   spinrwlockunlock(core);
1409 }
1410 
1411 
1412 /**
1413  * Promote a reader lock to the writer lock.
1414  */
promote()1415 bool SpinRWLock::promote() {
1416   _assert_(true);
1417   SpinRWLockCore* core = (SpinRWLockCore*)opq_;
1418   spinrwlocklock(core);
1419   if (core->cnt > 1) {
1420     spinrwlockunlock(core);
1421     return false;
1422   }
1423   core->cnt = INT32MAX;
1424   spinrwlockunlock(core);
1425   return true;
1426 }
1427 
1428 
1429 /**
1430  * Demote the writer lock to a reader lock.
1431  */
demote()1432 void SpinRWLock::demote() {
1433   _assert_(true);
1434   SpinRWLockCore* core = (SpinRWLockCore*)opq_;
1435   spinrwlocklock(core);
1436   core->cnt = 1;
1437   spinrwlockunlock(core);
1438 }
1439 
1440 
1441 /**
1442  * Lock the semephore of SpinRWLock.
1443  */
spinrwlocklock(SpinRWLockCore * core)1444 static void spinrwlocklock(SpinRWLockCore* core) {
1445 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1446   _assert_(core);
1447   while (::InterlockedCompareExchange(&core->sem, 1, 0) != 0) {
1448     ::Sleep(0);
1449   }
1450 #elif _KC_GCCATOMIC
1451   _assert_(core);
1452   while (!__sync_bool_compare_and_swap(&core->sem, 0, 1)) {
1453     ::sched_yield();
1454   }
1455 #else
1456   _assert_(core);
1457   if (::pthread_spin_lock(&core->sem) != 0) throw std::runtime_error("pthread_spin_lock");
1458 #endif
1459 }
1460 
1461 
1462 /**
1463  * Unlock the semephore of SpinRWLock.
1464  */
spinrwlockunlock(SpinRWLockCore * core)1465 static void spinrwlockunlock(SpinRWLockCore* core) {
1466 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1467   _assert_(core);
1468   ::InterlockedExchange(&core->sem, 0);
1469 #elif _KC_GCCATOMIC
1470   _assert_(core);
1471   __sync_lock_release(&core->sem);
1472 #else
1473   _assert_(core);
1474   if (::pthread_spin_unlock(&core->sem) != 0) throw std::runtime_error("pthread_spin_unlock");
1475 #endif
1476 }
1477 
1478 
1479 /**
1480  * SlottedRWLock internal.
1481  */
1482 struct SlottedSpinRWLockCore {
1483 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1484   LONG sems[LOCKSEMNUM];                 ///< semaphores
1485 #elif _KC_GCCATOMIC
1486   int32_t sems[LOCKSEMNUM];              ///< semaphores
1487 #else
1488   ::pthread_spinlock_t sems[LOCKSEMNUM]; ///< semaphores
1489 #endif
1490   uint32_t* cnts;                        ///< counts of threads
1491   size_t slotnum;                        ///< number of slots
1492 };
1493 
1494 
1495 /**
1496  * Lock the semephore of SlottedSpinRWLock.
1497  * @param core the internal fields.
1498  * @param idx the index of the semaphoe.
1499  */
1500 static void slottedspinrwlocklock(SlottedSpinRWLockCore* core, size_t idx);
1501 
1502 
1503 /**
1504  * Unlock the semephore of SlottedSpinRWLock.
1505  * @param core the internal fields.
1506  * @param idx the index of the semaphoe.
1507  */
1508 static void slottedspinrwlockunlock(SlottedSpinRWLockCore* core, size_t idx);
1509 
1510 
1511 /**
1512  * Constructor.
1513  */
SlottedSpinRWLock(size_t slotnum)1514 SlottedSpinRWLock::SlottedSpinRWLock(size_t slotnum) : opq_(NULL) {
1515 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1516   SlottedSpinRWLockCore* core = new SlottedSpinRWLockCore;
1517   LONG* sems = core->sems;
1518   uint32_t* cnts = new uint32_t[slotnum];
1519   for (size_t i = 0; i < LOCKSEMNUM; i++) {
1520     sems[i] = 0;
1521   }
1522   for (size_t i = 0; i < slotnum; i++) {
1523     cnts[i] = 0;
1524   }
1525   core->cnts = cnts;
1526   core->slotnum = slotnum;
1527   opq_ = (void*)core;
1528 #elif _KC_GCCATOMIC
1529   SlottedSpinRWLockCore* core = new SlottedSpinRWLockCore;
1530   int32_t* sems = core->sems;
1531   uint32_t* cnts = new uint32_t[slotnum];
1532   for (size_t i = 0; i < LOCKSEMNUM; i++) {
1533     sems[i] = 0;
1534   }
1535   for (size_t i = 0; i < slotnum; i++) {
1536     cnts[i] = 0;
1537   }
1538   core->cnts = cnts;
1539   core->slotnum = slotnum;
1540   opq_ = (void*)core;
1541 #else
1542   _assert_(true);
1543   SlottedSpinRWLockCore* core = new SlottedSpinRWLockCore;
1544   ::pthread_spinlock_t* sems = core->sems;
1545   uint32_t* cnts = new uint32_t[slotnum];
1546   for (size_t i = 0; i < LOCKSEMNUM; i++) {
1547     if (::pthread_spin_init(sems + i, PTHREAD_PROCESS_PRIVATE) != 0)
1548       throw std::runtime_error("pthread_spin_init");
1549   }
1550   for (size_t i = 0; i < slotnum; i++) {
1551     cnts[i] = 0;
1552   }
1553   core->cnts = cnts;
1554   core->slotnum = slotnum;
1555   opq_ = (void*)core;
1556 #endif
1557 }
1558 
1559 
1560 /**
1561  * Destructor.
1562  */
~SlottedSpinRWLock()1563 SlottedSpinRWLock::~SlottedSpinRWLock() {
1564 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || _KC_GCCATOMIC
1565   _assert_(true);
1566   SlottedSpinRWLockCore* core = (SlottedSpinRWLockCore*)opq_;
1567   delete[] core->cnts;
1568   delete core;
1569 #else
1570   _assert_(true);
1571   SlottedSpinRWLockCore* core = (SlottedSpinRWLockCore*)opq_;
1572   ::pthread_spinlock_t* sems = core->sems;
1573   for (size_t i = 0; i < LOCKSEMNUM; i++) {
1574     ::pthread_spin_destroy(sems + i);
1575   }
1576   delete[] core->cnts;
1577   delete core;
1578 #endif
1579 }
1580 
1581 
1582 /**
1583  * Get the writer lock of a slot.
1584  */
lock_writer(size_t idx)1585 void SlottedSpinRWLock::lock_writer(size_t idx) {
1586   _assert_(true);
1587   SlottedSpinRWLockCore* core = (SlottedSpinRWLockCore*)opq_;
1588   size_t semidx = idx % LOCKSEMNUM;
1589   slottedspinrwlocklock(core, semidx);
1590   uint32_t wcnt = 0;
1591   while (core->cnts[idx] > 0) {
1592     slottedspinrwlockunlock(core, semidx);
1593     if (wcnt >= LOCKBUSYLOOP) {
1594       Thread::chill();
1595     } else {
1596       Thread::yield();
1597       wcnt++;
1598     }
1599     slottedspinrwlocklock(core, semidx);
1600   }
1601   core->cnts[idx] = INT32MAX;
1602   slottedspinrwlockunlock(core, semidx);
1603 }
1604 
1605 
1606 /**
1607  * Get the reader lock of a slot.
1608  */
lock_reader(size_t idx)1609 void SlottedSpinRWLock::lock_reader(size_t idx) {
1610   _assert_(true);
1611   SlottedSpinRWLockCore* core = (SlottedSpinRWLockCore*)opq_;
1612   size_t semidx = idx % LOCKSEMNUM;
1613   slottedspinrwlocklock(core, semidx);
1614   uint32_t wcnt = 0;
1615   while (core->cnts[idx] >= (uint32_t)INT32MAX) {
1616     slottedspinrwlockunlock(core, semidx);
1617     if (wcnt >= LOCKBUSYLOOP) {
1618       Thread::chill();
1619     } else {
1620       Thread::yield();
1621       wcnt++;
1622     }
1623     slottedspinrwlocklock(core, semidx);
1624   }
1625   core->cnts[idx]++;
1626   slottedspinrwlockunlock(core, semidx);
1627 }
1628 
1629 
1630 /**
1631  * Release the lock of a slot.
1632  */
unlock(size_t idx)1633 void SlottedSpinRWLock::unlock(size_t idx) {
1634   _assert_(true);
1635   SlottedSpinRWLockCore* core = (SlottedSpinRWLockCore*)opq_;
1636   size_t semidx = idx % LOCKSEMNUM;
1637   slottedspinrwlocklock(core, semidx);
1638   if (core->cnts[idx] >= (uint32_t)INT32MAX) {
1639     core->cnts[idx] = 0;
1640   } else {
1641     core->cnts[idx]--;
1642   }
1643   slottedspinrwlockunlock(core, semidx);
1644 }
1645 
1646 
1647 /**
1648  * Get the writer locks of all slots.
1649  */
lock_writer_all()1650 void SlottedSpinRWLock::lock_writer_all() {
1651   _assert_(true);
1652   SlottedSpinRWLockCore* core = (SlottedSpinRWLockCore*)opq_;
1653   uint32_t* cnts = core->cnts;
1654   size_t slotnum = core->slotnum;
1655   for (size_t i = 0; i < slotnum; i++) {
1656     size_t semidx = i % LOCKSEMNUM;
1657     slottedspinrwlocklock(core, semidx);
1658     uint32_t wcnt = 0;
1659     while (cnts[i] > 0) {
1660       slottedspinrwlockunlock(core, semidx);
1661       if (wcnt >= LOCKBUSYLOOP) {
1662         Thread::chill();
1663       } else {
1664         Thread::yield();
1665         wcnt++;
1666       }
1667       slottedspinrwlocklock(core, semidx);
1668     }
1669     cnts[i] = INT32MAX;
1670     slottedspinrwlockunlock(core, semidx);
1671   }
1672 }
1673 
1674 
1675 /**
1676  * Get the reader locks of all slots.
1677  */
lock_reader_all()1678 void SlottedSpinRWLock::lock_reader_all() {
1679   _assert_(true);
1680   SlottedSpinRWLockCore* core = (SlottedSpinRWLockCore*)opq_;
1681   uint32_t* cnts = core->cnts;
1682   size_t slotnum = core->slotnum;
1683   for (size_t i = 0; i < slotnum; i++) {
1684     size_t semidx = i % LOCKSEMNUM;
1685     slottedspinrwlocklock(core, semidx);
1686     uint32_t wcnt = 0;
1687     while (cnts[i] >= (uint32_t)INT32MAX) {
1688       slottedspinrwlockunlock(core, semidx);
1689       if (wcnt >= LOCKBUSYLOOP) {
1690         Thread::chill();
1691       } else {
1692         Thread::yield();
1693         wcnt++;
1694       }
1695       slottedspinrwlocklock(core, semidx);
1696     }
1697     cnts[i]++;
1698     slottedspinrwlockunlock(core, semidx);
1699   }
1700 }
1701 
1702 
1703 /**
1704  * Release the locks of all slots.
1705  */
unlock_all()1706 void SlottedSpinRWLock::unlock_all() {
1707   _assert_(true);
1708   SlottedSpinRWLockCore* core = (SlottedSpinRWLockCore*)opq_;
1709   uint32_t* cnts = core->cnts;
1710   size_t slotnum = core->slotnum;
1711   for (size_t i = 0; i < slotnum; i++) {
1712     size_t semidx = i % LOCKSEMNUM;
1713     slottedspinrwlocklock(core, semidx);
1714     if (cnts[i] >= (uint32_t)INT32MAX) {
1715       cnts[i] = 0;
1716     } else {
1717       cnts[i]--;
1718     }
1719     slottedspinrwlockunlock(core, semidx);
1720   }
1721 }
1722 
1723 
1724 /**
1725  * Lock the semephore of SlottedSpinRWLock.
1726  */
slottedspinrwlocklock(SlottedSpinRWLockCore * core,size_t idx)1727 static void slottedspinrwlocklock(SlottedSpinRWLockCore* core, size_t idx) {
1728 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1729   _assert_(core);
1730   while (::InterlockedCompareExchange(core->sems + idx, 1, 0) != 0) {
1731     ::Sleep(0);
1732   }
1733 #elif _KC_GCCATOMIC
1734   _assert_(core);
1735   while (!__sync_bool_compare_and_swap(core->sems + idx, 0, 1)) {
1736     ::sched_yield();
1737   }
1738 #else
1739   _assert_(core);
1740   if (::pthread_spin_lock(core->sems + idx) != 0) throw std::runtime_error("pthread_spin_lock");
1741 #endif
1742 }
1743 
1744 
1745 /**
1746  * Unlock the semephore of SlottedSpinRWLock.
1747  */
slottedspinrwlockunlock(SlottedSpinRWLockCore * core,size_t idx)1748 static void slottedspinrwlockunlock(SlottedSpinRWLockCore* core, size_t idx) {
1749 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1750   _assert_(core);
1751   ::InterlockedExchange(core->sems + idx, 0);
1752 #elif _KC_GCCATOMIC
1753   _assert_(core);
1754   __sync_lock_release(core->sems + idx);
1755 #else
1756   _assert_(core);
1757   if (::pthread_spin_unlock(core->sems + idx) != 0)
1758     throw std::runtime_error("pthread_spin_unlock");
1759 #endif
1760 }
1761 
1762 
1763 /**
1764  * Default constructor.
1765  */
CondVar()1766 CondVar::CondVar() : opq_(NULL) {
1767 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1768   _assert_(true);
1769   CondVarCore* core = new CondVarCore;
1770   ::InitializeCriticalSection(&core->mutex);
1771   core->wait = 0;
1772   core->wake = 0;
1773   core->sev = ::CreateEvent(NULL, true, false, NULL);
1774   if (!core->sev) throw std::runtime_error("CreateEvent");
1775   core->fev = ::CreateEvent(NULL, false, false, NULL);
1776   if (!core->fev) throw std::runtime_error("CreateEvent");
1777   opq_ = (void*)core;
1778 #else
1779   _assert_(true);
1780   CondVarCore* core = new CondVarCore;
1781   if (::pthread_cond_init(&core->cond, NULL) != 0)
1782     throw std::runtime_error("pthread_cond_init");
1783   opq_ = (void*)core;
1784 #endif
1785 }
1786 
1787 
1788 /**
1789  * Destructor.
1790  */
~CondVar()1791 CondVar::~CondVar() {
1792 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1793   _assert_(true);
1794   CondVarCore* core = (CondVarCore*)opq_;
1795   ::CloseHandle(core->fev);
1796   ::CloseHandle(core->sev);
1797   ::DeleteCriticalSection(&core->mutex);
1798 #else
1799   _assert_(true);
1800   CondVarCore* core = (CondVarCore*)opq_;
1801   ::pthread_cond_destroy(&core->cond);
1802   delete core;
1803 #endif
1804 }
1805 
1806 
1807 /**
1808  * Wait for the signal.
1809  */
wait(Mutex * mutex)1810 void CondVar::wait(Mutex* mutex) {
1811 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1812   _assert_(mutex);
1813   CondVarCore* core = (CondVarCore*)opq_;
1814   ::CRITICAL_SECTION* mymutex = (::CRITICAL_SECTION*)mutex->opq_;
1815   ::EnterCriticalSection(&core->mutex);
1816   core->wait++;
1817   ::LeaveCriticalSection(&core->mutex);
1818   ::LeaveCriticalSection(mymutex);
1819   while (true) {
1820     ::WaitForSingleObject(core->sev, INFINITE);
1821     ::EnterCriticalSection(&core->mutex);
1822     if (core->wake > 0) {
1823       core->wait--;
1824       core->wake--;
1825       if (core->wake < 1) {
1826         ::ResetEvent(core->sev);
1827         ::SetEvent(core->fev);
1828       }
1829       ::LeaveCriticalSection(&core->mutex);
1830       break;
1831     }
1832     ::LeaveCriticalSection(&core->mutex);
1833   }
1834   ::EnterCriticalSection(mymutex);
1835 #else
1836   _assert_(mutex);
1837   CondVarCore* core = (CondVarCore*)opq_;
1838   ::pthread_mutex_t* mymutex = (::pthread_mutex_t*)mutex->opq_;
1839   if (::pthread_cond_wait(&core->cond, mymutex) != 0)
1840     throw std::runtime_error("pthread_cond_wait");
1841 #endif
1842 }
1843 
1844 
1845 /**
1846  * Wait for the signal.
1847  */
wait(Mutex * mutex,double sec)1848 bool CondVar::wait(Mutex* mutex, double sec) {
1849 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1850   _assert_(mutex && sec >= 0);
1851   if (sec <= 0) return false;
1852   CondVarCore* core = (CondVarCore*)opq_;
1853   ::CRITICAL_SECTION* mymutex = (::CRITICAL_SECTION*)mutex->opq_;
1854   ::EnterCriticalSection(&core->mutex);
1855   core->wait++;
1856   ::LeaveCriticalSection(&core->mutex);
1857   ::LeaveCriticalSection(mymutex);
1858   while (true) {
1859     if (::WaitForSingleObject(core->sev, sec * 1000) == WAIT_TIMEOUT) {
1860       ::EnterCriticalSection(&core->mutex);
1861       if (::WaitForSingleObject(core->sev, 0) == WAIT_TIMEOUT) {
1862         core->wait--;
1863         ::SetEvent(core->fev);
1864         ::LeaveCriticalSection(&core->mutex);
1865         ::EnterCriticalSection(mymutex);
1866         return false;
1867       }
1868       ::LeaveCriticalSection(&core->mutex);
1869     }
1870     ::EnterCriticalSection(&core->mutex);
1871     if (core->wake > 0) {
1872       core->wait--;
1873       core->wake--;
1874       if (core->wake < 1) {
1875         ::ResetEvent(core->sev);
1876         ::SetEvent(core->fev);
1877       }
1878       ::LeaveCriticalSection(&core->mutex);
1879       break;
1880     }
1881     ::LeaveCriticalSection(&core->mutex);
1882   }
1883   ::EnterCriticalSection(mymutex);
1884   return true;
1885 #else
1886   _assert_(mutex && sec >= 0);
1887   if (sec <= 0) return false;
1888   CondVarCore* core = (CondVarCore*)opq_;
1889   ::pthread_mutex_t* mymutex = (::pthread_mutex_t*)mutex->opq_;
1890   struct ::timeval tv;
1891   struct ::timespec ts;
1892   if (::gettimeofday(&tv, NULL) == 0) {
1893     double integ;
1894     double fract = std::modf(sec, &integ);
1895     ts.tv_sec = tv.tv_sec + (time_t)integ;
1896     ts.tv_nsec = (long)(tv.tv_usec * 1000.0 + fract * 999999000);
1897     if (ts.tv_nsec >= 1000000000) {
1898       ts.tv_nsec -= 1000000000;
1899       ts.tv_sec++;
1900     }
1901   } else {
1902     ts.tv_sec = std::time(NULL) + 1;
1903     ts.tv_nsec = 0;
1904   }
1905   int32_t ecode = ::pthread_cond_timedwait(&core->cond, mymutex, &ts);
1906   if (ecode == 0) return true;
1907   if (ecode != ETIMEDOUT && ecode != EINTR)
1908     throw std::runtime_error("pthread_cond_timedwait");
1909   return false;
1910 #endif
1911 }
1912 
1913 
1914 /**
1915  * Send the wake-up signal to another waiting thread.
1916  */
signal()1917 void CondVar::signal() {
1918 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1919   _assert_(true);
1920   CondVarCore* core = (CondVarCore*)opq_;
1921   ::EnterCriticalSection(&core->mutex);
1922   if (core->wait > 0) {
1923     core->wake = 1;
1924     ::SetEvent(core->sev);
1925     ::LeaveCriticalSection(&core->mutex);
1926     ::WaitForSingleObject(core->fev, INFINITE);
1927   } else {
1928     ::LeaveCriticalSection(&core->mutex);
1929   }
1930 #else
1931   _assert_(true);
1932   CondVarCore* core = (CondVarCore*)opq_;
1933   if (::pthread_cond_signal(&core->cond) != 0)
1934     throw std::runtime_error("pthread_cond_signal");
1935 #endif
1936 }
1937 
1938 
1939 /**
1940  * Send the wake-up signals to all waiting threads.
1941  */
broadcast()1942 void CondVar::broadcast() {
1943 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1944   _assert_(true);
1945   CondVarCore* core = (CondVarCore*)opq_;
1946   ::EnterCriticalSection(&core->mutex);
1947   if (core->wait > 0) {
1948     core->wake = core->wait;
1949     ::SetEvent(core->sev);
1950     ::LeaveCriticalSection(&core->mutex);
1951     ::WaitForSingleObject(core->fev, INFINITE);
1952   } else {
1953     ::LeaveCriticalSection(&core->mutex);
1954   }
1955 #else
1956   _assert_(true);
1957   CondVarCore* core = (CondVarCore*)opq_;
1958   if (::pthread_cond_broadcast(&core->cond) != 0)
1959     throw std::runtime_error("pthread_cond_broadcast");
1960 #endif
1961 }
1962 
1963 
1964 /**
1965  * Default constructor.
1966  */
TSDKey()1967 TSDKey::TSDKey() : opq_(NULL) {
1968 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1969   _assert_(true);
1970   ::DWORD key = ::TlsAlloc();
1971   if (key == 0xFFFFFFFF) throw std::runtime_error("TlsAlloc");
1972   opq_ = (void*)key;
1973 #else
1974   _assert_(true);
1975   ::pthread_key_t* key = new ::pthread_key_t;
1976   if (::pthread_key_create(key, NULL) != 0)
1977     throw std::runtime_error("pthread_key_create");
1978   opq_ = (void*)key;
1979 #endif
1980 }
1981 
1982 
1983 /**
1984  * Constructor with the specifications.
1985  */
TSDKey(void (* dstr)(void *))1986 TSDKey::TSDKey(void (*dstr)(void*)) : opq_(NULL) {
1987 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
1988   _assert_(true);
1989   ::DWORD key = ::TlsAlloc();
1990   if (key == 0xFFFFFFFF) throw std::runtime_error("TlsAlloc");
1991   opq_ = (void*)key;
1992 #else
1993   _assert_(true);
1994   ::pthread_key_t* key = new ::pthread_key_t;
1995   if (::pthread_key_create(key, dstr) != 0)
1996     throw std::runtime_error("pthread_key_create");
1997   opq_ = (void*)key;
1998 #endif
1999 }
2000 
2001 
2002 /**
2003  * Destructor.
2004  */
~TSDKey()2005 TSDKey::~TSDKey() {
2006 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
2007   _assert_(true);
2008   ::DWORD key = (::DWORD)opq_;
2009   ::TlsFree(key);
2010 #else
2011   _assert_(true);
2012   ::pthread_key_t* key = (::pthread_key_t*)opq_;
2013   ::pthread_key_delete(*key);
2014   delete key;
2015 #endif
2016 }
2017 
2018 
2019 /**
2020  * Set the value.
2021  */
set(void * ptr)2022 void TSDKey::set(void* ptr) {
2023 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
2024   _assert_(true);
2025   ::DWORD key = (::DWORD)opq_;
2026   if (!::TlsSetValue(key, ptr)) std::runtime_error("TlsSetValue");
2027 #else
2028   _assert_(true);
2029   ::pthread_key_t* key = (::pthread_key_t*)opq_;
2030   if (::pthread_setspecific(*key, ptr) != 0)
2031     throw std::runtime_error("pthread_setspecific");
2032 #endif
2033 }
2034 
2035 
2036 /**
2037  * Get the value.
2038  */
get() const2039 void* TSDKey::get() const {
2040 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
2041   _assert_(true);
2042   ::DWORD key = (::DWORD)opq_;
2043   return ::TlsGetValue(key);
2044 #else
2045   _assert_(true);
2046   ::pthread_key_t* key = (::pthread_key_t*)opq_;
2047   return ::pthread_getspecific(*key);
2048 #endif
2049 }
2050 
2051 
2052 /**
2053  * Set the new value.
2054  */
set(int64_t val)2055 int64_t AtomicInt64::set(int64_t val) {
2056 #if (defined(_SYS_MSVC_) || defined(_SYS_MINGW_)) && defined(_SYS_WIN64_)
2057   _assert_(true);
2058   return ::InterlockedExchange((uint64_t*)&value_, val);
2059 #elif _KC_GCCATOMIC
2060   _assert_(true);
2061   int64_t oval = __sync_lock_test_and_set(&value_, val);
2062   __sync_synchronize();
2063   return oval;
2064 #else
2065   _assert_(true);
2066   lock_.lock();
2067   int64_t oval = value_;
2068   value_ = val;
2069   lock_.unlock();
2070   return oval;
2071 #endif
2072 }
2073 
2074 
2075 /**
2076  * Add a value.
2077  */
add(int64_t val)2078 int64_t AtomicInt64::add(int64_t val) {
2079 #if (defined(_SYS_MSVC_) || defined(_SYS_MINGW_)) && defined(_SYS_WIN64_)
2080   _assert_(true);
2081   return ::InterlockedExchangeAdd((uint64_t*)&value_, val);
2082 #elif _KC_GCCATOMIC
2083   _assert_(true);
2084   int64_t oval = __sync_fetch_and_add(&value_, val);
2085   __sync_synchronize();
2086   return oval;
2087 #else
2088   _assert_(true);
2089   lock_.lock();
2090   int64_t oval = value_;
2091   value_ += val;
2092   lock_.unlock();
2093   return oval;
2094 #endif
2095 }
2096 
2097 
2098 /**
2099  * Perform compare-and-swap.
2100  */
cas(int64_t oval,int64_t nval)2101 bool AtomicInt64::cas(int64_t oval, int64_t nval) {
2102 #if (defined(_SYS_MSVC_) || defined(_SYS_MINGW_)) && defined(_SYS_WIN64_)
2103   _assert_(true);
2104   return ::InterlockedCompareExchange((uint64_t*)&value_, nval, oval) == oval;
2105 #elif _KC_GCCATOMIC
2106   _assert_(true);
2107   bool rv = __sync_bool_compare_and_swap(&value_, oval, nval);
2108   __sync_synchronize();
2109   return rv;
2110 #else
2111   _assert_(true);
2112   bool rv = false;
2113   lock_.lock();
2114   if (value_ == oval) {
2115     value_ = nval;
2116     rv = true;
2117   }
2118   lock_.unlock();
2119   return rv;
2120 #endif
2121 }
2122 
2123 
2124 /**
2125  * Get the current value.
2126  */
get() const2127 int64_t AtomicInt64::get() const {
2128 #if (defined(_SYS_MSVC_) || defined(_SYS_MINGW_)) && defined(_SYS_WIN64_)
2129   _assert_(true);
2130   return ::InterlockedExchangeAdd((uint64_t*)&value_, 0);
2131 #elif _KC_GCCATOMIC
2132   _assert_(true);
2133   return __sync_fetch_and_add((int64_t*)&value_, 0);
2134 #else
2135   _assert_(true);
2136   lock_.lock();
2137   int64_t oval = value_;
2138   lock_.unlock();
2139   return oval;
2140 #endif
2141 }
2142 
2143 
2144 }                                        // common namespace
2145 
2146 // END OF FILE
2147