| @@ -28,7 +28,7 @@ int getLogicalCoreCount(); | |||
| /** Sets a name of the current thread for debuggers and OS-specific process viewers. */ | |||
| void setThreadName(const std::string &name); | |||
| /** Sets the current thread to be high-priority. */ | |||
| void setThreadRealTime(); | |||
| void setThreadRealTime(bool realTime); | |||
| /** Returns the caller's human-readable stack trace with "\n"-separated lines. */ | |||
| std::string getStackTrace(); | |||
| /** Opens a URL, also happens to work with PDFs and folders. | |||
| @@ -211,7 +211,7 @@ static int rtCallback(void *outputBuffer, void *inputBuffer, unsigned int nFrame | |||
| // Exploit the stream time to run code on startup of the audio thread | |||
| if (streamTime == 0.0) { | |||
| system::setThreadName("Audio"); | |||
| system::setThreadRealTime(); | |||
| // system::setThreadRealTime(); | |||
| } | |||
| port->processStream((const float *) inputBuffer, (float *) outputBuffer, nFrames); | |||
| return 0; | |||
| @@ -116,15 +116,7 @@ struct EngineWorker { | |||
| thread.join(); | |||
| } | |||
| void run() { | |||
| system::setThreadName("Engine worker"); | |||
| // system::setThreadRealTime(); | |||
| disableDenormals(); | |||
| while (running) { | |||
| step(); | |||
| } | |||
| } | |||
| void run(); | |||
| void step(); | |||
| }; | |||
| @@ -168,6 +160,8 @@ Engine::Engine() { | |||
| internal->sampleRate = 44100.f; | |||
| internal->sampleTime = 1 / internal->sampleRate; | |||
| system::setThreadRealTime(false); | |||
| } | |||
| Engine::~Engine() { | |||
| @@ -300,22 +294,31 @@ static void Engine_relaunchWorkers(Engine *that) { | |||
| assert(1 <= internal->threadCount); | |||
| // Stop all workers | |||
| DEBUG("1"); | |||
| for (EngineWorker &worker : internal->workers) { | |||
| worker.stop(); | |||
| } | |||
| DEBUG("2"); | |||
| internal->engineBarrier.wait(); | |||
| // Destroy all workers | |||
| DEBUG("3"); | |||
| for (EngineWorker &worker : internal->workers) { | |||
| worker.join(); | |||
| } | |||
| DEBUG("4"); | |||
| internal->workers.resize(0); | |||
| DEBUG("5"); | |||
| // Configure main thread | |||
| system::setThreadRealTime(internal->realTime); | |||
| // Set barrier counts | |||
| internal->engineBarrier.total = internal->threadCount; | |||
| internal->workerBarrier.total = internal->threadCount; | |||
| // Create workers | |||
| DEBUG("6"); | |||
| internal->workers.resize(internal->threadCount - 1); | |||
| for (int id = 1; id < internal->threadCount; id++) { | |||
| EngineWorker &worker = internal->workers[id - 1]; | |||
| @@ -323,6 +326,7 @@ static void Engine_relaunchWorkers(Engine *that) { | |||
| worker.engine = that; | |||
| worker.start(); | |||
| } | |||
| DEBUG("7"); | |||
| } | |||
| static void Engine_run(Engine *that) { | |||
| @@ -351,8 +355,9 @@ static void Engine_run(Engine *that) { | |||
| } | |||
| // Launch workers | |||
| if (internal->threadCount != settings::threadCount) { | |||
| if (internal->threadCount != settings::threadCount || internal->realTime != settings::realTime) { | |||
| internal->threadCount = settings::threadCount; | |||
| internal->realTime = settings::realTime; | |||
| Engine_relaunchWorkers(that); | |||
| } | |||
| @@ -696,6 +701,15 @@ void Engine::updateParamHandle(ParamHandle *paramHandle, int moduleId, int param | |||
| } | |||
| void EngineWorker::run() { | |||
| system::setThreadName("Engine worker"); | |||
| system::setThreadRealTime(engine->internal->realTime); | |||
| disableDenormals(); | |||
| while (running) { | |||
| step(); | |||
| } | |||
| } | |||
| void EngineWorker::step() { | |||
| engine->internal->engineBarrier.wait(); | |||
| if (!running) | |||
| @@ -105,17 +105,37 @@ void setThreadName(const std::string &name) { | |||
| #endif | |||
| } | |||
| void setThreadRealTime() { | |||
| void setThreadRealTime(bool realTime) { | |||
| #if defined ARCH_LIN || defined ARCH_MAC | |||
| // Round-robin scheduler policy | |||
| int policy = SCHED_RR; | |||
| int err; | |||
| int policy; | |||
| struct sched_param param; | |||
| param.sched_priority = sched_get_priority_max(policy); | |||
| pthread_setschedparam(pthread_self(), policy, ¶m); | |||
| if (realTime) { | |||
| // Round-robin scheduler policy | |||
| policy = SCHED_RR; | |||
| param.sched_priority = sched_get_priority_max(policy); | |||
| } | |||
| else { | |||
| // Default scheduler policy | |||
| policy = 0; | |||
| param.sched_priority = 0; | |||
| } | |||
| err = pthread_setschedparam(pthread_self(), policy, ¶m); | |||
| assert(!err); | |||
| // pthread_getschedparam(pthread_self(), &policy, ¶m); | |||
| // DEBUG("policy %d priority %d", policy, param.sched_priority); | |||
| #elif defined ARCH_WIN | |||
| // Set process class first | |||
| SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); | |||
| SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); | |||
| if (realTime) { | |||
| SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); | |||
| SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); | |||
| } | |||
| else { | |||
| SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); | |||
| SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); | |||
| } | |||
| #endif | |||
| } | |||