From c1844e2ee9dd07888301a8d1fe632c3c668f4356 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Sat, 6 Apr 2013 17:16:09 +0200 Subject: [PATCH] Updated tinythread to 1.1 --- src/tinythread.cpp | 22 ++++++-- src/tinythread.h | 128 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 118 insertions(+), 32 deletions(-) diff --git a/src/tinythread.cpp b/src/tinythread.cpp index eb2dce0e..690eceea 100644 --- a/src/tinythread.cpp +++ b/src/tinythread.cpp @@ -1,5 +1,5 @@ -/* -Copyright (c) 2010 Marcus Geelnard +/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- +Copyright (c) 2010-2012 Marcus Geelnard This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -171,7 +171,7 @@ void * thread::wrapper_function(void * aArg) catch(...) { // Uncaught exceptions will terminate the application (default behavior - // according to the C++0x draft) + // according to C++11) std::terminate(); } @@ -228,6 +228,7 @@ void thread::join() { #if defined(_TTHREAD_WIN32_) WaitForSingleObject(mHandle, INFINITE); + CloseHandle(mHandle); #elif defined(_TTHREAD_POSIX_) pthread_join(mHandle, NULL); #endif @@ -242,6 +243,21 @@ bool thread::joinable() const return result; } +void thread::detach() +{ + mDataMutex.lock(); + if(!mNotAThread) + { +#if defined(_TTHREAD_WIN32_) + CloseHandle(mHandle); +#elif defined(_TTHREAD_POSIX_) + pthread_detach(mHandle); +#endif + mNotAThread = true; + } + mDataMutex.unlock(); +} + thread::id thread::get_id() const { if(!joinable()) diff --git a/src/tinythread.h b/src/tinythread.h index 494e1ec4..aed7b585 100644 --- a/src/tinythread.h +++ b/src/tinythread.h @@ -1,5 +1,5 @@ -/* -Copyright (c) 2010 Marcus Geelnard +/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- +Copyright (c) 2010-2012 Marcus Geelnard This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -24,6 +24,37 @@ freely, subject to the following restrictions: #ifndef _TINYTHREAD_H_ #define _TINYTHREAD_H_ +/// @file +/// @mainpage TinyThread++ API Reference +/// +/// @section intro_sec Introduction +/// TinyThread++ is a minimal, portable implementation of basic threading +/// classes for C++. +/// +/// They closely mimic the functionality and naming of the C++11 standard, and +/// should be easily replaceable with the corresponding std:: variants. +/// +/// @section port_sec Portability +/// The Win32 variant uses the native Win32 API for implementing the thread +/// classes, while for other systems, the POSIX threads API (pthread) is used. +/// +/// @section class_sec Classes +/// In order to mimic the threading API of the C++11 standard, subsets of +/// several classes are provided. The fundamental classes are: +/// @li tthread::thread +/// @li tthread::mutex +/// @li tthread::recursive_mutex +/// @li tthread::condition_variable +/// @li tthread::lock_guard +/// @li tthread::fast_mutex +/// +/// @section misc_sec Miscellaneous +/// The following special keywords are available: #thread_local. +/// +/// For more detailed information (including additional classes), browse the +/// different sections of this documentation. A good place to start is: +/// tinythread.h. + // Which platform are we on? #if !defined(_TTHREAD_PLATFORM_DEFINED_) #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) @@ -36,7 +67,15 @@ freely, subject to the following restrictions: // Platform specific includes #if defined(_TTHREAD_WIN32_) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #define __UNDEF_LEAN_AND_MEAN + #endif #include + #ifdef __UNDEF_LEAN_AND_MEAN + #undef WIN32_LEAN_AND_MEAN + #undef __UNDEF_LEAN_AND_MEAN + #endif #else #include #include @@ -50,22 +89,22 @@ freely, subject to the following restrictions: /// TinyThread++ version (major number). #define TINYTHREAD_VERSION_MAJOR 1 /// TinyThread++ version (minor number). -#define TINYTHREAD_VERSION_MINOR 0 +#define TINYTHREAD_VERSION_MINOR 1 /// TinyThread++ version (full version). #define TINYTHREAD_VERSION (TINYTHREAD_VERSION_MAJOR * 100 + TINYTHREAD_VERSION_MINOR) -// Do we have a fully featured C++0x compiler? +// Do we have a fully featured C++11 compiler? #if (__cplusplus > 199711L) || (defined(__STDCXX_VERSION__) && (__STDCXX_VERSION__ >= 201001L)) - #define _TTHREAD_CPP0X_ + #define _TTHREAD_CPP11_ #endif -// ...at least partial C++0x? -#if defined(_TTHREAD_CPP0X_) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__) - #define _TTHREAD_CPP0X_PARTIAL_ +// ...at least partial C++11? +#if defined(_TTHREAD_CPP11_) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__) + #define _TTHREAD_CPP11_PARTIAL_ #endif // Macro for disabling assignments of objects. -#ifdef _TTHREAD_CPP0X_PARTIAL_ +#ifdef _TTHREAD_CPP11_PARTIAL_ #define _TTHREAD_DISABLE_ASSIGNMENT(name) \ name(const name&) = delete; \ name& operator=(const name&) = delete; @@ -75,7 +114,28 @@ freely, subject to the following restrictions: name& operator=(const name&); #endif -#if !defined(_TTHREAD_CPP0X_) && !defined(thread_local) +/// @def thread_local +/// Thread local storage keyword. +/// A variable that is declared with the @c thread_local keyword makes the +/// value of the variable local to each thread (known as thread-local storage, +/// or TLS). Example usage: +/// @code +/// // This variable is local to each thread. +/// thread_local int variable; +/// @endcode +/// @note The @c thread_local keyword is a macro that maps to the corresponding +/// compiler directive (e.g. @c __declspec(thread)). While the C++11 standard +/// allows for non-trivial types (e.g. classes with constructors and +/// destructors) to be declared with the @c thread_local keyword, most pre-C++11 +/// compilers only allow for trivial types (e.g. @c int). So, to guarantee +/// portable code, only use trivial types for thread local storage. +/// @note This directive is currently not supported on Mac OS X (it will give +/// a compiler error), since compile-time TLS is not supported in the Mac OS X +/// executable format. Also, some older versions of MinGW (before GCC 4.x) do +/// not support this directive. +/// @hideinitializer + +#if !defined(_TTHREAD_CPP11_) && !defined(thread_local) #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__) #define thread_local __thread #else @@ -85,8 +145,8 @@ freely, subject to the following restrictions: /// Main name space for TinyThread++. -/// This namespace is more or less equivalent to the \c std namespace for the -/// C++0x thread classes. For instance, the tthread::mutex class corresponds to +/// This namespace is more or less equivalent to the @c std namespace for the +/// C++11 thread classes. For instance, the tthread::mutex class corresponds to /// the std::mutex class. namespace tthread { @@ -123,7 +183,7 @@ class mutex { /// Lock the mutex. /// The method will block the calling thread until a lock on the mutex can - /// be obtained. The mutex remains locked until \c unlock() is called. + /// be obtained. The mutex remains locked until @c unlock() is called. /// @see lock_guard inline void lock() { @@ -139,7 +199,7 @@ class mutex { /// Try to lock the mutex. /// The method will try to lock the mutex. If it fails, the function will /// return immediately (non-blocking). - /// @return \c true if the lock was acquired, or \c false if the lock could + /// @return @c true if the lock was acquired, or @c false if the lock could /// not be acquired. inline bool try_lock() { @@ -215,7 +275,7 @@ class recursive_mutex { /// Lock the mutex. /// The method will block the calling thread until a lock on the mutex can - /// be obtained. The mutex remains locked until \c unlock() is called. + /// be obtained. The mutex remains locked until @c unlock() is called. /// @see lock_guard inline void lock() { @@ -229,7 +289,7 @@ class recursive_mutex { /// Try to lock the mutex. /// The method will try to lock the mutex. If it fails, the function will /// return immediately (non-blocking). - /// @return \c true if the lock was acquired, or \c false if the lock could + /// @return @c true if the lock was acquired, or @c false if the lock could /// not be acquired. inline bool try_lock() { @@ -353,7 +413,7 @@ class condition_variable { /// Wait for the condition. /// The function will block the calling thread until the condition variable - /// is woken by \c notify_one(), \c notify_all() or a spurious wake up. + /// is woken by @c notify_one(), @c notify_all() or a spurious wake up. /// @param[in] aMutex A mutex that will be unlocked when the wait operation /// starts, an locked again as soon as the wait operation is finished. template @@ -429,7 +489,7 @@ class thread { class id; /// Default constructor. - /// Construct a \c thread object without an associated thread of execution + /// Construct a @c thread object without an associated thread of execution /// (i.e. non-joinable). thread() : mHandle(0), mNotAThread(true) #if defined(_TTHREAD_WIN32_) @@ -438,7 +498,7 @@ class thread { {} /// Thread starting constructor. - /// Construct a \c thread object with a new thread of execution. + /// Construct a @c thread object with a new thread of execution. /// @param[in] aFunction A function pointer to a function of type: /// void fun(void * arg) /// @param[in] aArg Argument to the thread function. @@ -448,24 +508,34 @@ class thread { thread(void (*aFunction)(void *), void * aArg); /// Destructor. - /// @note If the thread is joinable upon destruction, \c std::terminate() + /// @note If the thread is joinable upon destruction, @c std::terminate() /// will be called, which terminates the process. It is always wise to do - /// \c join() before deleting a thread object. + /// @c join() before deleting a thread object. ~thread(); /// Wait for the thread to finish (join execution flows). + /// After calling @c join(), the thread object is no longer associated with + /// a thread of execution (i.e. it is not joinable, and you may not join + /// with it nor detach from it). void join(); /// Check if the thread is joinable. /// A thread object is joinable if it has an associated thread of execution. bool joinable() const; + /// Detach from the thread. + /// After calling @c detach(), the thread object is no longer assicated with + /// a thread of execution (i.e. it is not joinable). The thread continues + /// execution without the calling thread blocking, and when the thread + /// ends execution, any owned resources are released. + void detach(); + /// Return the thread ID of a thread object. id get_id() const; /// Get the native handle for this thread. - /// @note Under Windows, this is a \c HANDLE, and under POSIX systems, this - /// is a \c pthread_t. + /// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this + /// is a @c pthread_t. inline native_handle_type native_handle() { return mHandle; @@ -560,18 +630,18 @@ class thread::id { // Related to - minimal to be able to support chrono. typedef long long __intmax_t; -/// Minimal implementation of the \c ratio class. This class provides enough -/// functionality to implement some basic \c chrono classes. +/// Minimal implementation of the @c ratio class. This class provides enough +/// functionality to implement some basic @c chrono classes. template <__intmax_t N, __intmax_t D = 1> class ratio { public: static double _as_double() { return double(N) / double(D); } }; -/// Minimal implementation of the \c chrono namespace. -/// The \c chrono namespace provides types for specifying time intervals. +/// Minimal implementation of the @c chrono namespace. +/// The @c chrono namespace provides types for specifying time intervals. namespace chrono { /// Duration template class. This class provides enough functionality to - /// implement \c this_thread::sleep_for(). + /// implement @c this_thread::sleep_for(). template > class duration { private: _Rep rep_; @@ -599,7 +669,7 @@ namespace chrono { typedef duration<__intmax_t, ratio<3600> > hours; ///< Duration with the unit hours. } -/// The namespace \c this_thread provides methods for dealing with the +/// The namespace @c this_thread provides methods for dealing with the /// calling thread. namespace this_thread { /// Return the thread ID of the calling thread.