Add remaining files
[juce-lv2.git] / juce / source / src / threads / juce_Thread.cpp
blobcb44891a3c1f85f31b862c384d88e8b0cb24a98a
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../core/juce_StandardHeader.h"
28 BEGIN_JUCE_NAMESPACE
30 #include "juce_Thread.h"
31 #include "juce_SpinLock.h"
32 #include "../core/juce_Time.h"
33 #include "../containers/juce_Array.h"
36 //==============================================================================
37 class RunningThreadsList
39 public:
40 RunningThreadsList()
44 ~RunningThreadsList()
46 // Some threads are still running! Make sure you stop all your
47 // threads cleanly before your app quits!
48 jassert (threads.size() == 0);
51 void add (Thread* const thread)
53 const SpinLock::ScopedLockType sl (lock);
54 jassert (! threads.contains (thread));
55 threads.add (thread);
58 void remove (Thread* const thread)
60 const SpinLock::ScopedLockType sl (lock);
61 jassert (threads.contains (thread));
62 threads.removeValue (thread);
65 int size() const noexcept
67 return threads.size();
70 Thread* getThreadWithID (const Thread::ThreadID targetID) const noexcept
72 const SpinLock::ScopedLockType sl (lock);
74 for (int i = threads.size(); --i >= 0;)
76 Thread* const t = threads.getUnchecked(i);
78 if (t->getThreadId() == targetID)
79 return t;
82 return nullptr;
85 void stopAll (const int timeOutMilliseconds)
87 signalAllThreadsToStop();
89 for (;;)
91 Thread* firstThread = getFirstThread();
93 if (firstThread != nullptr)
94 firstThread->stopThread (timeOutMilliseconds);
95 else
96 break;
100 static RunningThreadsList& getInstance()
102 static RunningThreadsList runningThreads;
103 return runningThreads;
106 private:
107 Array<Thread*> threads;
108 SpinLock lock;
110 void signalAllThreadsToStop()
112 const SpinLock::ScopedLockType sl (lock);
114 for (int i = threads.size(); --i >= 0;)
115 threads.getUnchecked(i)->signalThreadShouldExit();
118 Thread* getFirstThread() const
120 const SpinLock::ScopedLockType sl (lock);
121 return threads.getFirst();
126 //==============================================================================
127 void Thread::threadEntryPoint()
129 RunningThreadsList::getInstance().add (this);
131 JUCE_TRY
133 if (threadName_.isNotEmpty())
134 setCurrentThreadName (threadName_);
136 if (startSuspensionEvent_.wait (10000))
138 jassert (getCurrentThreadId() == threadId_);
140 if (affinityMask_ != 0)
141 setCurrentThreadAffinityMask (affinityMask_);
143 run();
146 JUCE_CATCH_ALL_ASSERT
148 RunningThreadsList::getInstance().remove (this);
149 closeThreadHandle();
152 // used to wrap the incoming call from the platform-specific code
153 void JUCE_API juce_threadEntryPoint (void* userData)
155 static_cast <Thread*> (userData)->threadEntryPoint();
159 //==============================================================================
160 Thread::Thread (const String& threadName)
161 : threadName_ (threadName),
162 threadHandle_ (nullptr),
163 threadId_ (0),
164 threadPriority_ (5),
165 affinityMask_ (0),
166 threadShouldExit_ (false)
170 Thread::~Thread()
172 /* If your thread class's destructor has been called without first stopping the thread, that
173 means that this partially destructed object is still performing some work - and that's
174 probably a Bad Thing!
176 To avoid this type of nastiness, always make sure you call stopThread() before or during
177 your subclass's destructor.
179 jassert (! isThreadRunning());
181 stopThread (100);
184 //==============================================================================
185 void Thread::startThread()
187 const ScopedLock sl (startStopLock);
189 threadShouldExit_ = false;
191 if (threadHandle_ == nullptr)
193 launchThread();
194 setThreadPriority (threadHandle_, threadPriority_);
195 startSuspensionEvent_.signal();
199 void Thread::startThread (const int priority)
201 const ScopedLock sl (startStopLock);
203 if (threadHandle_ == nullptr)
205 threadPriority_ = priority;
206 startThread();
208 else
210 setPriority (priority);
214 bool Thread::isThreadRunning() const
216 return threadHandle_ != nullptr;
219 //==============================================================================
220 void Thread::signalThreadShouldExit()
222 threadShouldExit_ = true;
225 bool Thread::waitForThreadToExit (const int timeOutMilliseconds) const
227 // Doh! So how exactly do you expect this thread to wait for itself to stop??
228 jassert (getThreadId() != getCurrentThreadId());
230 const int sleepMsPerIteration = 5;
231 int count = timeOutMilliseconds / sleepMsPerIteration;
233 while (isThreadRunning())
235 if (timeOutMilliseconds > 0 && --count < 0)
236 return false;
238 sleep (sleepMsPerIteration);
241 return true;
244 void Thread::stopThread (const int timeOutMilliseconds)
246 // agh! You can't stop the thread that's calling this method! How on earth
247 // would that work??
248 jassert (getCurrentThreadId() != getThreadId());
250 const ScopedLock sl (startStopLock);
252 if (isThreadRunning())
254 signalThreadShouldExit();
255 notify();
257 if (timeOutMilliseconds != 0)
258 waitForThreadToExit (timeOutMilliseconds);
260 if (isThreadRunning())
262 // very bad karma if this point is reached, as there are bound to be
263 // locks and events left in silly states when a thread is killed by force..
264 jassertfalse;
265 Logger::writeToLog ("!! killing thread by force !!");
267 killThread();
269 RunningThreadsList::getInstance().remove (this);
270 threadHandle_ = nullptr;
271 threadId_ = 0;
276 //==============================================================================
277 bool Thread::setPriority (const int priority)
279 const ScopedLock sl (startStopLock);
281 if (setThreadPriority (threadHandle_, priority))
283 threadPriority_ = priority;
284 return true;
287 return false;
290 bool Thread::setCurrentThreadPriority (const int priority)
292 return setThreadPriority (0, priority);
295 void Thread::setAffinityMask (const uint32 affinityMask)
297 affinityMask_ = affinityMask;
300 //==============================================================================
301 bool Thread::wait (const int timeOutMilliseconds) const
303 return defaultEvent_.wait (timeOutMilliseconds);
306 void Thread::notify() const
308 defaultEvent_.signal();
311 //==============================================================================
312 int Thread::getNumRunningThreads()
314 return RunningThreadsList::getInstance().size();
317 Thread* Thread::getCurrentThread()
319 return RunningThreadsList::getInstance().getThreadWithID (getCurrentThreadId());
322 void Thread::stopAllThreads (const int timeOutMilliseconds)
324 RunningThreadsList::getInstance().stopAll (timeOutMilliseconds);
327 //==============================================================================
328 void SpinLock::enter() const noexcept
330 if (! tryEnter())
332 for (int i = 20; --i >= 0;)
333 if (tryEnter())
334 return;
336 while (! tryEnter())
337 Thread::yield();
342 END_JUCE_NAMESPACE