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"
30 #include "juce_TimeSliceThread.h"
33 //==============================================================================
34 TimeSliceThread::TimeSliceThread (const String
& threadName
)
35 : Thread (threadName
),
36 clientBeingCalled (nullptr)
40 TimeSliceThread::~TimeSliceThread()
45 //==============================================================================
46 void TimeSliceThread::addTimeSliceClient (TimeSliceClient
* const client
, int millisecondsBeforeStarting
)
48 if (client
!= nullptr)
50 const ScopedLock
sl (listLock
);
51 client
->nextCallTime
= Time::getCurrentTime() + RelativeTime::milliseconds (millisecondsBeforeStarting
);
52 clients
.addIfNotAlreadyThere (client
);
57 void TimeSliceThread::removeTimeSliceClient (TimeSliceClient
* const client
)
59 const ScopedLock
sl1 (listLock
);
61 // if there's a chance we're in the middle of calling this client, we need to
62 // also lock the outer lock..
63 if (clientBeingCalled
== client
)
65 const ScopedUnlock
ul (listLock
); // unlock first to get the order right..
67 const ScopedLock
sl2 (callbackLock
);
68 const ScopedLock
sl3 (listLock
);
70 clients
.removeValue (client
);
74 clients
.removeValue (client
);
78 int TimeSliceThread::getNumClients() const
80 return clients
.size();
83 TimeSliceClient
* TimeSliceThread::getClient (const int i
) const
85 const ScopedLock
sl (listLock
);
89 //==============================================================================
90 TimeSliceClient
* TimeSliceThread::getNextClient (int index
) const
93 TimeSliceClient
* client
= nullptr;
95 for (int i
= clients
.size(); --i
>= 0;)
97 TimeSliceClient
* const c
= clients
.getUnchecked ((i
+ index
) % clients
.size());
99 if (client
== nullptr || c
->nextCallTime
< soonest
)
102 soonest
= c
->nextCallTime
;
109 void TimeSliceThread::run()
113 while (! threadShouldExit())
115 int timeToWait
= 500;
121 const ScopedLock
sl2 (listLock
);
123 index
= clients
.size() > 0 ? ((index
+ 1) % clients
.size()) : 0;
125 TimeSliceClient
* const firstClient
= getNextClient (index
);
126 if (firstClient
!= nullptr)
127 nextClientTime
= firstClient
->nextCallTime
;
130 const Time
now (Time::getCurrentTime());
132 if (nextClientTime
> now
)
134 timeToWait
= (int) jmin ((int64
) 500, (nextClientTime
- now
).inMilliseconds());
138 timeToWait
= index
== 0 ? 1 : 0;
140 const ScopedLock
sl (callbackLock
);
143 const ScopedLock
sl2 (listLock
);
144 clientBeingCalled
= getNextClient (index
);
147 if (clientBeingCalled
!= nullptr)
149 const int msUntilNextCall
= clientBeingCalled
->useTimeSlice();
151 const ScopedLock
sl2 (listLock
);
153 if (msUntilNextCall
>= 0)
154 clientBeingCalled
->nextCallTime
+= RelativeTime::milliseconds (msUntilNextCall
);
156 clients
.removeValue (clientBeingCalled
);
158 clientBeingCalled
= nullptr;