Signed-off-by: falkTX <falktx@falktx.com>tags/v2.5.0
@@ -1311,13 +1311,13 @@ protected: | |||
*/ | |||
friend class CarlaEngineEventPort; | |||
friend class CarlaEngineOsc; | |||
friend class CarlaEngineThread; | |||
friend class CarlaEngineRunner; | |||
friend class CarlaPluginInstance; | |||
friend class EngineInternalGraph; | |||
friend class PendingRtEventsRunner; | |||
friend class ScopedActionLock; | |||
friend class ScopedEngineEnvironmentLocker; | |||
friend class ScopedThreadStopper; | |||
friend class ScopedRunnerStopper; | |||
friend class PatchbayGraph; | |||
friend struct ExternalGraph; | |||
friend struct RackGraph; | |||
@@ -854,7 +854,7 @@ bool CarlaEngine::addPlugin(const BinaryType btype, | |||
{ | |||
CARLA_SAFE_ASSERT(! pData->loadingProject); | |||
const ScopedThreadStopper sts(this); | |||
const ScopedRunnerStopper srs(this); | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
pData->graph.replacePlugin(oldPlugin, plugin); | |||
@@ -925,7 +925,7 @@ bool CarlaEngine::removePlugin(const uint id) | |||
CARLA_SAFE_ASSERT_RETURN_ERR(plugin.get() != nullptr, "Could not find plugin to remove"); | |||
CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data"); | |||
const ScopedThreadStopper sts(this); | |||
const ScopedRunnerStopper srs(this); | |||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
@@ -967,7 +967,7 @@ bool CarlaEngine::removeAllPlugins() | |||
if (pData->curPluginCount == 0) | |||
return true; | |||
const ScopedThreadStopper sts(this); | |||
const ScopedRunnerStopper srs(this); | |||
const uint curPluginCount = pData->curPluginCount; | |||
@@ -1112,7 +1112,7 @@ bool CarlaEngine::switchPlugins(const uint idA, const uint idB) noexcept | |||
CARLA_SAFE_ASSERT_RETURN_ERR(pluginA->getId() == idA, "Invalid engine internal data"); | |||
CARLA_SAFE_ASSERT_RETURN_ERR(pluginB->getId() == idB, "Invalid engine internal data"); | |||
const ScopedThreadStopper sts(this); | |||
const ScopedRunnerStopper srs(this); | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
pData->graph.switchPlugins(pluginA, pluginB); | |||
@@ -377,7 +377,7 @@ EngineEvent* CarlaEngine::getInternalEventBuffer(const bool isInput) const noexc | |||
// CarlaEngine::ProtectedData | |||
CarlaEngine::ProtectedData::ProtectedData(CarlaEngine* const engine) | |||
: thread(engine), | |||
: runner(engine), | |||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | |||
osc(engine), | |||
#endif | |||
@@ -511,7 +511,7 @@ bool CarlaEngine::ProtectedData::init(const char* const clientName) | |||
#endif | |||
nextAction.clearAndReset(); | |||
thread.startThread(); | |||
runner.start(); | |||
return true; | |||
} | |||
@@ -526,7 +526,7 @@ void CarlaEngine::ProtectedData::close() | |||
aboutToClose = true; | |||
thread.stopThread(500); | |||
runner.stop(); | |||
nextAction.clearAndReset(); | |||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | |||
@@ -840,19 +840,19 @@ ScopedActionLock::~ScopedActionLock() noexcept | |||
} | |||
// ----------------------------------------------------------------------- | |||
// ScopedThreadStopper | |||
// ScopedRunnerStopper | |||
ScopedThreadStopper::ScopedThreadStopper(CarlaEngine* const e) noexcept | |||
ScopedRunnerStopper::ScopedRunnerStopper(CarlaEngine* const e) noexcept | |||
: engine(e), | |||
pData(e->pData) | |||
{ | |||
pData->thread.stopThread(500); | |||
pData->runner.stop(); | |||
} | |||
ScopedThreadStopper::~ScopedThreadStopper() noexcept | |||
ScopedRunnerStopper::~ScopedRunnerStopper() noexcept | |||
{ | |||
if (engine->isRunning() && ! pData->aboutToClose) | |||
pData->thread.startThread(); | |||
pData->runner.start(); | |||
} | |||
// ----------------------------------------------------------------------- | |||
@@ -18,7 +18,7 @@ | |||
#ifndef CARLA_ENGINE_INTERNAL_HPP_INCLUDED | |||
#define CARLA_ENGINE_INTERNAL_HPP_INCLUDED | |||
#include "CarlaEngineThread.hpp" | |||
#include "CarlaEngineRunner.hpp" | |||
#include "CarlaEngineUtils.hpp" | |||
#include "CarlaPlugin.hpp" | |||
#include "LinkedList.hpp" | |||
@@ -244,7 +244,7 @@ struct EnginePluginData { | |||
// CarlaEngineProtectedData | |||
struct CarlaEngine::ProtectedData { | |||
CarlaEngineThread thread; | |||
CarlaEngineRunner runner; | |||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | |||
CarlaEngineOsc osc; | |||
@@ -268,7 +268,7 @@ struct CarlaEngine::ProtectedData { | |||
uint32_t bufferSize; | |||
double sampleRate; | |||
bool aboutToClose; // don't re-activate thread if true | |||
bool aboutToClose; // don't re-activate runner if true | |||
int isIdling; // don't allow any operations while idling | |||
uint curPluginCount; // number of plugins loaded (0...max) | |||
uint maxPluginNumber; // number of plugins allowed (0, 16, 99 or 255) | |||
@@ -362,18 +362,18 @@ private: | |||
// ----------------------------------------------------------------------- | |||
class ScopedThreadStopper | |||
class ScopedRunnerStopper | |||
{ | |||
public: | |||
ScopedThreadStopper(CarlaEngine* engine) noexcept; | |||
~ScopedThreadStopper() noexcept; | |||
ScopedRunnerStopper(CarlaEngine* engine) noexcept; | |||
~ScopedRunnerStopper() noexcept; | |||
private: | |||
CarlaEngine* const engine; | |||
CarlaEngine::ProtectedData* const pData; | |||
CARLA_PREVENT_HEAP_ALLOCATION | |||
CARLA_DECLARE_NON_COPYABLE(ScopedThreadStopper) | |||
CARLA_DECLARE_NON_COPYABLE(ScopedRunnerStopper) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
@@ -1520,8 +1520,8 @@ protected: | |||
} | |||
// stopped during removeAllPlugins() | |||
if (! pData->thread.isThreadRunning()) | |||
pData->thread.startThread(); | |||
if (! pData->runner.isRunnerActive()) | |||
pData->runner.start(); | |||
fOptionsForced = true; | |||
const String state(data); | |||
@@ -0,0 +1,170 @@ | |||
/* | |||
* Carla Plugin Host | |||
* Copyright (C) 2011-2022 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
* published by the Free Software Foundation; either version 2 of | |||
* the License, or any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
*/ | |||
#include "CarlaEngineRunner.hpp" | |||
#include "CarlaEngineInternal.hpp" | |||
#include "CarlaPlugin.hpp" | |||
#include "water/misc/Time.h" | |||
CARLA_BACKEND_START_NAMESPACE | |||
// ----------------------------------------------------------------------- | |||
CarlaEngineRunner::CarlaEngineRunner(CarlaEngine* const engine) noexcept | |||
: CarlaRunner("CarlaEngineRunner"), | |||
kEngine(engine), | |||
fIsAlwaysRunning(false), | |||
fIsPlugin(false) | |||
{ | |||
CARLA_SAFE_ASSERT(engine != nullptr); | |||
carla_debug("CarlaEngineRunner::CarlaEngineRunner(%p)", engine); | |||
} | |||
CarlaEngineRunner::~CarlaEngineRunner() noexcept | |||
{ | |||
carla_debug("CarlaEngineRunner::~CarlaEngineRunner()"); | |||
} | |||
void CarlaEngineRunner::start() | |||
{ | |||
carla_debug("CarlaEngineRunner::start()"); | |||
if (isRunnerActive()) | |||
stopRunner(); | |||
fIsPlugin = kEngine->getType() == kEngineTypePlugin; | |||
fIsAlwaysRunning = kEngine->getType() == kEngineTypeBridge || fIsPlugin; | |||
startRunner(25); | |||
} | |||
void CarlaEngineRunner::stop() | |||
{ | |||
carla_debug("CarlaEngineRunner::stop()"); | |||
stopRunner(); | |||
} | |||
// ----------------------------------------------------------------------- | |||
bool CarlaEngineRunner::run() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(kEngine != nullptr, false); | |||
float value; | |||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||
// int64_t lastPingTime = 0; | |||
const CarlaEngineOsc& engineOsc(kEngine->pData->osc); | |||
#endif | |||
// runner must do something... | |||
CARLA_SAFE_ASSERT_RETURN(fIsAlwaysRunning || kEngine->isRunning(), false); | |||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||
const bool oscRegistedForUDP = engineOsc.isControlRegisteredForUDP(); | |||
#else | |||
const bool oscRegistedForUDP = false; | |||
#endif | |||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | |||
if (kIsPlugin) | |||
engineOsc.idle(); | |||
#endif | |||
for (uint i=0, count = kEngine->getCurrentPluginCount(); i < count; ++i) | |||
{ | |||
const CarlaPluginPtr plugin = kEngine->getPluginUnchecked(i); | |||
CARLA_SAFE_ASSERT_CONTINUE(plugin.get() != nullptr && plugin->isEnabled()); | |||
CARLA_SAFE_ASSERT_UINT2(i == plugin->getId(), i, plugin->getId()); | |||
const uint hints = plugin->getHints(); | |||
const bool updateUI = (hints & PLUGIN_HAS_CUSTOM_UI) != 0 && (hints & PLUGIN_NEEDS_UI_MAIN_THREAD) == 0; | |||
// ----------------------------------------------------------- | |||
// DSP Idle | |||
try { | |||
plugin->idle(); | |||
} CARLA_SAFE_EXCEPTION("idle()") | |||
// ----------------------------------------------------------- | |||
// Post-poned events | |||
if (oscRegistedForUDP || updateUI) | |||
{ | |||
// ------------------------------------------------------- | |||
// Update parameter outputs | |||
for (uint32_t j=0, pcount=plugin->getParameterCount(); j < pcount; ++j) | |||
{ | |||
if (! plugin->isParameterOutput(j)) | |||
continue; | |||
value = plugin->getParameterValue(j); | |||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||
// Update OSC engine client | |||
if (oscRegistedForUDP) | |||
engineOsc.sendParameterValue(i, j, value); | |||
#endif | |||
// Update UI | |||
if (updateUI) | |||
plugin->uiParameterChange(j, value); | |||
} | |||
if (updateUI) | |||
{ | |||
try { | |||
plugin->uiIdle(); | |||
} CARLA_SAFE_EXCEPTION("uiIdle()") | |||
} | |||
} | |||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||
// ----------------------------------------------------------- | |||
// Update OSC control client peaks | |||
if (oscRegistedForUDP) | |||
engineOsc.sendPeaks(i, kEngine->getPeaks(i)); | |||
#endif | |||
} | |||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | |||
if (oscRegistedForUDP) | |||
engineOsc.sendRuntimeInfo(); | |||
/* | |||
if (engineOsc.isControlRegisteredForTCP()) | |||
{ | |||
const int64_t timeNow = water::Time::currentTimeMillis(); | |||
if (timeNow - lastPingTime > 1000) | |||
{ | |||
engineOsc.sendPing(); | |||
lastPingTime = timeNow; | |||
} | |||
} | |||
*/ | |||
#endif | |||
return true; | |||
} | |||
// ----------------------------------------------------------------------- | |||
CARLA_BACKEND_END_NAMESPACE |
@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla Plugin Host | |||
* Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2011-2022 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
@@ -19,28 +19,34 @@ | |||
#define CARLA_ENGINE_THREAD_HPP_INCLUDED | |||
#include "CarlaBackend.h" | |||
#include "CarlaThread.hpp" | |||
#include "CarlaRunner.hpp" | |||
#include "CarlaJuceUtils.hpp" | |||
CARLA_BACKEND_START_NAMESPACE | |||
// ----------------------------------------------------------------------- | |||
// CarlaEngineThread | |||
// CarlaEngineRunner | |||
class CarlaEngineThread : public CarlaThread | |||
class CarlaEngineRunner : public CarlaRunner | |||
{ | |||
public: | |||
CarlaEngineThread(CarlaEngine* engine) noexcept; | |||
~CarlaEngineThread() noexcept override; | |||
CarlaEngineRunner(CarlaEngine* engine) noexcept; | |||
~CarlaEngineRunner() noexcept override; | |||
void start(); | |||
void stop(); | |||
protected: | |||
void run() noexcept override; | |||
bool run() noexcept override; | |||
private: | |||
CarlaEngine* const kEngine; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineThread) | |||
bool fIsAlwaysRunning; | |||
bool fIsPlugin; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineRunner) | |||
}; | |||
// ----------------------------------------------------------------------- |
@@ -1,159 +0,0 @@ | |||
/* | |||
* Carla Plugin Host | |||
* Copyright (C) 2011-2020 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
* published by the Free Software Foundation; either version 2 of | |||
* the License, or any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
*/ | |||
#include "CarlaEngineThread.hpp" | |||
#include "CarlaEngineInternal.hpp" | |||
#include "CarlaPlugin.hpp" | |||
#include "water/misc/Time.h" | |||
CARLA_BACKEND_START_NAMESPACE | |||
// ----------------------------------------------------------------------- | |||
CarlaEngineThread::CarlaEngineThread(CarlaEngine* const engine) noexcept | |||
: CarlaThread("CarlaEngineThread"), | |||
kEngine(engine) | |||
{ | |||
CARLA_SAFE_ASSERT(engine != nullptr); | |||
carla_debug("CarlaEngineThread::CarlaEngineThread(%p)", engine); | |||
} | |||
CarlaEngineThread::~CarlaEngineThread() noexcept | |||
{ | |||
carla_debug("CarlaEngineThread::~CarlaEngineThread()"); | |||
} | |||
// ----------------------------------------------------------------------- | |||
void CarlaEngineThread::run() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(kEngine != nullptr,); | |||
carla_debug("CarlaEngineThread::run()"); | |||
const bool kIsPlugin = kEngine->getType() == kEngineTypePlugin; | |||
const bool kIsAlwaysRunning = kEngine->getType() == kEngineTypeBridge || kIsPlugin; | |||
float value; | |||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||
// int64_t lastPingTime = 0; | |||
const CarlaEngineOsc& engineOsc(kEngine->pData->osc); | |||
#endif | |||
// thread must do something... | |||
CARLA_SAFE_ASSERT_RETURN(kIsAlwaysRunning || kEngine->isRunning(),); | |||
for (; (kIsAlwaysRunning || kEngine->isRunning()) && ! shouldThreadExit();) | |||
{ | |||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||
const bool oscRegistedForUDP = engineOsc.isControlRegisteredForUDP(); | |||
#else | |||
const bool oscRegistedForUDP = false; | |||
#endif | |||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | |||
if (kIsPlugin) | |||
engineOsc.idle(); | |||
#endif | |||
for (uint i=0, count = kEngine->getCurrentPluginCount(); i < count; ++i) | |||
{ | |||
const CarlaPluginPtr plugin = kEngine->getPluginUnchecked(i); | |||
CARLA_SAFE_ASSERT_CONTINUE(plugin.get() != nullptr && plugin->isEnabled()); | |||
CARLA_SAFE_ASSERT_UINT2(i == plugin->getId(), i, plugin->getId()); | |||
const uint hints(plugin->getHints()); | |||
const bool updateUI((hints & PLUGIN_HAS_CUSTOM_UI) != 0 && (hints & PLUGIN_NEEDS_UI_MAIN_THREAD) == 0); | |||
// ----------------------------------------------------------- | |||
// DSP Idle | |||
try { | |||
plugin->idle(); | |||
} CARLA_SAFE_EXCEPTION("idle()") | |||
// ----------------------------------------------------------- | |||
// Post-poned events | |||
if (oscRegistedForUDP || updateUI) | |||
{ | |||
// ------------------------------------------------------- | |||
// Update parameter outputs | |||
for (uint32_t j=0, pcount=plugin->getParameterCount(); j < pcount; ++j) | |||
{ | |||
if (! plugin->isParameterOutput(j)) | |||
continue; | |||
value = plugin->getParameterValue(j); | |||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||
// Update OSC engine client | |||
if (oscRegistedForUDP) | |||
engineOsc.sendParameterValue(i, j, value); | |||
#endif | |||
// Update UI | |||
if (updateUI) | |||
plugin->uiParameterChange(j, value); | |||
} | |||
if (updateUI) | |||
{ | |||
try { | |||
plugin->uiIdle(); | |||
} CARLA_SAFE_EXCEPTION("uiIdle()") | |||
} | |||
} | |||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||
// ----------------------------------------------------------- | |||
// Update OSC control client peaks | |||
if (oscRegistedForUDP) | |||
engineOsc.sendPeaks(i, kEngine->getPeaks(i)); | |||
#endif | |||
} | |||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | |||
if (oscRegistedForUDP) | |||
engineOsc.sendRuntimeInfo(); | |||
/* | |||
if (engineOsc.isControlRegisteredForTCP()) | |||
{ | |||
const int64_t timeNow = water::Time::currentTimeMillis(); | |||
if (timeNow - lastPingTime > 1000) | |||
{ | |||
engineOsc.sendPing(); | |||
lastPingTime = timeNow; | |||
} | |||
} | |||
*/ | |||
#endif | |||
carla_msleep(25); | |||
} | |||
carla_debug("CarlaEngineThread closed"); | |||
} | |||
// ----------------------------------------------------------------------- | |||
CARLA_BACKEND_END_NAMESPACE |
@@ -38,7 +38,7 @@ OBJS = \ | |||
$(OBJDIR)/CarlaEngineGraph.cpp.o \ | |||
$(OBJDIR)/CarlaEngineInternal.cpp.o \ | |||
$(OBJDIR)/CarlaEnginePorts.cpp.o \ | |||
$(OBJDIR)/CarlaEngineThread.cpp.o | |||
$(OBJDIR)/CarlaEngineRunner.cpp.o | |||
ifeq ($(HAVE_LIBLO),true) | |||
OBJS += \ | |||
@@ -0,0 +1,227 @@ | |||
/* | |||
* Carla Runner | |||
* Copyright (C) 2022 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
* or without fee is hereby granted, provided that the above copyright notice and this | |||
* permission notice appear in all copies. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
*/ | |||
#ifndef CARLA_RUNNER_HPP_INCLUDED | |||
#define CARLA_RUNNER_HPP_INCLUDED | |||
#include "CarlaUtils.hpp" | |||
#ifndef CARLA_OS_WASM | |||
# include "CarlaThread.hpp" | |||
#else | |||
# include "CarlaString.hpp" | |||
# include <emscripten/emscripten.h> | |||
#endif | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
// CarlaRunner class | |||
/** | |||
This is a handy class that handles "idle" time in either background or main thread, | |||
whichever is more suitable to the target platform. | |||
Typically background threads on desktop platforms, main thread on web. | |||
A single function is expected to be implemented by subclasses, | |||
which directly allows it to stop the runner by returning false. | |||
You can use it for quick operations that do not need to be handled in the main thread if possible. | |||
The target is to spread out execution over many runs, instead of spending a lot of time on a single task. | |||
*/ | |||
class CarlaRunner | |||
{ | |||
protected: | |||
/* | |||
* Constructor. | |||
*/ | |||
CarlaRunner(const char* const runnerName = nullptr) noexcept | |||
#ifndef CARLA_OS_WASM | |||
: fRunnerThread(runnerName), | |||
#else | |||
: fRunnerName(runnerName), | |||
fShouldStop(false), | |||
#endif | |||
fTimeInterval(0) {} | |||
/* | |||
* Destructor. | |||
*/ | |||
virtual ~CarlaRunner() /*noexcept*/ | |||
{ | |||
CARLA_SAFE_ASSERT(! isRunnerActive()); | |||
stopRunner(); | |||
} | |||
/* | |||
* Virtual function to be implemented by the subclass. | |||
* Return true to keep running, false to stop execution. | |||
*/ | |||
virtual bool run() = 0; | |||
/* | |||
* Check if the runner should stop. | |||
* To be called from inside the runner to know if a stop request has been made. | |||
*/ | |||
bool shouldRunnerStop() const noexcept | |||
{ | |||
#ifndef CARLA_OS_WASM | |||
return fRunnerThread.shouldThreadExit(); | |||
#else | |||
return fShouldStop; | |||
#endif | |||
} | |||
// --------------------------------------------------------------------------------------------------------------- | |||
public: | |||
/* | |||
* Check if the runner is active. | |||
*/ | |||
bool isRunnerActive() noexcept | |||
{ | |||
#ifndef CARLA_OS_WASM | |||
return fRunnerThread.isThreadRunning(); | |||
#else | |||
fShouldStop = false; | |||
return true; | |||
#endif | |||
} | |||
/* | |||
* Start the thread. | |||
*/ | |||
bool startRunner(const uint timeIntervalMilliseconds = 0) noexcept | |||
{ | |||
fTimeInterval = timeIntervalMilliseconds; | |||
#ifndef CARLA_OS_WASM | |||
return fRunnerThread.startThread(); | |||
#else | |||
fShouldStop = false; | |||
emscripten_async_call(_entryPoint, this, timeIntervalMilliseconds); | |||
return true; | |||
#endif | |||
} | |||
/* | |||
* Stop the runner. | |||
* This will signal the runner to stop if active, and wait until it finishes. | |||
*/ | |||
bool stopRunner() noexcept | |||
{ | |||
#ifndef CARLA_OS_WASM | |||
return fRunnerThread.stopThread(); | |||
#else | |||
fShouldStop = true; | |||
return true; | |||
#endif | |||
} | |||
/* | |||
* Tell the runner to stop as soon as possible. | |||
*/ | |||
void signalRunnerShouldStop() noexcept | |||
{ | |||
#ifndef CARLA_OS_WASM | |||
fRunnerThread.signalThreadShouldExit(); | |||
#else | |||
fShouldStop = true; | |||
#endif | |||
} | |||
// --------------------------------------------------------------------------------------------------------------- | |||
/* | |||
* Returns the name of the runner. | |||
* This is the name that gets set in the constructor. | |||
*/ | |||
const CarlaString& getRunnerName() const noexcept | |||
{ | |||
#ifndef CARLA_OS_WASM | |||
return fRunnerThread.getThreadName(); | |||
#else | |||
return fRunnerName; | |||
#endif | |||
} | |||
// --------------------------------------------------------------------------------------------------------------- | |||
private: | |||
#ifndef CARLA_OS_WASM | |||
class RunnerThread : private Thread | |||
{ | |||
Runner* const runner; | |||
RunnerThread(Runner* const r, const char* const tn, const uint t) | |||
: Thread(rn), | |||
runner(r), | |||
timeInterval(t) {} | |||
void run() override | |||
{ | |||
while (!shouldThreadExit()) | |||
{ | |||
bool stillRunning = false; | |||
try { | |||
stillRunning = run(); | |||
} catch(...) {} | |||
if (stillRunning && !shouldThreadExit()) | |||
{ | |||
if (timeInterval != 0) | |||
d_msleep(timeInterval) | |||
pthread_yield(); | |||
continue; | |||
} | |||
break; | |||
} | |||
} | |||
} fRunnerThread; | |||
#else | |||
const CarlaString fRunnerName; | |||
volatile bool fShouldStop; | |||
void _runEntryPoint() noexcept | |||
{ | |||
if (fShouldStop) | |||
return; | |||
bool stillRunning = false; | |||
try { | |||
stillRunning = run(); | |||
} catch(...) {} | |||
if (stillRunning && !fShouldStop) | |||
emscripten_async_call(_entryPoint, this, fTimeInterval); | |||
} | |||
static void _entryPoint(void* const userData) noexcept | |||
{ | |||
static_cast<CarlaRunner*>(userData)->_runEntryPoint(); | |||
} | |||
#endif | |||
uint fTimeInterval; | |||
CARLA_DECLARE_NON_COPYABLE(CarlaRunner) | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
#endif // CARLA_RUNNER_HPP_INCLUDED |