MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
thread.h
Go to the documentation of this file.
1 // The DAGFrameScheduler is a Multi-Threaded lock free and wait free scheduling library.
2 // © Copyright 2010 - 2014 BlackTopp Studios Inc.
3 /* This file is part of The DAGFrameScheduler.
4 
5  The DAGFrameScheduler is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  The DAGFrameScheduler is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with The DAGFrameScheduler. If not, see <http://www.gnu.org/licenses/>.
17 */
18 /* The original authors have included a copy of the license specified above in the
19  'doc' folder. See 'gpl.txt'
20 */
21 /* We welcome the use of the DAGFrameScheduler to anyone, including companies who wish to
22  Build professional software and charge for their product.
23 
24  However there are some practical restrictions, so if your project involves
25  any of the following you should contact us and we will try to work something
26  out:
27  - DRM or Copy Protection of any kind(except Copyrights)
28  - Software Patents You Do Not Wish to Freely License
29  - Any Kind of Linking to Non-GPL licensed Works
30  - Are Currently In Violation of Another Copyright Holder's GPL License
31  - If You want to change our code and not add a few hundred MB of stuff to
32  your distribution
33 
34  These and other limitations could cause serious legal problems if you ignore
35  them, so it is best to simply contact us or the Free Software Foundation, if
36  you have any questions.
37 
38  Joseph Toppi - toppij@gmail.com
39  John Blackwood - makoenergy02@gmail.com
40 */
41 #ifndef _btsthread_h
42 #define _btsthread_h
43 
44 /// @file
45 /// @brief This file defines a minimalistic cross-platform thread that the scheduler uses to schedule tasks.
46 
47 // Parts of this library use the TinyThread++ libary and those parts are also covered by the following license
48 /*
49 Copyright (c) 2010-2012 Marcus Geelnard
50 
51 This software is provided 'as-is', without any express or implied
52 warranty. In no event will the authors be held liable for any damages
53 arising from the use of this software.
54 
55 Permission is granted to anyone to use this software for any purpose,
56 including commercial applications, and to alter it and redistribute it
57 freely, subject to the following restrictions:
58 
59  1. The origin of this software must not be misrepresented; you must not
60  claim that you wrote the original software. If you use this software
61  in a product, an acknowledgment in the product documentation would be
62  appreciated but is not required.
63 
64  2. Altered source versions must be plainly marked as such, and must not be
65  misrepresented as being the original software.
66 
67  3. This notice may not be removed or altered from any source
68  distribution.
69 */
70 
71 #if !defined(SWIG) || defined(SWIG_THREADING) // Do not read when in swig and not in the threading module
72 #include "systemcalls.h"
73 #include "mutex.h"
74 #endif
75 
76 namespace Mezzanine
77 {
78  namespace Threading
79  {
80  // Forward Declaration
81  class ThreadId;
82 
83  /// @brief A small wrapper around the system thread.
84  /// @details In general game code should not be creating this if they are using the
85  /// DAG Frame Scheduler, as it tries to maintain control over the threads created
86  /// by a game. This tries to keep the names the same as the standard thread, and might
87  /// at some point be replace by some template machinery that wraps the minor difference
88  /// that currently exist.
90  {
91  public:
92  #if defined(_MEZZ_THREAD_WIN32_)
93  /// @typedef HANDLE
94  /// @brief Currently windows defines this to be a void pointer. This might have to be adjusted in the future.
95  typedef void* HANDLE;
96  #endif
97 
98  /// @typedef native_handle_type
99  /// @brief The native handle type, made available with requiring specific knowledge of whether it is a posix or win32 handle.
100  #if defined(_MEZZ_THREAD_WIN32_)
101  typedef HANDLE native_handle_type;
102  #else
103  typedef pthread_t native_handle_type;
104  #endif
105 
106  /// @brief Default constructor.
107  /// @details Construct a @c thread object without an associated thread of execution
108  /// (i.e. non-joinable).
109  Thread() : mHandle(0), mNotAThread(true)
110  #if defined(_MEZZ_WIN32_)
111  , mWin32ThreadID(0)
112  #endif
113  {}
114 
115  /// @brief Thread starting constructor with no parameters.
116  /// @note May work in templates that do not attempt to pass values to threads, but not standard conformant.
117  /// @param[in] aFunction A function pointer to a function of type:
118  /// @code void fun(void * arg) @endcode
119  explicit Thread(void (*aFunction)(void *));
120 
121  /// @brief Thread starting constructor.
122  /// @details Construct a @c thread object with a new thread of execution.
123  /// @param[in] aFunction A function pointer to a function of type:
124  /// @code void fun(void * arg) @endcode
125  /// @param[in] aArg Argument to the thread function.
126  /// @note This constructor is not fully compatible with the standard C++
127  /// thread class. It is more similar to the pthread_create() (POSIX) and
128  /// CreateThread() (Windows) functions.
129  Thread(void (*aFunction)(void *), void * aArg);
130 
131  /// @brief Destructor.
132  /// @note If the thread is joinable upon destruction, @c std::terminate()
133  /// will be called, which terminates the process. It is always wise to do
134  /// @c join() before deleting a thread object.
135  ~Thread();
136 
137  /// @brief Wait for the thread to finish (join execution flows).
138  /// @details After calling @c join(), the thread object is no longer associated with
139  /// a thread of execution (i.e. it is not joinable, and you may not join
140  /// with it nor detach from it).
141  void join();
142 
143  /// @brief Check if the thread is joinable.
144  /// @details A thread object is joinable if it has an associated thread of execution.
145  /// @return A bool, false if the thread has been detached, joined or otherwise made unjoinable by exceptional circumstances, true otherwise.
146  bool joinable() const;
147 
148  /// @brief Detach from the thread.
149  /// @details After calling @c detach(), the thread object is no longer assicated with
150  /// a thread of execution (i.e. it is not joinable). The thread continues
151  /// execution without the calling thread blocking, and when the thread
152  /// ends execution, any owned resources are released.
153  void detach();
154 
155  /// @brief Return the thread ID of a thread object.
156  /// @return A platform specific handle for the thread.
157  ThreadId get_id() const;
158 
159  /// @brief Get the native handle for this thread.
160  /// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this is a @c pthread_t.
161  /// @return The native handle for the thread in case it is desired to use it with OS APIs.
163  { return mHandle; }
164 
165  /// @brief Determine the number of threads which can possibly execute concurrently.
166  /// @details This function is useful for determining the optimal number of threads to
167  /// use for a task.
168  /// @return The number of hardware thread contexts in the system.
169  /// @note If this value is not defined, the function returns zero (0).
170  static unsigned hardware_concurrency();
171 
172  private:
173  /// @brief Deleted assignment operator.
174  #ifdef _MEZZ_CPP11_PARTIAL_
175  Thread& operator=(const Thread&) = delete;
176  #else
177  Thread& operator=(const Thread&);
178  #endif
179 
180  /// @brief Deleted assignment operator copy constructor.
181  #ifdef _MEZZ_CPP11_PARTIAL_
182  Thread(const Thread&) = delete;
183  #else
184  Thread(const Thread&);
185  #endif
186 
187 
188  native_handle_type mHandle; ///< Thread handle.
189  mutable Mutex mDataMutex; ///< Serializer for access to the thread private data.
190  bool mNotAThread; ///< True if this object is not a thread of execution.
191  #if defined(_MEZZ_THREAD_WIN32_)
192  unsigned int mWin32ThreadID; ///< Unique thread ID (filled out by _beginthreadex).
193  #endif
194 
195  #if defined(_MEZZ_THREAD_WIN32_)
196  /// @brief This is the internal thread wrapper function.
197  static unsigned WINAPI wrapper_function(void * aArg);
198  #else
199  /// @brief This is the internal thread wrapper function.
200  static void * wrapper_function(void * aArg);
201  #endif
202  };//Thread
203 
204  /// @brief The thread ID is a unique identifier for each thread.
205  /// @see thread::get_id()
207  {
208  public:
209  /// @brief Default constructor.
210  /// @details The default constructed ID is that of thread without a thread of
211  /// execution.
212  ThreadId() : mId(0)
213  {}
214 
215  /// @brief Creation from long.
216  /// @param aId The OS provided long to create an ID from.
217  ThreadId(unsigned long int aId) : mId(aId)
218  {}
219 
220  /// @brief Copy constructor.
221  /// @param aId The other id to create a copy of.
222  ThreadId(const ThreadId& aId) : mId(aId.mId)
223  {}
224 
225  /// @brief Assignment Operator.
226  /// @param aId The right hand operand during assignment.
227  /// @return A reference to the left hand operand after it has been assigned.
228  inline ThreadId & operator=(const ThreadId &aId)
229  {
230  mId = aId.mId;
231  return *this;
232  }
233 
234  /// @brief Equality Comparison.
235  /// @param aId1 Left hand operand.
236  /// @param aId2 Right hand operand.
237  /// @returns True boolean value if the OS specific IDs match and false otherwise.
238  inline friend bool operator==(const ThreadId &aId1, const ThreadId &aId2)
239  { return (aId1.mId == aId2.mId); }
240 
241  /// @brief Inequality Comparison.
242  /// @param aId1 Left hand operand.
243  /// @param aId2 Right hand operand.
244  /// @returns False boolean value if the OS specific IDs match and true otherwise.
245  inline friend bool operator!=(const ThreadId &aId1, const ThreadId &aId2)
246  { return (aId1.mId != aId2.mId); }
247 
248  /// @brief Greater than or equal to Comparison.
249  /// @param aId1 Left hand operand.
250  /// @param aId2 Right hand operand.
251  /// @returns A consistent value to allow for sorting/ordering of threads.
252  inline friend bool operator<=(const ThreadId &aId1, const ThreadId &aId2)
253  { return (aId1.mId <= aId2.mId); }
254 
255  /// @brief Greater than Comparison.
256  /// @param aId1 Left hand operand.
257  /// @param aId2 Right hand operand.
258  /// @returns A consistent value to allow for sorting/ordering of threads.
259  inline friend bool operator<(const ThreadId &aId1, const ThreadId &aId2)
260  { return (aId1.mId < aId2.mId); }
261 
262  /// @brief Less than or equal to Comparison.
263  /// @param aId1 Left hand operand.
264  /// @param aId2 Right hand operand.
265  /// @returns A consistent value to allow for sorting/ordering of threads.
266  inline friend bool operator>=(const ThreadId &aId1, const ThreadId &aId2)
267  { return (aId1.mId >= aId2.mId); }
268 
269  /// @brief Less than Comparison.
270  /// @param aId1 Left hand operand.
271  /// @param aId2 Right hand operand.
272  /// @returns A consistent value to allow for sorting/ordering of threads.
273  inline friend bool operator>(const ThreadId &aId1, const ThreadId &aId2)
274  { return (aId1.mId > aId2.mId); }
275 
276  #ifndef SWIG
277  /// @brief Output Streaming operator.
278  /// @param os The output stream to send the id into.
279  /// @param obj the streamed id.
280  /// @returns A reference to the output stream to allow for operator chaining.
281  inline friend std::ostream& operator <<(std::ostream &os, const ThreadId &obj)
282  {
283  os << obj.mId;
284  return os;
285  }
286  #endif
287 
288  private:
289  /// @internal
290  /// @brief The ID value
291  unsigned long int mId;
292  };//Thread::id
293 
294  /// @brief A partial implementation of std::thread::this_thread.
295  namespace this_thread
296  {
297  /// @brief Return the thread ID of the calling thread.
298  /// @return A thread::id unique to this thread.
300 
301  /// @brief Yield execution to another thread.
302  /// @details Offers the operating system the opportunity to schedule another thread
303  /// that is ready to run on the current processor.
304  void MEZZ_LIB yield();
305 
306  /// @brief Blocks the calling thread for a period of time.
307  /// @param MicroSeconds Minimum time to put the thread to sleep.
308  void MEZZ_LIB sleep_for(UInt32 MicroSeconds);
309 
310  } // namespace this_thread
311  }//Threading
312 }//Mezzanine
313 
314 #endif