About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
libFAUDES

Sections

Index

cfl_tinythread.h

Go to the documentation of this file.
00001 /** @file cfl_tinythread.h Minimalistic portable multi-threading */
00002 
00003 /*
00004 We provide Marcus Gleenard's TinyThread++ for libFAUDES 
00005 plug-ins to implement protable multi-threading. This is currently 
00006 used in the iodevice plug-ing for networking and edge-detection.
00007 For sake of simplicity, this include file is merged with
00008 fast_mutex.h from the original distribution. We hereby acknowledge 
00009 the authors work and state the original copyright below.
00010 
00011 Note, however, that core libFAUDES itself is *NOT* thread-safe, 
00012 in particular for using global statics for symbol tables. This 
00013 may be improved in a subsequent reversion.
00014 
00015 */
00016 
00017 /* 
00018 Copyright (c) 2010-2012 Marcus Geelnard
00019 
00020 This software is provided 'as-is', without any express or implied
00021 warranty. In no event will the authors be held liable for any damages
00022 arising from the use of this software.
00023 
00024 Permission is granted to anyone to use this software for any purpose,
00025 including commercial applications, and to alter it and redistribute it
00026 freely, subject to the following restrictions:
00027 
00028     1. The origin of this software must not be misrepresented; you must not
00029     claim that you wrote the original software. If you use this software
00030     in a product, an acknowledgment in the product documentation would be
00031     appreciated but is not required.
00032 
00033     2. Altered source versions must be plainly marked as such, and must not be
00034     misrepresented as being the original software.
00035 
00036     3. This notice may not be removed or altered from any source
00037     distribution.
00038 */
00039 
00040 // exclude from faudes html docs  
00041 /** @cond FAUDES_EXCLUDE_DOXYGEN */
00042 
00043 // faudes-style include 
00044 #ifndef FAUDES_TINYTHREAD_H
00045 #define FAUDES_TINYTHREAD_H
00046 
00047 /*
00048 ******************************************************************
00049 ******************************************************************
00050 ******************************************************************
00051 
00052 Original source: "tinythread.h"
00053 
00054 Marginal adjustments signed "tmoor"
00055 
00056 ******************************************************************
00057 ******************************************************************
00058 ******************************************************************
00059 */
00060 
00061 
00062 /// @file
00063 /// @mainpage TinyThread++ API Reference
00064 ///
00065 /// @section intro_sec Introduction
00066 /// TinyThread++ is a minimal, portable implementation of basic threading
00067 /// classes for C++.
00068 ///
00069 /// They closely mimic the functionality and naming of the C++11 standard, and
00070 /// should be easily replaceable with the corresponding std:: variants.
00071 ///
00072 /// @section port_sec Portability
00073 /// The Win32 variant uses the native Win32 API for implementing the thread
00074 /// classes, while for other systems, the POSIX threads API (pthread) is used.
00075 ///
00076 /// @section class_sec Classes
00077 /// In order to mimic the threading API of the C++11 standard, subsets of
00078 /// several classes are provided. The fundamental classes are:
00079 /// @li tthread::thread
00080 /// @li tthread::mutex
00081 /// @li tthread::recursive_mutex
00082 /// @li tthread::condition_variable
00083 /// @li tthread::lock_guard
00084 /// @li tthread::fast_mutex
00085 ///
00086 /// @section misc_sec Miscellaneous
00087 /// The following special keywords are available: #thread_local.
00088 ///
00089 /// For more detailed information (including additional classes), browse the
00090 /// different sections of this documentation. A good place to start is:
00091 /// tinythread.h.
00092 
00093 // Which platform are we on?
00094 #if !defined(_TTHREAD_PLATFORM_DEFINED_)
00095   #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
00096     #define _TTHREAD_WIN32_
00097   #else
00098     #define _TTHREAD_POSIX_
00099   #endif
00100   #define _TTHREAD_PLATFORM_DEFINED_
00101 #endif
00102 
00103 // Platform specific includes
00104 #if defined(_TTHREAD_WIN32_)
00105   #ifndef WIN32_LEAN_AND_MEAN
00106     #define WIN32_LEAN_AND_MEAN
00107     #define __UNDEF_LEAN_AND_MEAN
00108   #endif
00109   #include <windows.h>
00110   #ifdef __UNDEF_LEAN_AND_MEAN
00111     #undef WIN32_LEAN_AND_MEAN
00112     #undef __UNDEF_LEAN_AND_MEAN
00113   #endif
00114 #else
00115   #include <pthread.h>
00116   #include <signal.h>
00117   #include <sched.h>
00118   #include <unistd.h>
00119 #endif
00120 
00121 // Generic includes
00122 #include <ostream>
00123 
00124 /// TinyThread++ version (major number).
00125 #define TINYTHREAD_VERSION_MAJOR 1
00126 /// TinyThread++ version (minor number).
00127 #define TINYTHREAD_VERSION_MINOR 1
00128 /// TinyThread++ version (full version).
00129 #define TINYTHREAD_VERSION (TINYTHREAD_VERSION_MAJOR * 100 + TINYTHREAD_VERSION_MINOR)
00130 
00131 // Do we have a fully featured C++11 compiler?
00132 #if (__cplusplus > 199711L) || (defined(__STDCXX_VERSION__) && (__STDCXX_VERSION__ >= 201001L))
00133   #define _TTHREAD_CPP11_
00134 #endif
00135 
00136 // ...at least partial C++11?
00137 #if defined(_TTHREAD_CPP11_) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__)
00138   #define _TTHREAD_CPP11_PARTIAL_
00139 #endif
00140 
00141 // Macro for disabling assignments of objects.
00142 #ifdef _TTHREAD_CPP11_PARTIAL_
00143   #define _TTHREAD_DISABLE_ASSIGNMENT(name) \
00144       name(const name&) = delete; \
00145       name& operator=(const name&) = delete;
00146 #else
00147   #define _TTHREAD_DISABLE_ASSIGNMENT(name) \
00148       name(const name&); \
00149       name& operator=(const name&);
00150 #endif
00151 
00152 /// @def thread_local
00153 /// Thread local storage keyword.
00154 /// A variable that is declared with the @c thread_local keyword makes the
00155 /// value of the variable local to each thread (known as thread-local storage,
00156 /// or TLS). Example usage:
00157 /// @code
00158 /// // This variable is local to each thread.
00159 /// thread_local int variable;
00160 /// @endcode
00161 /// @note The @c thread_local keyword is a macro that maps to the corresponding
00162 /// compiler directive (e.g. @c __declspec(thread)). While the C++11 standard
00163 /// allows for non-trivial types (e.g. classes with constructors and
00164 /// destructors) to be declared with the @c thread_local keyword, most pre-C++11
00165 /// compilers only allow for trivial types (e.g. @c int). So, to guarantee
00166 /// portable code, only use trivial types for thread local storage.
00167 /// @note This directive is currently not supported on Mac OS X (it will give
00168 /// a compiler error), since compile-time TLS is not supported in the Mac OS X
00169 /// executable format. Also, some older versions of MinGW (before GCC 4.x) do
00170 /// not support this directive.
00171 /// @hideinitializer
00172 
00173 #if !defined(_TTHREAD_CPP11_) && !defined(thread_local)
00174  #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
00175   #define thread_local __thread
00176  #else
00177   #define thread_local __declspec(thread)
00178  #endif
00179 #endif
00180 
00181 
00182 /// Main name space for TinyThread++.
00183 /// This namespace is more or less equivalent to the @c std namespace for the
00184 /// C++11 thread classes. For instance, the tthread::mutex class corresponds to
00185 /// the std::mutex class.
00186 namespace tthread {
00187 
00188 /// Mutex class.
00189 /// This is a mutual exclusion object for synchronizing access to shared
00190 /// memory areas for several threads. The mutex is non-recursive (i.e. a
00191 /// program may deadlock if the thread that owns a mutex object calls lock()
00192 /// on that object).
00193 /// @see recursive_mutex
00194 class mutex {
00195   public:
00196     /// Constructor.
00197     mutex()
00198 #if defined(_TTHREAD_WIN32_)
00199       : mAlreadyLocked(false)
00200 #endif
00201     {
00202 #if defined(_TTHREAD_WIN32_)
00203       InitializeCriticalSection(&mHandle);
00204 #else
00205       pthread_mutex_init(&mHandle, NULL);
00206 #endif
00207     }
00208 
00209     /// Destructor.
00210     ~mutex()
00211     {
00212 #if defined(_TTHREAD_WIN32_)
00213       DeleteCriticalSection(&mHandle);
00214 #else
00215       pthread_mutex_destroy(&mHandle);
00216 #endif
00217     }
00218 
00219     /// Lock the mutex.
00220     /// The method will block the calling thread until a lock on the mutex can
00221     /// be obtained. The mutex remains locked until @c unlock() is called.
00222     /// @see lock_guard
00223     inline void lock()
00224     {
00225 #if defined(_TTHREAD_WIN32_)
00226       EnterCriticalSection(&mHandle);
00227       while(mAlreadyLocked) Sleep(1000); // Simulate deadlock...
00228       mAlreadyLocked = true;
00229 #else
00230       pthread_mutex_lock(&mHandle);
00231 #endif
00232     }
00233 
00234     /// Try to lock the mutex.
00235     /// The method will try to lock the mutex. If it fails, the function will
00236     /// return immediately (non-blocking).
00237     /// @return @c true if the lock was acquired, or @c false if the lock could
00238     /// not be acquired.
00239     inline bool try_lock()
00240     {
00241 #if defined(_TTHREAD_WIN32_)
00242       bool ret = (TryEnterCriticalSection(&mHandle) ? true : false);
00243       if(ret && mAlreadyLocked)
00244       {
00245         LeaveCriticalSection(&mHandle);
00246         ret = false;
00247       }
00248       return ret;
00249 #else
00250       return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
00251 #endif
00252     }
00253 
00254     /// Unlock the mutex.
00255     /// If any threads are waiting for the lock on this mutex, one of them will
00256     /// be unblocked.
00257     inline void unlock()
00258     {
00259 #if defined(_TTHREAD_WIN32_)
00260       mAlreadyLocked = false;
00261       LeaveCriticalSection(&mHandle);
00262 #else
00263       pthread_mutex_unlock(&mHandle);
00264 #endif
00265     }
00266 
00267     _TTHREAD_DISABLE_ASSIGNMENT(mutex)
00268 
00269   private:
00270 #if defined(_TTHREAD_WIN32_)
00271     CRITICAL_SECTION mHandle;
00272     bool mAlreadyLocked;
00273 #else
00274     pthread_mutex_t mHandle;
00275 #endif
00276 
00277     friend class condition_variable;
00278 };
00279 
00280 /// Recursive mutex class.
00281 /// This is a mutual exclusion object for synchronizing access to shared
00282 /// memory areas for several threads. The mutex is recursive (i.e. a thread
00283 /// may lock the mutex several times, as long as it unlocks the mutex the same
00284 /// number of times).
00285 /// @see mutex
00286 class recursive_mutex {
00287   public:
00288     /// Constructor.
00289     recursive_mutex()
00290     {
00291 #if defined(_TTHREAD_WIN32_)
00292       InitializeCriticalSection(&mHandle);
00293 #else
00294       pthread_mutexattr_t attr;
00295       pthread_mutexattr_init(&attr);
00296       pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
00297       pthread_mutex_init(&mHandle, &attr);
00298 #endif
00299     }
00300 
00301     /// Destructor.
00302     ~recursive_mutex()
00303     {
00304 #if defined(_TTHREAD_WIN32_)
00305       DeleteCriticalSection(&mHandle);
00306 #else
00307       pthread_mutex_destroy(&mHandle);
00308 #endif
00309     }
00310 
00311     /// Lock the mutex.
00312     /// The method will block the calling thread until a lock on the mutex can
00313     /// be obtained. The mutex remains locked until @c unlock() is called.
00314     /// @see lock_guard
00315     inline void lock()
00316     {
00317 #if defined(_TTHREAD_WIN32_)
00318       EnterCriticalSection(&mHandle);
00319 #else
00320       pthread_mutex_lock(&mHandle);
00321 #endif
00322     }
00323 
00324     /// Try to lock the mutex.
00325     /// The method will try to lock the mutex. If it fails, the function will
00326     /// return immediately (non-blocking).
00327     /// @return @c true if the lock was acquired, or @c false if the lock could
00328     /// not be acquired.
00329     inline bool try_lock()
00330     {
00331 #if defined(_TTHREAD_WIN32_)
00332       return TryEnterCriticalSection(&mHandle) ? true : false;
00333 #else
00334       return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
00335 #endif
00336     }
00337 
00338     /// Unlock the mutex.
00339     /// If any threads are waiting for the lock on this mutex, one of them will
00340     /// be unblocked.
00341     inline void unlock()
00342     {
00343 #if defined(_TTHREAD_WIN32_)
00344       LeaveCriticalSection(&mHandle);
00345 #else
00346       pthread_mutex_unlock(&mHandle);
00347 #endif
00348     }
00349 
00350     _TTHREAD_DISABLE_ASSIGNMENT(recursive_mutex)
00351 
00352   private:
00353 #if defined(_TTHREAD_WIN32_)
00354     CRITICAL_SECTION mHandle;
00355 #else
00356     pthread_mutex_t mHandle;
00357 #endif
00358 
00359     friend class condition_variable;
00360 };
00361 
00362 /// Lock guard class.
00363 /// The constructor locks the mutex, and the destructor unlocks the mutex, so
00364 /// the mutex will automatically be unlocked when the lock guard goes out of
00365 /// scope. Example usage:
00366 /// @code
00367 /// mutex m;
00368 /// int counter;
00369 ///
00370 /// void increment()
00371 /// {
00372 ///   lock_guard<mutex> guard(m);
00373 ///   ++ counter;
00374 /// }
00375 /// @endcode
00376 
00377 template <class T>
00378 class lock_guard {
00379   public:
00380     typedef T mutex_type;
00381 
00382     lock_guard() : mMutex(0) {}
00383 
00384     /// The constructor locks the mutex.
00385     explicit lock_guard(mutex_type &aMutex)
00386     {
00387       mMutex = &aMutex;
00388       mMutex->lock();
00389     }
00390 
00391     /// The destructor unlocks the mutex.
00392     ~lock_guard()
00393     {
00394       if(mMutex)
00395         mMutex->unlock();
00396     }
00397 
00398   private:
00399     mutex_type * mMutex;
00400 };
00401 
00402 /// Condition variable class.
00403 /// This is a signalling object for synchronizing the execution flow for
00404 /// several threads. Example usage:
00405 /// @code
00406 /// // Shared data and associated mutex and condition variable objects
00407 /// int count;
00408 /// mutex m;
00409 /// condition_variable cond;
00410 ///
00411 /// // Wait for the counter to reach a certain number
00412 /// void wait_counter(int targetCount)
00413 /// {
00414 ///   lock_guard<mutex> guard(m);
00415 ///   while(count < targetCount)
00416 ///     cond.wait(m);
00417 /// }
00418 ///
00419 /// // Increment the counter, and notify waiting threads
00420 /// void increment()
00421 /// {
00422 ///   lock_guard<mutex> guard(m);
00423 ///   ++ count;
00424 ///   cond.notify_all();
00425 /// }
00426 /// @endcode
00427 class condition_variable {
00428   public:
00429     /// Constructor.
00430 #if defined(_TTHREAD_WIN32_)
00431     condition_variable();
00432 #else
00433     condition_variable()
00434     {
00435       pthread_cond_init(&mHandle, NULL);
00436     }
00437 #endif
00438 
00439     /// Destructor.
00440 #if defined(_TTHREAD_WIN32_)
00441     ~condition_variable();
00442 #else
00443     ~condition_variable()
00444     {
00445       pthread_cond_destroy(&mHandle);
00446     }
00447 #endif
00448 
00449     /// Wait for the condition.
00450     /// The function will block the calling thread until the condition variable
00451     /// is woken by @c notify_one(), @c notify_all() or a spurious wake up.
00452     /// @param[in] aMutex A mutex that will be unlocked when the wait operation
00453     ///   starts, an locked again as soon as the wait operation is finished.
00454     template <class _mutexT>
00455     inline void wait(_mutexT &aMutex)
00456     {
00457 #if defined(_TTHREAD_WIN32_)
00458       // Increment number of waiters
00459       EnterCriticalSection(&mWaitersCountLock);
00460       ++ mWaitersCount;
00461       LeaveCriticalSection(&mWaitersCountLock);
00462 
00463       // Release the mutex while waiting for the condition (will decrease
00464       // the number of waiters when done)...
00465       aMutex.unlock();
00466       _wait();
00467       aMutex.lock();
00468 #else
00469       pthread_cond_wait(&mHandle, &aMutex.mHandle);
00470 #endif
00471     }
00472 
00473     /// Notify one thread that is waiting for the condition.
00474     /// If at least one thread is blocked waiting for this condition variable,
00475     /// one will be woken up.
00476     /// @note Only threads that started waiting prior to this call will be
00477     /// woken up.
00478 #if defined(_TTHREAD_WIN32_)
00479     void notify_one();
00480 #else
00481     inline void notify_one()
00482     {
00483       pthread_cond_signal(&mHandle);
00484     }
00485 #endif
00486 
00487     /// Notify all threads that are waiting for the condition.
00488     /// All threads that are blocked waiting for this condition variable will
00489     /// be woken up.
00490     /// @note Only threads that started waiting prior to this call will be
00491     /// woken up.
00492 #if defined(_TTHREAD_WIN32_)
00493     void notify_all();
00494 #else
00495     inline void notify_all()
00496     {
00497       pthread_cond_broadcast(&mHandle);
00498     }
00499 #endif
00500 
00501     _TTHREAD_DISABLE_ASSIGNMENT(condition_variable)
00502 
00503   private:
00504 #if defined(_TTHREAD_WIN32_)
00505     void _wait();
00506     HANDLE mEvents[2];                  ///< Signal and broadcast event HANDLEs.
00507     unsigned int mWaitersCount;         ///< Count of the number of waiters.
00508     CRITICAL_SECTION mWaitersCountLock; ///< Serialize access to mWaitersCount.
00509 #else
00510     pthread_cond_t mHandle;
00511 #endif
00512 };
00513 
00514 
00515 /// Thread class.
00516 class thread {
00517   public:
00518 #if defined(_TTHREAD_WIN32_)
00519     typedef HANDLE native_handle_type;
00520 #else
00521     typedef pthread_t native_handle_type;
00522 #endif
00523 
00524     class id;
00525 
00526     /// Default constructor.
00527     /// Construct a @c thread object without an associated thread of execution
00528     /// (i.e. non-joinable).
00529     thread() : mHandle(0), mNotAThread(true)
00530 #if defined(_TTHREAD_WIN32_)
00531     , mWin32ThreadID(0)
00532 #endif
00533     {}
00534 
00535     /// Thread starting constructor.
00536     /// Construct a @c thread object with a new thread of execution.
00537     /// @param[in] aFunction A function pointer to a function of type:
00538     ///          <tt>void fun(void * arg)</tt>
00539     /// @param[in] aArg Argument to the thread function.
00540     /// @note This constructor is not fully compatible with the standard C++
00541     /// thread class. It is more similar to the pthread_create() (POSIX) and
00542     /// CreateThread() (Windows) functions.
00543     thread(void (*aFunction)(void *), void * aArg);
00544 
00545     /// Destructor.
00546     /// @note If the thread is joinable upon destruction, @c std::terminate()
00547     /// will be called, which terminates the process. It is always wise to do
00548     /// @c join() before deleting a thread object.
00549     ~thread();
00550 
00551     /// Wait for the thread to finish (join execution flows).
00552     /// After calling @c join(), the thread object is no longer associated with
00553     /// a thread of execution (i.e. it is not joinable, and you may not join
00554     /// with it nor detach from it).
00555     void join();
00556 
00557     /// Check if the thread is joinable.
00558     /// A thread object is joinable if it has an associated thread of execution.
00559     bool joinable() const;
00560 
00561     /// Detach from the thread.
00562     /// After calling @c detach(), the thread object is no longer assicated with
00563     /// a thread of execution (i.e. it is not joinable). The thread continues
00564     /// execution without the calling thread blocking, and when the thread
00565     /// ends execution, any owned resources are released.
00566     void detach();
00567 
00568     /// Return the thread ID of a thread object.
00569     id get_id() const;
00570 
00571     /// Get the native handle for this thread.
00572     /// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this
00573     /// is a @c pthread_t.
00574     inline native_handle_type native_handle()
00575     {
00576       return mHandle;
00577     }
00578 
00579     /// Determine the number of threads which can possibly execute concurrently.
00580     /// This function is useful for determining the optimal number of threads to
00581     /// use for a task.
00582     /// @return The number of hardware thread contexts in the system.
00583     /// @note If this value is not defined, the function returns zero (0).
00584     static unsigned hardware_concurrency();
00585 
00586     _TTHREAD_DISABLE_ASSIGNMENT(thread)
00587 
00588   private:
00589     native_handle_type mHandle;   ///< Thread handle.
00590     mutable mutex mDataMutex;     ///< Serializer for access to the thread private data.
00591     bool mNotAThread;             ///< True if this object is not a thread of execution.
00592 #if defined(_TTHREAD_WIN32_)
00593     unsigned int mWin32ThreadID;  ///< Unique thread ID (filled out by _beginthreadex).
00594 #endif
00595 
00596     // This is the internal thread wrapper function.
00597 #if defined(_TTHREAD_WIN32_)
00598     static unsigned WINAPI wrapper_function(void * aArg);
00599 #else
00600     static void * wrapper_function(void * aArg);
00601 #endif
00602 };
00603 
00604 /// Thread ID.
00605 /// The thread ID is a unique identifier for each thread.
00606 /// @see thread::get_id()
00607 class thread::id {
00608   public:
00609     /// Default constructor.
00610     /// The default constructed ID is that of thread without a thread of
00611     /// execution.
00612     id() : mId(0) {};
00613 
00614     id(unsigned long int aId) : mId(aId) {};
00615 
00616     id(const id& aId) : mId(aId.mId) {};
00617 
00618     inline id & operator=(const id &aId)
00619     {
00620       mId = aId.mId;
00621       return *this;
00622     }
00623 
00624     inline friend bool operator==(const id &aId1, const id &aId2)
00625     {
00626       return (aId1.mId == aId2.mId);
00627     }
00628 
00629     inline friend bool operator!=(const id &aId1, const id &aId2)
00630     {
00631       return (aId1.mId != aId2.mId);
00632     }
00633 
00634     inline friend bool operator<=(const id &aId1, const id &aId2)
00635     {
00636       return (aId1.mId <= aId2.mId);
00637     }
00638 
00639     inline friend bool operator<(const id &aId1, const id &aId2)
00640     {
00641       return (aId1.mId < aId2.mId);
00642     }
00643 
00644     inline friend bool operator>=(const id &aId1, const id &aId2)
00645     {
00646       return (aId1.mId >= aId2.mId);
00647     }
00648 
00649     inline friend bool operator>(const id &aId1, const id &aId2)
00650     {
00651       return (aId1.mId > aId2.mId);
00652     }
00653 
00654     inline friend std::ostream& operator <<(std::ostream &os, const id &obj)
00655     {
00656       os << obj.mId;
00657       return os;
00658     }
00659 
00660   private:
00661     unsigned long int mId;
00662 };
00663 
00664 
00665 // Related to <ratio> - minimal to be able to support chrono.
00666 __extension__ typedef long long __intmax_t;  // tmoor:  "extension" for g++/osx/pedantic
00667 
00668 /// Minimal implementation of the @c ratio class. This class provides enough
00669 /// functionality to implement some basic @c chrono classes.
00670 template <__intmax_t N, __intmax_t D = 1> class ratio {
00671   public:
00672     static double _as_double() { return double(N) / double(D); }
00673 };
00674 
00675 /// Minimal implementation of the @c chrono namespace.
00676 /// The @c chrono namespace provides types for specifying time intervals.
00677 namespace chrono {
00678   /// Duration template class. This class provides enough functionality to
00679   /// implement @c this_thread::sleep_for().
00680   template <class _Rep, class _Period = ratio<1> > class duration {
00681     private:
00682       _Rep rep_;
00683     public:
00684       typedef _Rep rep;
00685       typedef _Period period;
00686 
00687       /// Construct a duration object with the given duration.
00688       template <class _Rep2>
00689       explicit duration(const _Rep2& r) : rep_(r) {} // no colon ; ? tmoor
00690    
00691       /// Return the value of the duration object.
00692       rep count() const
00693       {
00694         return rep_;
00695       }
00696   };
00697 
00698   // Standard duration types.
00699   typedef duration<__intmax_t, ratio<1, 1000000000> > nanoseconds; ///< Duration with the unit nanoseconds.
00700   typedef duration<__intmax_t, ratio<1, 1000000> > microseconds;   ///< Duration with the unit microseconds.
00701   typedef duration<__intmax_t, ratio<1, 1000> > milliseconds;      ///< Duration with the unit milliseconds.
00702   typedef duration<__intmax_t> seconds;                            ///< Duration with the unit seconds.
00703   typedef duration<__intmax_t, ratio<60> > minutes;                ///< Duration with the unit minutes.
00704   typedef duration<__intmax_t, ratio<3600> > hours;                ///< Duration with the unit hours.
00705 }
00706 
00707 /// The namespace @c this_thread provides methods for dealing with the
00708 /// calling thread.
00709 namespace this_thread {
00710   /// Return the thread ID of the calling thread.
00711   thread::id get_id();
00712 
00713   /// Yield execution to another thread.
00714   /// Offers the operating system the opportunity to schedule another thread
00715   /// that is ready to run on the current processor.
00716   inline void yield()
00717   {
00718 #if defined(_TTHREAD_WIN32_)
00719     Sleep(0);
00720 #else
00721     sched_yield();
00722 #endif
00723   }
00724 
00725   /// Blocks the calling thread for a period of time.
00726   /// @param[in] aTime Minimum time to put the thread to sleep.
00727   /// Example usage:
00728   /// @code
00729   /// // Sleep for 100 milliseconds
00730   /// this_thread::sleep_for(chrono::milliseconds(100));
00731   /// @endcode
00732   /// @note Supported duration types are: nanoseconds, microseconds,
00733   /// milliseconds, seconds, minutes and hours.
00734   template <class _Rep, class _Period> void sleep_for(const chrono::duration<_Rep, _Period>& aTime)
00735   {
00736 #if defined(_TTHREAD_WIN32_)
00737     Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5));
00738 #else
00739     usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5));
00740 #endif
00741   }
00742 }
00743 
00744 } // end: namespace
00745 
00746 // Define/macro cleanup
00747 #undef _TTHREAD_DISABLE_ASSIGNMENT
00748 
00749 
00750 /*
00751 ******************************************************************
00752 ******************************************************************
00753 ******************************************************************
00754 
00755 Original source: "fast_mutex.h"
00756 
00757 ******************************************************************
00758 ******************************************************************
00759 ******************************************************************
00760 */
00761 
00762 // Check if we can support the assembly language level implementation (otherwise
00763 // revert to the system API)
00764 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || \
00765     (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) || \
00766     (defined(__GNUC__) && (defined(__ppc__)))
00767   #define _FAST_MUTEX_ASM_
00768 #else
00769   #define _FAST_MUTEX_SYS_
00770 #endif
00771 
00772 #if defined(_TTHREAD_WIN32_)
00773   #ifndef WIN32_LEAN_AND_MEAN
00774     #define WIN32_LEAN_AND_MEAN
00775     #define __UNDEF_LEAN_AND_MEAN
00776   #endif
00777   #include <windows.h>
00778   #ifdef __UNDEF_LEAN_AND_MEAN
00779     #undef WIN32_LEAN_AND_MEAN
00780     #undef __UNDEF_LEAN_AND_MEAN
00781   #endif
00782 #else
00783   #ifdef _FAST_MUTEX_ASM_
00784     #include <sched.h>
00785   #else
00786     #include <pthread.h>
00787   #endif
00788 #endif
00789 
00790 namespace tthread {
00791 
00792 /// Fast mutex class.
00793 /// This is a mutual exclusion object for synchronizing access to shared
00794 /// memory areas for several threads. It is similar to the tthread::mutex class,
00795 /// but instead of using system level functions, it is implemented as an atomic
00796 /// spin lock with very low CPU overhead.
00797 ///
00798 /// The \c fast_mutex class is NOT compatible with the \c condition_variable
00799 /// class (however, it IS compatible with the \c lock_guard class). It should
00800 /// also be noted that the \c fast_mutex class typically does not provide
00801 /// as accurate thread scheduling as a the standard \c mutex class does.
00802 ///
00803 /// Because of the limitations of the class, it should only be used in
00804 /// situations where the mutex needs to be locked/unlocked very frequently.
00805 ///
00806 /// @note The "fast" version of this class relies on inline assembler language,
00807 /// which is currently only supported for 32/64-bit Intel x86/AMD64 and
00808 /// PowerPC architectures on a limited number of compilers (GNU g++ and MS
00809 /// Visual C++).
00810 /// For other architectures/compilers, system functions are used instead.
00811 class fast_mutex {
00812   public:
00813     /// Constructor.
00814 #if defined(_FAST_MUTEX_ASM_)
00815     fast_mutex() : mLock(0) {}
00816 #else
00817     fast_mutex()
00818     {
00819   #if defined(_TTHREAD_WIN32_)
00820       InitializeCriticalSection(&mHandle);
00821   #elif defined(_TTHREAD_POSIX_)
00822       pthread_mutex_init(&mHandle, NULL);
00823   #endif
00824     }
00825 #endif
00826 
00827 #if !defined(_FAST_MUTEX_ASM_)
00828     /// Destructor.
00829     ~fast_mutex()
00830     {
00831   #if defined(_TTHREAD_WIN32_)
00832       DeleteCriticalSection(&mHandle);
00833   #elif defined(_TTHREAD_POSIX_)
00834       pthread_mutex_destroy(&mHandle);
00835   #endif
00836     }
00837 #endif
00838 
00839     /// Lock the mutex.
00840     /// The method will block the calling thread until a lock on the mutex can
00841     /// be obtained. The mutex remains locked until \c unlock() is called.
00842     /// @see lock_guard
00843     inline void lock()
00844     {
00845 #if defined(_FAST_MUTEX_ASM_)
00846       bool gotLock;
00847       do {
00848         gotLock = try_lock();
00849         if(!gotLock)
00850         {
00851   #if defined(_TTHREAD_WIN32_)
00852           Sleep(0);
00853   #elif defined(_TTHREAD_POSIX_)
00854           sched_yield();
00855   #endif
00856         }
00857       } while(!gotLock);
00858 #else
00859   #if defined(_TTHREAD_WIN32_)
00860       EnterCriticalSection(&mHandle);
00861   #elif defined(_TTHREAD_POSIX_)
00862       pthread_mutex_lock(&mHandle);
00863   #endif
00864 #endif
00865     }
00866 
00867     /// Try to lock the mutex.
00868     /// The method will try to lock the mutex. If it fails, the function will
00869     /// return immediately (non-blocking).
00870     /// @return \c true if the lock was acquired, or \c false if the lock could
00871     /// not be acquired.
00872     inline bool try_lock()
00873     {
00874 #if defined(_FAST_MUTEX_ASM_)
00875       int oldLock;
00876   #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
00877       asm volatile (
00878         "movl $1,%%eax\n\t"
00879         "xchg %%eax,%0\n\t"
00880         "movl %%eax,%1\n\t"
00881         : "=m" (mLock), "=m" (oldLock)
00882         :
00883         : "%eax", "memory"
00884       );
00885   #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
00886       int *ptrLock = &mLock;
00887       __asm {
00888         mov eax,1
00889         mov ecx,ptrLock
00890         xchg eax,[ecx]
00891         mov oldLock,eax
00892       }
00893   #elif defined(__GNUC__) && (defined(__ppc__))
00894       int newLock = 1;
00895       asm volatile (
00896         "\n1:\n\t"
00897         "lwarx  %0,0,%1\n\t"
00898         "cmpwi  0,%0,0\n\t"
00899         "bne-   2f\n\t"
00900         "stwcx. %2,0,%1\n\t"
00901         "bne-   1b\n\t"
00902         "isync\n"
00903         "2:\n\t"
00904         : "=&r" (oldLock)
00905         : "r" (&mLock), "r" (newLock)
00906         : "cr0", "memory"
00907       );
00908   #endif
00909       return (oldLock == 0);
00910 #else
00911   #if defined(_TTHREAD_WIN32_)
00912       return TryEnterCriticalSection(&mHandle) ? true : false;
00913   #elif defined(_TTHREAD_POSIX_)
00914       return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
00915   #endif
00916 #endif
00917     }
00918 
00919     /// Unlock the mutex.
00920     /// If any threads are waiting for the lock on this mutex, one of them will
00921     /// be unblocked.
00922     inline void unlock()
00923     {
00924 #if defined(_FAST_MUTEX_ASM_)
00925   #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
00926       asm volatile (
00927         "movl $0,%%eax\n\t"
00928         "xchg %%eax,%0\n\t"
00929         : "=m" (mLock)
00930         :
00931         : "%eax", "memory"
00932       );
00933   #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
00934       int *ptrLock = &mLock;
00935       __asm {
00936         mov eax,0
00937         mov ecx,ptrLock
00938         xchg eax,[ecx]
00939       }
00940   #elif defined(__GNUC__) && (defined(__ppc__))
00941       asm volatile (
00942         "sync\n\t"  // Replace with lwsync where possible?
00943         : : : "memory"
00944       );
00945       mLock = 0;
00946   #endif
00947 #else
00948   #if defined(_TTHREAD_WIN32_)
00949       LeaveCriticalSection(&mHandle);
00950   #elif defined(_TTHREAD_POSIX_)
00951       pthread_mutex_unlock(&mHandle);
00952   #endif
00953 #endif
00954     }
00955 
00956   private:
00957 #if defined(_FAST_MUTEX_ASM_)
00958     int mLock;
00959 #else
00960   #if defined(_TTHREAD_WIN32_)
00961     CRITICAL_SECTION mHandle;
00962   #elif defined(_TTHREAD_POSIX_)
00963     pthread_mutex_t mHandle;
00964   #endif
00965 #endif
00966 };
00967 
00968 } // end: namespace
00969 
00970 
00971 #endif // FAUDES_TINYTHREAD_H // tmoor
00972 
00973 // exclude from faudes html docs  
00974 /** @endcond  */
00975 

libFAUDES 2.22k --- 2013.04.02 --- c++ source docu by doxygen