Browse Source

Write to `settings::sampleRate` and `threadCount` instead of calling Engine methods.

tags/v1.0.0
Andrew Belt 6 years ago
parent
commit
a0e738bc07
5 changed files with 87 additions and 73 deletions
  1. +0
    -3
      include/engine/Engine.hpp
  2. +1
    -0
      include/settings.hpp
  3. +20
    -8
      src/app/Toolbar.cpp
  4. +59
    -62
      src/engine/Engine.cpp
  5. +7
    -0
      src/settings.cpp

+ 0
- 3
include/engine/Engine.hpp View File

@@ -20,11 +20,8 @@ struct Engine {
void start(); void start();
/** Stops engine thread. */ /** Stops engine thread. */
void stop(); void stop();
void setThreadCount(int threadCount);
int getThreadCount();
void setPaused(bool paused); void setPaused(bool paused);
bool isPaused(); bool isPaused();
void setSampleRate(float sampleRate);
float getSampleRate(); float getSampleRate();
/** Returns the inverse of the current sample rate. */ /** Returns the inverse of the current sample rate. */
float getSampleTime(); float getSampleTime();


+ 1
- 0
include/settings.hpp View File

@@ -25,6 +25,7 @@ extern bool invertZoom;
extern float cableOpacity; extern float cableOpacity;
extern float cableTension; extern float cableTension;
extern bool allowCursorLock; extern bool allowCursorLock;
extern bool realTime;
extern float sampleRate; extern float sampleRate;
extern int threadCount; extern int threadCount;
extern bool paramTooltip; extern bool paramTooltip;


+ 20
- 8
src/app/Toolbar.cpp View File

@@ -277,7 +277,7 @@ struct EnginePauseItem : ui::MenuItem {
struct SampleRateValueItem : ui::MenuItem { struct SampleRateValueItem : ui::MenuItem {
float sampleRate; float sampleRate;
void onAction(const event::Action &e) override { void onAction(const event::Action &e) override {
APP->engine->setSampleRate(sampleRate);
settings::sampleRate = sampleRate;
APP->engine->setPaused(false); APP->engine->setPaused(false);
} }
}; };
@@ -288,7 +288,7 @@ struct SampleRateItem : ui::MenuItem {
ui::Menu *menu = new ui::Menu; ui::Menu *menu = new ui::Menu;


EnginePauseItem *enginePauseItem = new EnginePauseItem; EnginePauseItem *enginePauseItem = new EnginePauseItem;
enginePauseItem->text = "Pause engine";
enginePauseItem->text = "Pause";
enginePauseItem->rightText = CHECKMARK(APP->engine->isPaused()); enginePauseItem->rightText = CHECKMARK(APP->engine->isPaused());
menu->addChild(enginePauseItem); menu->addChild(enginePauseItem);


@@ -304,7 +304,7 @@ struct SampleRateItem : ui::MenuItem {
if (oversample > 1) if (oversample > 1)
item->rightText += string::f("(%dx)", oversample); item->rightText += string::f("(%dx)", oversample);
item->rightText += " "; item->rightText += " ";
item->rightText += CHECKMARK(APP->engine->getSampleRate() == sampleRate);
item->rightText += CHECKMARK(settings::sampleRate == sampleRate);
menu->addChild(item); menu->addChild(item);
} }
} }
@@ -313,6 +313,13 @@ struct SampleRateItem : ui::MenuItem {
}; };




struct RealTimeItem : ui::MenuItem {
void onAction(const event::Action &e) override {
settings::realTime ^= true;
}
};


