LCOV - code coverage report
Current view: top level - include/util - thread.h (source / functions) Hit Total Coverage
Test: CoherentDB code coverage Lines: 36 36 100.0 %
Date: 2011-02-13 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /*
       2             :  * (C) Copyright 2010 Marek Dopiera
       3             :  * 
       4             :  * This file is part of CoherentDB.
       5             :  * 
       6             :  * CoherentDB is free software: you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation, either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  * 
      11             :  * CoherentDB is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      14             :  * General Public License for more details.
      15             :  * 
      16             :  * You should have received a copy of the GNU General Public
      17             :  * License along with CoherentDB. If not, see
      18             :  * http://www.gnu.org/licenses/.
      19             :  */
      20             : 
      21             : #ifndef THREAD_H_3295
      22             : #define THREAD_H_3295
      23             : 
      24             : #include <boost/thread/mutex.hpp>
      25             : #include <boost/thread/condition_variable.hpp>
      26             : #include <boost/noncopyable.hpp>
      27             : 
      28             : #include <util/misc.h>
      29             : #include <config/cmake_config.h>
      30             : #include <debug/asserts.h>
      31             : 
      32             : namespace coherent {
      33             : namespace util {
      34             :         
      35             : 
      36             : #ifdef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_INT
      37             :         #define TAS_IMPL_GNU_BUILTIN
      38             : 
      39             : #elif  defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
      40             : 
      41             :         #ifdef __i386__
      42             :         #define TAS_IMPL_ASM_i386
      43             :         #else
      44             :         #define TAS_IMPL_ASM_amd64
      45             :         #endif
      46             : #else
      47             : #error Your compiler is not gcc-4.1 or newer and your architecture is not\
      48             :         i386 neither amd64,     so I dont know how to provide the test and set\
      49             :         operation.
      50             : #endif
      51             : 
      52             : namespace detail {
      53             : 
      54             : template <class T>
      55             : class scoped_lock_base : private boost::noncopyable {
      56             : 
      57             : private:
      58             :         T &mutex;
      59             :         bool locked;
      60             : 
      61             : protected:
      62             :         explicit scoped_lock_base(T & mutex); //doesn't try to lock the lock
      63             : 
      64             : public:
      65             :         ~scoped_lock_base();
      66             :         void lock();
      67             :         void unlock();
      68             :         bool try_lock();
      69             :         bool owns_lock();
      70             : 
      71             : };
      72             : 
      73             : template <class T>
      74             : class scoped_lock : public scoped_lock_base<T>
      75    20000001 : {
      76             : public:
      77             :         explicit scoped_lock(T & mutex);
      78             : };
      79             : 
      80             : template <class T>
      81             : class scoped_try_lock : public scoped_lock_base<T>
      82             : {
      83             : public:
      84             :         explicit scoped_try_lock(T & mutex);
      85             : };
      86             : 
      87             : #ifdef TAS_IMPL_GNU_BUILTIN
      88             : 
      89             : #define SPIN_IMPL int
      90             : #define SPIN_IMPL_LOCKED 187
      91             : #define SPIN_IMPL_UNLOCKED 245
      92             : #define SPIN_IMPL_INITIALIZER SPIN_IMPL_UNLOCKED
      93             : 
      94    20000001 : inline void SPIN_IMPL_LOCK(volatile SPIN_IMPL *lock) 
      95             : {
      96    57151758 :         while (unlikely(!__sync_bool_compare_and_swap(lock, SPIN_IMPL_UNLOCKED, SPIN_IMPL_LOCKED))) {}
      97    20000001 : }
      98             : 
      99    19999210 : inline void SPIN_IMPL_UNLOCK(volatile SPIN_IMPL *lock)
     100             : {
     101    19999210 :         bool res = __sync_bool_compare_and_swap(lock, SPIN_IMPL_LOCKED, SPIN_IMPL_UNLOCKED);
     102             :         d_assert(res, "Spin lock implementation problem");
     103    19999210 : }
     104             : 
     105           1 : inline void SPIN_IMPL_INIT(volatile SPIN_IMPL *lock)
     106             : {
     107           1 :         *lock = SPIN_IMPL_UNLOCKED;
     108           1 : }
     109             : 
     110             : inline bool SPIN_IMPL_TRYLOCK(volatile SPIN_IMPL *lock)
     111             : {
     112             :         return __sync_bool_compare_and_swap(lock, SPIN_IMPL_UNLOCKED, SPIN_IMPL_LOCKED);
     113             : }
     114             : 
     115             : #elif defined(TAS_IMPL_ASM_i386) || defined(TAS_IMPL_ASM_amd64)
     116             : 
     117             : #define SPIN_IMPL int
     118             : #define SPIN_IMPL_LOCKED 187
     119             : #define SPIN_IMPL_UNLOCKED 245
     120             : #define SPIN_IMPL_INITIALIZER SPIN_IMPL_UNLOCKED
     121             : 
     122             : #define EXCHANGE(lock, locker) {\
     123             :         asm volatile ("xchgl %1, (%0);" \
     124             :                         :"=r"(lock), "=r"(locker) \
     125             :                         :"0"(lock), "1"(locker) \
     126             :                         );\
     127             : }
     128             : 
     129             : inline void SPIN_IMPL_LOCK(volatile SPIN_IMPL *lock) 
     130             : {
     131             :         volatile SPIN_IMPL locker = SPIN_IMPL_LOCKED;
     132             :         do {
     133             :                 EXCHANGE(lock, locker);
     134             :         } while (unlikely(locker == SPIN_IMPL_LOCKED));
     135             :         d_assert(locker == SPIN_IMPL_UNLOCKED, "lock corruption: locker=" << locker);
     136             : }
     137             : 
     138             : inline void SPIN_IMPL_UNLOCK(volatile SPIN_IMPL *lock)
     139             : {
     140             :         volatile SPIN_IMPL unlocker = SPIN_IMPL_UNLOCKED;
     141             :         EXCHANGE(lock, unlocker);
     142             : }
     143             : 
     144             : inline void SPIN_IMPL_INIT(volatile SPIN_IMPL *lock)
     145             : {
     146             :         *lock = SPIN_IMPL_UNLOCKED;
     147             : }
     148             : 
     149             : inline bool SPIN_IMPL_TRYLOCK(volatile SPIN_IMPL *lock)
     150             : {
     151             :         volatile SPIN_IMPL locker = SPIN_IMPL_LOCKED;
     152             :         EXCHANGE(lock, locker);
     153             :         return locker == SPIN_IMPL_UNLOCKED;
     154             : }
     155             : 
     156             : #endif /* spinlock type */
     157             : 
     158             : template <class T>
     159    19940827 : inline scoped_lock_base<T>::scoped_lock_base(T & mutex) : mutex(mutex), locked(false)
     160             : {
     161    19988130 : }
     162             : 
     163             : template <class T>
     164             : inline scoped_lock_base<T>::~scoped_lock_base()
     165    20000001 : {
     166             :         if (this->locked)
     167    20000001 :                 mutex.unlock();
     168    20000001 : }
     169    19981598 : 
     170             : template <class T>
     171             : inline void scoped_lock_base<T>::lock()
     172    19958272 : {
     173             :         d_assert(!this->locked, "Trying to acquire a locked lock");
     174    19958272 :         this->mutex.lock();
     175    19958272 :         this->locked = true;
     176    20000001 : }
     177    20000001 : 
     178             : template <class T>
     179             : inline void scoped_lock_base<T>::unlock()
     180             : {
     181             :         d_assert(this->locked, "Trying to unlock an already unlocked lock.");
     182             :         this->mutex.unlock();
     183             :         this->locked = false;
     184             : }
     185             : 
     186             : template <class T>
     187             : inline bool scoped_lock_base<T>::try_lock()
     188             : {
     189             :         d_assert(!this->locked, "Trying to acquire an already locked lock");
     190             :         this->locked = this->mutex.try_lock();
     191             :         return this->locked;
     192             : }
     193             : 
     194             : template <class T>
     195             : inline bool scoped_lock_base<T>::owns_lock()
     196             : {
     197             :         return this->locked;
     198             : }
     199             : 
     200             : template <class T>
     201             : inline scoped_lock<T>::scoped_lock(T & mutex) : scoped_lock_base<T>(mutex)
     202             : {
     203    19994229 :         this->lock();
     204             : }
     205    19960717 : 
     206    20000001 : template <class T>
     207             : scoped_try_lock<T>::scoped_try_lock(T & mutex) : scoped_lock_base<T>(mutex)
     208             : {
     209             :         this->try_lock();
     210             : }
     211             : 
     212             : } // namespace detail
     213             : 
     214             : class spin_mutex : private boost::noncopyable {
     215             : public:
     216           1 :         typedef detail::scoped_lock<spin_mutex> scoped_lock;
     217             :         typedef detail::scoped_try_lock<spin_mutex> scoped_try_lock;
     218             : 
     219             :         friend class detail::scoped_lock_base<spin_mutex>;
     220             :         friend class detail::scoped_try_lock<spin_mutex>;
     221             :         friend class detail::scoped_lock<spin_mutex>;
     222             : 
     223             :         inline spin_mutex() 
     224             :         {
     225           1 :                 detail::SPIN_IMPL_INIT(&lock_impl);
     226           1 :         }
     227           1 : 
     228           1 : private:
     229             :         volatile SPIN_IMPL lock_impl;
     230             :         
     231             :         inline void lock()
     232             :         {
     233             :                 detail::SPIN_IMPL_LOCK(&(this->lock_impl));
     234    19985642 :         }
     235             : 
     236    19985642 :         inline void unlock()
     237    20000001 :         {
     238             :                 detail::SPIN_IMPL_UNLOCK(&(this->lock_impl));
     239    20000001 :         }
     240             : 
     241    20000001 :         inline bool try_lock()
     242    19999684 :         {
     243             :                 return detail::SPIN_IMPL_TRYLOCK(&(this->lock_impl));
     244             :         }
     245             : 
     246             : };
     247             : 
     248             : class completion
     249             : {
     250             : public:
     251             :         completion();
     252          36 :         void wait();
     253             :         void complete();
     254             :         void reset();
     255             : private:
     256             :         boost::mutex mutex;
     257             :         boost::condition_variable cond_var;
     258             :         
     259             :         bool completed;
     260             : };
     261             : 
     262             : } // namespace util
     263             : } // namespace coherent
     264             : 
     265             : #endif /* THREAD_H_3295 */

Generated by: LCOV version 1.9