3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005 - 2011 Christian Schoenebeck * |
* Copyright (C) 2005 - 2017 Christian Schoenebeck * |
7 |
* * |
* * |
8 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
9 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
47 |
|
|
48 |
namespace LinuxSampler { |
namespace LinuxSampler { |
49 |
|
|
50 |
/// Abstract base class for classes that need to run in an own thread. |
/** |
51 |
|
* Abstract base class for classes that need to run in an own thread. The |
52 |
|
* deriving class needs to implement the abstract method Main() for the actual |
53 |
|
* task of the thread to be implemented. |
54 |
|
* |
55 |
|
* @b IMPORTANT: You @b MUST call StopThread() before destructing a running |
56 |
|
* Thread object! Destructing the Thread object without stopping it first can |
57 |
|
* lead to undefined behavior! The destructor will detect if the thread is still |
58 |
|
* running and will stop it automatically in this case, however once the |
59 |
|
* destructor is entered, this Thread object's vpointer is already been |
60 |
|
* modified, so if the thread is still running at this point this would cause a |
61 |
|
* data race condition since the active thread is calling virtual methods and |
62 |
|
* thus this can lead to undefined behavior. |
63 |
|
*/ |
64 |
class Thread { |
class Thread { |
65 |
public: |
public: |
66 |
Thread(bool LockMemory, bool RealTime, int PriorityMax, int PriorityDelta); |
Thread(bool LockMemory, bool RealTime, int PriorityMax, int PriorityDelta); |
67 |
virtual ~Thread(); |
virtual ~Thread(); |
68 |
virtual int StartThread(); |
virtual int StartThread(); |
69 |
virtual int StopThread(); |
virtual int StopThread(); |
|
virtual int SignalStartThread(); |
|
70 |
virtual int SignalStopThread(); |
virtual int SignalStopThread(); |
|
|
|
|
void TestCancel(); |
|
|
|
|
71 |
virtual bool IsRunning(); |
virtual bool IsRunning(); |
|
virtual int SetSchedulingPriority(); //FIXME: should be private |
|
|
virtual int LockMemory(); //FIXME: should be private |
|
|
virtual void EnableDestructor(); //FIXME: should be private |
|
|
virtual int Destructor(); //FIXME: should be private |
|
|
virtual int Main() = 0; ///< This method needs to be implemented by the descendant and is the entry point for the new thread. FIXME: should be protected |
|
72 |
|
|
73 |
/** |
/** |
74 |
* Allocates an aligned block of memory. Allocated memory blocks |
* Allocates an aligned block of memory. Allocated memory blocks |
128 |
#endif |
#endif |
129 |
} |
} |
130 |
|
|
131 |
|
protected: |
132 |
|
/** |
133 |
|
* This method needs to be implemented by the descending class and is |
134 |
|
* the entry point for the new thread. |
135 |
|
* |
136 |
|
* @b NOTE: If your thread runs for a longer time, i.e. if it is running |
137 |
|
* a loop, then you should explicitly call TestCancel() once in a while |
138 |
|
* in your Main() implementation, especially if your implementation does |
139 |
|
* not use any system calls. |
140 |
|
*/ |
141 |
|
virtual int Main() = 0; |
142 |
|
|
143 |
|
/** |
144 |
|
* Synchronization point for potentially terminating the thread. Like |
145 |
|
* already described in Main() you should call TestCancel() in your |
146 |
|
* Main() implementation once in a while to provide the system a chance |
147 |
|
* to perform a clean termination of your thread. Depending on the |
148 |
|
* underlying OS, and also depending on whether your are using any |
149 |
|
* system call in your Main() implementation, it might otherwise be |
150 |
|
* possible that the thread cannot be terminated at all! And even if the |
151 |
|
* underlying OS supports terminating busy threads which do not call |
152 |
|
* TestCancel(), this might still cause undefined behavior on such OSes! |
153 |
|
*/ |
154 |
|
void TestCancel(); |
155 |
|
|
156 |
|
virtual int SignalStartThread(); |
157 |
|
virtual int SetSchedulingPriority(); |
158 |
|
virtual int LockMemory(); |
159 |
|
virtual void EnableDestructor(); |
160 |
|
virtual int onThreadEnd(); |
161 |
|
|
162 |
private: |
private: |
163 |
|
enum state_t { |
164 |
|
NOT_RUNNING, |
165 |
|
RUNNING, |
166 |
|
PENDING_JOIN, |
167 |
|
DETACHED |
168 |
|
}; |
169 |
|
|
170 |
#if defined(WIN32) |
#if defined(WIN32) |
171 |
HANDLE hThread; |
HANDLE hThread; |
172 |
DWORD lpThreadId; |
DWORD lpThreadId; |
183 |
int PriorityDelta; |
int PriorityDelta; |
184 |
bool isRealTime; |
bool isRealTime; |
185 |
bool bLockedMemory; |
bool bLockedMemory; |
186 |
|
state_t state; |
187 |
|
|
188 |
|
#if defined(WIN32) |
189 |
|
static DWORD WINAPI win32threadLauncher(LPVOID lpParameter); |
190 |
|
#else |
191 |
|
static void* pthreadLauncher(void* thread); |
192 |
|
static void pthreadDestructor(void* thread); |
193 |
|
#endif |
194 |
}; |
}; |
195 |
|
|
196 |
} // namespace LinuxSampler |
} // namespace LinuxSampler |