1 |
/*************************************************************************** |
/*************************************************************************** |
2 |
* * |
* * |
3 |
* Copyright (C) 2005 - 2020 Christian Schoenebeck * |
* Copyright (C) 2005 - 2022 Christian Schoenebeck * |
4 |
* * |
* * |
5 |
* This library is free software; you can redistribute it and/or modify * |
* This library is free software; you can redistribute it and/or modify * |
6 |
* 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 * |
23 |
#include "../common/global_private.h" |
#include "../common/global_private.h" |
24 |
#include "EngineChannelFactory.h" |
#include "EngineChannelFactory.h" |
25 |
|
|
26 |
|
// how often periodic jobs for external components shall be executed |
27 |
|
// (every 200ms) |
28 |
|
#define PERIODIC_JOBS_SEC 0 |
29 |
|
#define PERIODIC_JOBS_NSEC (200 * 1000 * 1000) |
30 |
|
|
31 |
namespace LinuxSampler { |
namespace LinuxSampler { |
32 |
|
|
33 |
InstrumentManagerThread::InstrumentManagerThread() : Thread(true, false, 0, -4) { |
InstrumentManagerThread::InstrumentManagerThread() : Thread(true, false, 0, -4) { |
157 |
} |
} |
158 |
} |
} |
159 |
|
|
160 |
|
// perform periodic, custom jobs on behalf of external components |
161 |
|
{ |
162 |
|
LockGuard lock(periodicJobsMutex); |
163 |
|
for (ext_job_t job : periodicJobs) { |
164 |
|
job.fn(); |
165 |
|
} |
166 |
|
} |
167 |
|
|
168 |
// now allow thread being cancelled again |
// now allow thread being cancelled again |
169 |
// (since all mutexes are now unlocked) |
// (since all mutexes are now unlocked) |
170 |
popCancelable(); |
popCancelable(); |
171 |
|
|
172 |
// nothing left to do, sleep until new jobs arrive |
// nothing left to do, sleep until new jobs arrive |
173 |
conditionJobsLeft.WaitIf(false); |
const bool timedOut = |
174 |
|
(AnyPeriodicJobs()) ? |
175 |
|
// do wait, but with a maximum timeout value |
176 |
|
conditionJobsLeft.WaitIf(false, PERIODIC_JOBS_SEC, PERIODIC_JOBS_NSEC) : |
177 |
|
// wait indefinitely |
178 |
|
conditionJobsLeft.WaitIf(false); |
179 |
// reset flag |
// reset flag |
180 |
conditionJobsLeft.Set(false); |
if (!timedOut) { |
181 |
// unlock condition object so it can be turned again by other thread |
conditionJobsLeft.Set(false); |
182 |
conditionJobsLeft.Unlock(); |
// unlock condition object so it can be turned again by other thread |
183 |
|
conditionJobsLeft.Unlock(); |
184 |
|
} |
185 |
} |
} |
186 |
return 0; |
return 0; |
187 |
} |
} |
188 |
|
|
189 |
|
/** |
190 |
|
* Schedule a job to be executed by instrument manager thread periodically. |
191 |
|
* |
192 |
|
* This method is intended to be used by external components to execute |
193 |
|
* instrument files related tasks periodically. Currently this is hard |
194 |
|
* coded to happen approximately every 200ms, however if the instrument |
195 |
|
* manager thread is currently blocked by executing other tasks (e.g. |
196 |
|
* loading some instrument) then this might also be significantly delayed |
197 |
|
* accordingly. |
198 |
|
* |
199 |
|
* The scheduled task will continue to be executed indefinitely until |
200 |
|
* @c RemovePeriodicJob() is called. |
201 |
|
* |
202 |
|
* Currently this method is only used by the SFZ engine for its auto |
203 |
|
* reload feature (i.e. on modifications of .sfz files by external apps). |
204 |
|
* |
205 |
|
* @param name - arbitrary but unique ID for the task |
206 |
|
* @param fn - actual callback for the task to be executed |
207 |
|
*/ |
208 |
|
void InstrumentManagerThread::AddPeriodicJob(String name, std::function<void()> fn) { |
209 |
|
LockGuard lock(periodicJobsMutex); |
210 |
|
RemovePeriodicJobWithoutLock(name); |
211 |
|
periodicJobs.push_back({ |
212 |
|
.name = name, |
213 |
|
.fn = fn |
214 |
|
}); |
215 |
|
} |
216 |
|
|
217 |
|
/** |
218 |
|
* Unschedule a periodic task previously scheduled by @c AddPeriodicJob(). |
219 |
|
* |
220 |
|
* @param name - unique ID of the previously scheduled periodic task |
221 |
|
*/ |
222 |
|
void InstrumentManagerThread::RemovePeriodicJob(String name) { |
223 |
|
LockGuard lock(periodicJobsMutex); |
224 |
|
RemovePeriodicJobWithoutLock(name); |
225 |
|
} |
226 |
|
|
227 |
|
void InstrumentManagerThread::RemovePeriodicJobWithoutLock(String name) { |
228 |
|
for (size_t i = 0; i < periodicJobs.size(); ++i) { |
229 |
|
if (periodicJobs[i].name == name) { |
230 |
|
periodicJobs.erase( periodicJobs.begin() + i ); |
231 |
|
return; |
232 |
|
} |
233 |
|
} |
234 |
|
} |
235 |
|
|
236 |
|
bool InstrumentManagerThread::AnyPeriodicJobs() { |
237 |
|
// would probably be OK without a lock, but strictly it would be undefined behaviour |
238 |
|
LockGuard lock(periodicJobsMutex); |
239 |
|
return !periodicJobs.empty(); |
240 |
|
} |
241 |
|
|
242 |
void InstrumentManagerThread::EventHandler::ChannelToBeRemoved(SamplerChannel* pChannel) { |
void InstrumentManagerThread::EventHandler::ChannelToBeRemoved(SamplerChannel* pChannel) { |
243 |
/* |
/* |
244 |
Removing from the queue an eventual scheduled loading of an instrument |
Removing from the queue an eventual scheduled loading of an instrument |