Add TAL-Reverb-II plugin to test
[juce-lv2.git] / juce / source / extras / JuceDemo / Source / demos / ThreadingDemo.cpp
blobd86a17c5cf63101f849c47748e8243b230e92579
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-9 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 "../jucedemo_headers.h"
29 //==============================================================================
30 class BouncingBallComp : public Component
32 public:
33 BouncingBallComp()
35 x = Random::getSystemRandom().nextFloat() * 200.0f;
36 y = Random::getSystemRandom().nextFloat() * 200.0f;
37 parentWidth = 50;
38 parentHeight = 50;
39 innerX = 0;
40 innerY = 0;
41 threadId = 0;
43 const float speed = 5.0f; // give each ball a fixed speed so we can
44 // see the effects of thread priority on how fast
45 // they actually go.
46 const float angle = Random::getSystemRandom().nextFloat() * float_Pi * 2.0f;
48 dx = sinf (angle) * speed;
49 dy = cosf (angle) * speed;
51 size = Random::getSystemRandom().nextFloat() * 30.0f + 30.0f;
53 colour = Colour (Random::getSystemRandom().nextInt())
54 .withAlpha (0.5f)
55 .withBrightness (0.7f);
58 ~BouncingBallComp()
62 void paint (Graphics& g)
64 g.setColour (colour);
65 g.fillEllipse (innerX, innerY, size, size);
67 g.setColour (Colours::black);
68 g.setFont (10.0f);
69 g.drawText (String::toHexString ((int64) threadId), 0, 0, getWidth(), getHeight(), Justification::centred, false);
72 void parentSizeChanged()
74 parentWidth = getParentWidth() - size;
75 parentHeight = getParentHeight() - size;
78 void moveBall()
80 threadId = Thread::getCurrentThreadId(); // this is so the component can print the thread ID inside the ball
82 x += dx;
83 y += dy;
85 if (x < 0)
86 dx = fabsf (dx);
88 if (x > parentWidth)
89 dx = -fabsf (dx);
91 if (y < 0)
92 dy = fabsf (dy);
94 if (y > parentHeight)
95 dy = -fabsf (dy);
97 setBounds (((int) x) - 2,
98 ((int) y) - 2,
99 ((int) size) + 4,
100 ((int) size) + 4);
102 innerX = x - getX();
103 innerY = y - getY();
105 repaint();
108 private:
109 float x, y, size, dx, dy, w, h, parentWidth, parentHeight;
110 float innerX, innerY;
111 Colour colour;
112 Thread::ThreadID threadId;
114 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BouncingBallComp);
118 //==============================================================================
119 class DemoThread : public BouncingBallComp,
120 public Thread
122 public:
123 DemoThread()
124 : Thread ("Juce Demo Thread")
126 interval = Random::getSystemRandom().nextInt (50) + 6;
128 // give the threads a random priority, so some will move more
129 // smoothly than others..
130 startThread (Random::getSystemRandom().nextInt (3) + 3);
133 ~DemoThread()
135 // allow the thread 2 seconds to stop cleanly - should be plenty of time.
136 stopThread (2000);
139 void run()
141 // this is the code that runs this thread - we'll loop continuously,
142 // updating the co-ordinates of our blob.
144 // threadShouldExit() returns true when the stopThread() method has been
145 // called, so we should check it often, and exit as soon as it gets flagged.
146 while (! threadShouldExit())
148 // sleep a bit so the threads don't all grind the CPU to a halt..
149 wait (interval);
151 // because this is a background thread, we mustn't do any UI work without
152 // first grabbing a MessageManagerLock..
153 const MessageManagerLock mml (Thread::getCurrentThread());
155 if (! mml.lockWasGained()) // if something is trying to kill this job, the lock
156 return; // will fail, in which case we'd better return..
158 // now we've got the UI thread locked, we can mess about with the components
159 moveBall();
163 private:
164 int interval;
166 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DemoThread);
170 //==============================================================================
171 class DemoThreadPoolJob : public BouncingBallComp,
172 public ThreadPoolJob
174 public:
175 DemoThreadPoolJob()
176 : ThreadPoolJob ("Demo Threadpool Job")
180 ~DemoThreadPoolJob()
184 JobStatus runJob()
186 // this is the code that runs this job. It'll be repeatedly called until we return
187 // jobHasFinished instead of jobNeedsRunningAgain.
189 Thread::sleep (30);
192 // because this is a background thread, we mustn't do any UI work without
193 // first grabbing a MessageManagerLock..
194 const MessageManagerLock mml (this);
196 // before moving the ball, we need to check whether the lock was actually gained, because
197 // if something is trying to stop this job, it will have failed..
198 if (mml.lockWasGained())
199 moveBall();
201 return jobNeedsRunningAgain;
204 void removedFromQueue()
206 // This is called to tell us that our job has been removed from the pool.
207 // In this case there's no need to do anything here.
210 private:
211 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DemoThreadPoolJob);
214 //==============================================================================
215 class ThreadingDemo : public Component,
216 public Timer,
217 public ButtonListener
219 public:
220 //==============================================================================
221 ThreadingDemo()
222 : pool (3),
223 controlButton ("Thread type"),
224 isUsingPool (false)
226 setName ("Multithreading");
228 setOpaque (true);
230 addAndMakeVisible (&controlButton);
231 controlButton.changeWidthToFitText (20);
232 controlButton.setTopLeftPosition (20, 20);
233 controlButton.setTriggeredOnMouseDown (true);
234 controlButton.setAlwaysOnTop (true);
235 controlButton.addListener (this);
238 ~ThreadingDemo()
240 pool.removeAllJobs (true, 2000);
243 void resetAllBalls()
245 stopTimer();
247 pool.removeAllJobs (true, 4000);
248 balls.clear();
250 if (isShowing())
252 while (balls.size() < 5)
253 addABall();
255 startTimer (2000);
259 void paint (Graphics& g)
261 g.fillAll (Colours::white);
264 void setUsingPool (bool usePool)
266 isUsingPool = usePool;
267 resetAllBalls();
270 void addABall()
272 if (isUsingPool)
274 DemoThreadPoolJob* newBall = new DemoThreadPoolJob();
275 balls.add (newBall);
276 addAndMakeVisible (newBall);
277 newBall->parentSizeChanged();
279 pool.addJob (newBall);
281 else
283 DemoThread* newBall = new DemoThread();
284 balls.add (newBall);
285 addAndMakeVisible (newBall);
286 newBall->parentSizeChanged();
290 void removeABall()
292 if (balls.size() > 0)
294 int indexToRemove = Random::getSystemRandom().nextInt (balls.size());
296 if (isUsingPool)
297 pool.removeJob (dynamic_cast <DemoThreadPoolJob*> (balls [indexToRemove]), true, 4000);
299 balls.remove (indexToRemove);
303 void timerCallback()
305 if (Random::getSystemRandom().nextBool())
307 if (balls.size() <= 10)
308 addABall();
310 else
312 if (balls.size() > 3)
313 removeABall();
317 void buttonClicked (Button*)
319 PopupMenu m;
320 m.addItem (1, "Use one thread per ball", true, ! isUsingPool);
321 m.addItem (2, "Use a thread pool", true, isUsingPool);
323 m.showMenuAsync (PopupMenu::Options().withTargetComponent (&controlButton),
324 ModalCallbackFunction::forComponent (menuItemChosenCallback, this));
327 static void menuItemChosenCallback (int result, ThreadingDemo* demoComponent)
329 if (demoComponent != 0)
330 demoComponent->setUsingPool (result == 2);
333 // this gets called when a component is added or removed from a parent component.
334 void parentHierarchyChanged()
336 // we'll use this as an opportunity to start and stop the threads, so that
337 // we don't leave them going when the component's not actually visible.
338 resetAllBalls();
341 private:
342 ThreadPool pool;
343 TextButton controlButton;
344 bool isUsingPool;
346 OwnedArray<Component> balls;
351 //==============================================================================
352 Component* createThreadingDemo()
354 return new ThreadingDemo();