struct ThreadCountValueItem : ui::MenuItem { struct ThreadCountValueItem : ui::MenuItem {
int threadCount; int threadCount;
void setThreadCount(int threadCount) { void setThreadCount(int threadCount) {
@@ -322,18 +329,23 @@ struct ThreadCountValueItem : ui::MenuItem {
text += " (most modules)"; text += " (most modules)";
else if (threadCount == 1) else if (threadCount == 1)
text += " (lowest CPU usage)"; text += " (lowest CPU usage)";
rightText = CHECKMARK(APP->engine->getThreadCount() == threadCount);
rightText = CHECKMARK(settings::threadCount == threadCount);
} }
void onAction(const event::Action &e) override { void onAction(const event::Action &e) override {
APP->engine->setThreadCount(threadCount);
settings::threadCount = threadCount;
} }
}; };




struct ThreadCount : ui::MenuItem {
struct ThreadCountItem : ui::MenuItem {
ui::Menu *createChildMenu() override { ui::Menu *createChildMenu() override {
ui::Menu *menu = new ui::Menu; ui::Menu *menu = new ui::Menu;


RealTimeItem *realTimeItem = new RealTimeItem;
realTimeItem->text = "Real-time priority";
realTimeItem->rightText = CHECKMARK(settings::realTime);
menu->addChild(realTimeItem);

int coreCount = system::getLogicalCoreCount(); int coreCount = system::getLogicalCoreCount();
for (int i = 1; i <= coreCount; i++) { for (int i = 1; i <= coreCount; i++) {
ThreadCountValueItem *item = new ThreadCountValueItem; ThreadCountValueItem *item = new ThreadCountValueItem;
@@ -378,8 +390,8 @@ struct SettingsButton : MenuButton {
sampleRateItem->rightText = RIGHT_ARROW; sampleRateItem->rightText = RIGHT_ARROW;
menu->addChild(sampleRateItem); menu->addChild(sampleRateItem);


ThreadCount *threadCount = new ThreadCount;
threadCount->text = "Thread count";
ThreadCountItem *threadCount = new ThreadCountItem;
threadCount->text = "Engine threads";
threadCount->rightText = RIGHT_ARROW; threadCount->rightText = RIGHT_ARROW;
menu->addChild(threadCount); menu->addChild(threadCount);




+ 59
- 62
src/engine/Engine.cpp View File

@@ -151,6 +151,7 @@ struct Engine::Internal {
std::thread thread; std::thread thread;
VIPMutex vipMutex; VIPMutex vipMutex;


bool realTime = false;
int threadCount = 1; int threadCount = 1;
std::vector<EngineWorker> workers; std::vector<EngineWorker> workers;
SpinBarrier engineBarrier; SpinBarrier engineBarrier;
@@ -165,17 +166,11 @@ Engine::Engine() {
internal->engineBarrier.total = 1; internal->engineBarrier.total = 1;
internal->workerBarrier.total = 1; internal->workerBarrier.total = 1;


setSampleRate(44100.f);
setThreadCount(settings::threadCount);
internal->sampleRate = 44100.f;
internal->sampleTime = 1 / internal->sampleRate;
} }


Engine::~Engine() { Engine::~Engine() {
settings::sampleRate = internal->sampleRate;
settings::threadCount = internal->threadCount;

// Stop worker threads
setThreadCount(1);

// Make sure there are no cables or modules in the rack on destruction. // Make sure there are no cables or modules in the rack on destruction.
// If this happens, a module must have failed to remove itself before the RackWidget was destroyed. // If this happens, a module must have failed to remove itself before the RackWidget was destroyed.
assert(internal->cables.empty()); assert(internal->cables.empty());
@@ -300,7 +295,38 @@ static void Engine_updateAdjacent(Engine *that, Module *m) {
} }
} }


static void Engine_relaunchWorkers(Engine *that) {
Engine::Internal *internal = that->internal;
assert(1 <= internal->threadCount);

// Stop all workers
for (EngineWorker &worker : internal->workers) {
worker.stop();
}
internal->engineBarrier.wait();

// Destroy all workers
for (EngineWorker &worker : internal->workers) {
worker.join();
}
internal->workers.resize(0);

// Set barrier counts
internal->engineBarrier.total = internal->threadCount;
internal->workerBarrier.total = internal->threadCount;

// Create workers
internal->workers.resize(internal->threadCount - 1);
for (int id = 1; id < internal->threadCount; id++) {
EngineWorker &worker = internal->workers[id - 1];
worker.id = id;
worker.engine = that;
worker.start();
}
}

static void Engine_run(Engine *that) { static void Engine_run(Engine *that) {
Engine::Internal *internal = that->internal;
// Set up thread // Set up thread
system::setThreadName("Engine"); system::setThreadName("Engine");
// system::setThreadRealTime(); // system::setThreadRealTime();
@@ -312,13 +338,28 @@ static void Engine_run(Engine *that) {
double ahead = 0.0; double ahead = 0.0;
auto lastTime = std::chrono::high_resolution_clock::now(); auto lastTime = std::chrono::high_resolution_clock::now();


while (that->internal->running) {
that->internal->vipMutex.wait();
while (internal->running) {
internal->vipMutex.wait();

// Set sample rate
if (internal->sampleRate != settings::sampleRate) {
internal->sampleRate = settings::sampleRate;
internal->sampleTime = 1 / internal->sampleRate;
for (Module *module : internal->modules) {
module->onSampleRateChange();
}
}

// Launch workers
if (internal->threadCount != settings::threadCount) {
internal->threadCount = settings::threadCount;
Engine_relaunchWorkers(that);
}


if (!that->internal->paused) {
std::lock_guard<std::recursive_mutex> lock(that->internal->mutex);
if (!internal->paused) {
std::lock_guard<std::recursive_mutex> lock(internal->mutex);


for (Module *module : that->internal->modules) {
for (Module *module : internal->modules) {
Engine_updateAdjacent(that, module); Engine_updateAdjacent(that, module);
} }


@@ -328,7 +369,7 @@ static void Engine_run(Engine *that) {
} }
} }


double stepTime = mutexSteps * that->internal->sampleTime;
double stepTime = mutexSteps * internal->sampleTime;
ahead += stepTime; ahead += stepTime;
auto currTime = std::chrono::high_resolution_clock::now(); auto currTime = std::chrono::high_resolution_clock::now();
const double aheadFactor = 2.0; const double aheadFactor = 2.0;
@@ -343,6 +384,10 @@ static void Engine_run(Engine *that) {
std::this_thread::sleep_for(std::chrono::duration<double>(stepTime)); std::this_thread::sleep_for(std::chrono::duration<double>(stepTime));
} }
} }

// Stop workers
internal->threadCount = 1;
Engine_relaunchWorkers(that);
} }


void Engine::start() { void Engine::start() {
@@ -355,43 +400,6 @@ void Engine::stop() {
internal->thread.join(); internal->thread.join();
} }


void Engine::setThreadCount(int threadCount) {
assert(1 <= threadCount);
VIPLock vipLock(internal->vipMutex);
std::lock_guard<std::recursive_mutex> lock(internal->mutex);

// Stop all workers
for (EngineWorker &worker : internal->workers) {
worker.stop();
}
internal->engineBarrier.wait();

// Destroy all workers
for (EngineWorker &worker : internal->workers) {
worker.join();
}
internal->workers.resize(0);

// Set barrier counts
internal->threadCount = threadCount;
internal->engineBarrier.total = threadCount;
internal->workerBarrier.total = threadCount;

// Create workers
internal->workers.resize(threadCount - 1);
for (int id = 1; id < threadCount; id++) {
EngineWorker &worker = internal->workers[id - 1];
worker.id = id;
worker.engine = this;
worker.start();
}
}

int Engine::getThreadCount() {
// No lock
return internal->threadCount;
}

void Engine::setPaused(bool paused) { void Engine::setPaused(bool paused) {
VIPLock vipLock(internal->vipMutex); VIPLock vipLock(internal->vipMutex);
std::lock_guard<std::recursive_mutex> lock(internal->mutex); std::lock_guard<std::recursive_mutex> lock(internal->mutex);
@@ -403,17 +411,6 @@ bool Engine::isPaused() {
return internal->paused; return internal->paused;
} }


void Engine::setSampleRate(float sampleRate) {
VIPLock vipLock(internal->vipMutex);
std::lock_guard<std::recursive_mutex> lock(internal->mutex);

internal->sampleRate = sampleRate;
internal->sampleTime = 1 / sampleRate;
for (Module *module : internal->modules) {
module->onSampleRateChange();
}
}

float Engine::getSampleRate() { float Engine::getSampleRate() {
return internal->sampleRate; return internal->sampleRate;
} }


+ 7
- 0
src/settings.cpp View File

@@ -23,6 +23,7 @@ bool invertZoom = false;
float cableOpacity = 0.5; float cableOpacity = 0.5;
float cableTension = 0.5; float cableTension = 0.5;
bool allowCursorLock = true; bool allowCursorLock = true;
bool realTime = false;
float sampleRate = 44100.0; float sampleRate = 44100.0;
int threadCount = 1; int threadCount = 1;
bool paramTooltip = false; bool paramTooltip = false;
@@ -57,6 +58,8 @@ json_t *toJson() {


json_object_set_new(rootJ, "allowCursorLock", json_boolean(allowCursorLock)); json_object_set_new(rootJ, "allowCursorLock", json_boolean(allowCursorLock));


json_object_set_new(rootJ, "realTime", json_boolean(realTime));

json_object_set_new(rootJ, "sampleRate", json_real(sampleRate)); json_object_set_new(rootJ, "sampleRate", json_real(sampleRate));


json_object_set_new(rootJ, "threadCount", json_integer(threadCount)); json_object_set_new(rootJ, "threadCount", json_integer(threadCount));
@@ -130,6 +133,10 @@ void fromJson(json_t *rootJ) {
if (allowCursorLockJ) if (allowCursorLockJ)
allowCursorLock = json_is_true(allowCursorLockJ); allowCursorLock = json_is_true(allowCursorLockJ);


json_t *realTimeJ = json_object_get(rootJ, "realTime");
if (realTimeJ)
realTime = json_boolean_value(realTimeJ);

json_t *sampleRateJ = json_object_get(rootJ, "sampleRate"); json_t *sampleRateJ = json_object_get(rootJ, "sampleRate");
if (sampleRateJ) if (sampleRateJ)
sampleRate = json_number_value(sampleRateJ); sampleRate = json_number_value(sampleRateJ);


Loading…
Cancel
Save