1 /**
2  * @file concurrency.h
3  * Concurrency: threads, mutexes, semaphores.
4  *
5  * @authors Copyright © 2003-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
6  * @authors Copyright © 2006-2013 Daniel Swanson <danij@dengine.net>
7  * @authors Copyright © 2006 Jamie Jones <jamie_jones_au@yahoo.com.au>
8  *
9  * @par License
10  * GPL: http://www.gnu.org/licenses/gpl.html
11  *
12  * <small>This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by the
14  * Free Software Foundation; either version 2 of the License, or (at your
15  * option) any later version. This program is distributed in the hope that it
16  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
17  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
18  * Public License for more details. You should have received a copy of the GNU
19  * General Public License along with this program; if not, write to the Free
20  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA</small>
22  */
23 
24 #ifndef LIBDENG_SYSTEM_CONCURRENCY_H
25 #define LIBDENG_SYSTEM_CONCURRENCY_H
26 
27 #include <de/liblegacy.h>
28 
29 /// @addtogroup legacy
30 /// @{
31 
32 typedef void *thread_t;
33 typedef void *mutex_t;
34 //typedef void *sem_t;
35 
36 typedef enum systhreadexitstatus_e {
37     DENG_THREAD_STOPPED_NORMALLY,
38     DENG_THREAD_STOPPED_WITH_FORCE, // terminated
39     DENG_THREAD_STOPPED_WITH_EXCEPTION
40 } systhreadexitstatus_t;
41 
42 #ifdef __cplusplus
43 
44 #include <functional>
45 typedef std::function<int (void *)> systhreadfunc_t;
46 
47 #ifdef __DENG__ // libdeng internal
48 #include <QThread>
49 /**
50  * Thread that runs a user-specified callback function. Exceptions from the callback
51  * function are caught.
52  */
53 class CallbackThread : public QThread
54 {
55     Q_OBJECT
56 
57 public:
58     CallbackThread(systhreadfunc_t func, void *parm = 0);
59     ~CallbackThread();
60 
61     void run();
62     int exitValue() const;
63     systhreadexitstatus_t exitStatus() const;
64     void setTerminationFunc(void (*func)(systhreadexitstatus_t));
65 
66 protected slots:
67     void deleteNow();
68 
69 private:
70     systhreadfunc_t _callback;
71     void *_parm;
72     int _returnValue;
73     systhreadexitstatus_t _exitStatus;
74     void (*_terminationFunc)(systhreadexitstatus_t);
75 };
76 
77 #endif // __DENG__
78 
79 /**
80  * Starts a new thread.
81  *
82  * @param startpos  Executes while the thread is running. When the function exists,
83  *                  the thread stops.
84  * @param parm             Parameter given to the thread function.
85  * @param terminationFunc  Callback function that is called from the worker thread
86  *                         right before it exits. The callback is given the exit status
87  *                         of the thread as a parameter.
88  * @return Thread handle.
89  */
90 DENG_PUBLIC thread_t Sys_StartThread(systhreadfunc_t startpos, void *parm,
91                                      void (*terminationFunc)(systhreadexitstatus_t));
92 
93 extern "C" {
94 #endif // __cplusplus
95 
96 /**
97  * @def DENG_ASSERT_IN_MAIN_THREAD
98  * In a debug build, this asserts that the current code is executing in the main thread.
99  */
100 #define DENG_ASSERT_IN_MAIN_THREAD()   DENG2_ASSERT_IN_MAIN_THREAD()
101 
102 /**
103  * Starts a new thread.
104  *
105  * @param startpos  Executes while the thread is running. When the function exists,
106  *                  the thread stops.
107  * @param parm             Parameter given to the thread function.
108  * @param terminationFunc  Callback function that is called from the worker thread
109  *                         right before it exits. The callback is given the exit status
110  *                         of the thread as a parameter.
111  * @return Thread handle.
112  */
113 DENG_PUBLIC thread_t Sys_StartThread(int (*startpos)(void *), void *parm,
114                                      void (*terminationFunc)(systhreadexitstatus_t));
115 
116 DENG_PUBLIC void Thread_Sleep(int milliseconds);
117 
118 DENG_PUBLIC void Thread_KillAbnormally(thread_t handle);
119 
120 /**
121  * Wait for a thread to stop. If the thread does not stop after @a timeoutMs,
122  * it will be forcibly terminated.
123  *
124  * @param handle      Thread handle.
125  * @param timeoutMs   How long to wait until the thread terminates.
126  * @param exitStatus  If not @c NULL, the exit status is returned here.
127  *                    @c true for normal exit, @c false if exception was caught.
128  *
129  * @return  Return value of the thread.
130  */
131 DENG_PUBLIC int Sys_WaitThread(thread_t handle, int timeoutMs, systhreadexitstatus_t *exitStatus);
132 
133 /**
134  * @param handle  Handle to the thread to return the id of.
135  *                Can be @c NULL in which case the current thread is assumed.
136  * @return  Identifier of the thread.
137  */
138 DENG_PUBLIC uint32_t Sys_ThreadId(thread_t handle);
139 
140 DENG_PUBLIC uint32_t Sys_CurrentThreadId(void);
141 
142 DENG_PUBLIC dd_bool Sys_InMainThread(void);
143 
144 DENG_PUBLIC mutex_t Sys_CreateMutex(char const *name);
145 
146 DENG_PUBLIC void Sys_DestroyMutex(mutex_t mutexHandle);
147 
148 DENG_PUBLIC void Sys_Lock(mutex_t mutexHandle);
149 
150 DENG_PUBLIC void Sys_Unlock(mutex_t mutexHandle);
151 
152 #if 0
153 /// @todo update these if/when needed
154 sem_t Sem_Create(uint32_t initialValue);
155 void Sem_Destroy(sem_t semaphore);
156 void Sem_P(sem_t semaphore);
157 void Sem_V(sem_t semaphore);
158 #endif
159 
160 /// @}
161 
162 #ifdef __cplusplus
163 } // extern "C"
164 #endif
165 
166 #endif // LIBDENG_SYSTEM_CONCURRENCY_H
167