You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

796 lines
20KB

  1. #include <engine/Engine.hpp>
  2. #include <settings.hpp>
  3. #include <system.hpp>
  4. #include <random.hpp>
  5. #include <algorithm>
  6. #include <chrono>
  7. #include <thread>
  8. #include <condition_variable>
  9. #include <mutex>
  10. #include <atomic>
  11. #include <x86intrin.h>
  12. namespace rack {
  13. namespace engine {
  14. static void disableDenormals() {
  15. // Set CPU to flush-to-zero (FTZ) and denormals-are-zero (DAZ) mode
  16. // https://software.intel.com/en-us/node/682949
  17. _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
  18. _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
  19. }
  20. /** Threads which obtain a VIPLock will cause wait() to block for other less important threads.
  21. This does not provide the VIPs with an exclusive lock. That should be left up to another mutex shared between the less important thread.
  22. */
  23. struct VIPMutex {
  24. int count = 0;
  25. std::condition_variable cv;
  26. std::mutex countMutex;
  27. /** Blocks until there are no remaining VIPLocks */
  28. void wait() {
  29. std::unique_lock<std::mutex> lock(countMutex);
  30. while (count > 0)
  31. cv.wait(lock);
  32. }
  33. };
  34. struct VIPLock {
  35. VIPMutex &m;
  36. VIPLock(VIPMutex &m) : m(m) {
  37. std::unique_lock<std::mutex> lock(m.countMutex);
  38. m.count++;
  39. }
  40. ~VIPLock() {
  41. std::unique_lock<std::mutex> lock(m.countMutex);
  42. m.count--;
  43. lock.unlock();
  44. m.cv.notify_all();
  45. }
  46. };
  47. struct Barrier {
  48. std::mutex mutex;
  49. std::condition_variable cv;
  50. int count = 0;
  51. int total = 0;
  52. void wait() {
  53. // Waiting on one thread is trivial.
  54. if (total <= 1)
  55. return;
  56. std::unique_lock<std::mutex> lock(mutex);
  57. int id = ++count;
  58. if (id == total) {
  59. count = 0;
  60. cv.notify_all();
  61. }
  62. else {
  63. cv.wait(lock);
  64. }
  65. }
  66. };
  67. struct SpinBarrier {
  68. std::atomic<int> count{0};
  69. int total = 0;
  70. void wait() {
  71. int id = ++count;
  72. if (id == total) {
  73. count = 0;
  74. }
  75. else {
  76. while (count != 0) {
  77. _mm_pause();
  78. }
  79. }
  80. }
  81. };
  82. /** Spinlocks until all `total` threads are waiting.
  83. If `yield` is set to true at any time, all threads will switch to waiting on a mutex instead.
  84. All threads must return before beginning a new phase. Alternating between two barriers solves this problem.
  85. */
  86. struct HybridBarrier {
  87. std::atomic<int> count {0};
  88. int total = 0;
  89. std::mutex mutex;
  90. std::condition_variable cv;
  91. std::atomic<bool> yield {false};
  92. void wait() {
  93. int id = ++count;
  94. // End and reset phase if this is the last thread
  95. if (id == total) {
  96. count = 0;
  97. if (yield) {
  98. std::unique_lock<std::mutex> lock(mutex);
  99. cv.notify_all();
  100. yield = false;
  101. }
  102. return;
  103. }
  104. // Spinlock
  105. while (!yield) {
  106. if (count == 0)
  107. return;
  108. _mm_pause();
  109. }
  110. // Wait on mutex
  111. {
  112. std::unique_lock<std::mutex> lock(mutex);
  113. cv.wait(lock, [&]{
  114. return count == 0;
  115. });
  116. }
  117. }
  118. };
  119. struct EngineWorker {
  120. Engine *engine;
  121. int id;
  122. std::thread thread;
  123. bool running = true;
  124. void start() {
  125. thread = std::thread([&] {
  126. random::init();
  127. run();
  128. });
  129. }
  130. void stop() {
  131. running = false;
  132. }
  133. void join() {
  134. thread.join();
  135. }
  136. void run();
  137. };
  138. struct Engine::Internal {
  139. std::vector<Module*> modules;
  140. std::vector<Cable*> cables;
  141. std::vector<ParamHandle*> paramHandles;
  142. bool paused = false;
  143. bool running = false;
  144. float sampleRate;
  145. float sampleTime;
  146. int nextModuleId = 0;
  147. int nextCableId = 0;
  148. // Parameter smoothing
  149. Module *smoothModule = NULL;
  150. int smoothParamId;
  151. float smoothValue;
  152. std::recursive_mutex mutex;
  153. std::thread thread;
  154. VIPMutex vipMutex;
  155. bool realTime = false;
  156. int threadCount = 1;
  157. std::vector<EngineWorker> workers;
  158. HybridBarrier engineBarrier;
  159. HybridBarrier workerBarrier;
  160. std::atomic<int> workerModuleIndex;
  161. };
  162. Engine::Engine() {
  163. internal = new Internal;
  164. internal->engineBarrier.total = 1;
  165. internal->workerBarrier.total = 1;
  166. internal->sampleRate = 44100.f;
  167. internal->sampleTime = 1 / internal->sampleRate;
  168. system::setThreadRealTime(false);
  169. }
  170. Engine::~Engine() {
  171. // Make sure there are no cables or modules in the rack on destruction.
  172. // If this happens, a module must have failed to remove itself before the RackWidget was destroyed.
  173. assert(internal->cables.empty());
  174. assert(internal->modules.empty());
  175. assert(internal->paramHandles.empty());
  176. delete internal;
  177. }
  178. static void Engine_stepModules(Engine *that, int threadId) {
  179. Engine::Internal *internal = that->internal;
  180. // int threadCount = internal->threadCount;
  181. int modulesLen = internal->modules.size();
  182. float sampleTime = internal->sampleTime;
  183. Module::ProcessArgs processCtx;
  184. processCtx.sampleRate = internal->sampleRate;
  185. processCtx.sampleTime = internal->sampleTime;
  186. // Step each module
  187. // for (int i = threadId; i < modulesLen; i += threadCount) {
  188. while (true) {
  189. // Choose next module
  190. int i = internal->workerModuleIndex++;
  191. if (i >= modulesLen)
  192. break;
  193. Module *module = internal->modules[i];
  194. if (!module->bypass) {
  195. // Step module
  196. if (settings::cpuMeter) {
  197. auto startTime = std::chrono::high_resolution_clock::now();
  198. module->process(processCtx);
  199. auto stopTime = std::chrono::high_resolution_clock::now();
  200. float cpuTime = std::chrono::duration<float>(stopTime - startTime).count();
  201. // Smooth CPU time
  202. const float cpuTau = 2.f /* seconds */;
  203. module->cpuTime += (cpuTime - module->cpuTime) * sampleTime / cpuTau;
  204. }
  205. else {
  206. module->process(processCtx);
  207. }
  208. }
  209. // Iterate ports to step plug lights
  210. for (Input &input : module->inputs) {
  211. input.process(sampleTime);
  212. }
  213. for (Output &output : module->outputs) {
  214. output.process(sampleTime);
  215. }
  216. }
  217. }
  218. static void Cable_step(Cable *that) {
  219. Output *output = &that->outputModule->outputs[that->outputId];
  220. Input *input = &that->inputModule->inputs[that->inputId];
  221. // Match number of polyphonic channels to output port
  222. input->channels = output->channels;
  223. // Copy all voltages from output to input
  224. for (int i = 0; i < PORT_MAX_CHANNELS; i++) {
  225. input->voltages[i] = output->voltages[i];
  226. }
  227. }
  228. static void Engine_step(Engine *that) {
  229. Engine::Internal *internal = that->internal;
  230. // Param smoothing
  231. Module *smoothModule = internal->smoothModule;
  232. int smoothParamId = internal->smoothParamId;
  233. float smoothValue = internal->smoothValue;
  234. if (smoothModule) {
  235. Param *param = &smoothModule->params[smoothParamId];
  236. float value = param->value;
  237. // Decay rate is 1 graphics frame
  238. const float smoothLambda = 60.f;
  239. float newValue = value + (smoothValue - value) * smoothLambda * internal->sampleTime;
  240. if (value == newValue) {
  241. // Snap to actual smooth value if the value doesn't change enough (due to the granularity of floats)
  242. param->setValue(smoothValue);
  243. internal->smoothModule = NULL;
  244. internal->smoothParamId = 0;
  245. }
  246. else {
  247. param->value = newValue;
  248. }
  249. }
  250. // Step cables
  251. for (Cable *cable : that->internal->cables) {
  252. Cable_step(cable);
  253. }
  254. // Flip messages for each module
  255. for (Module *module : that->internal->modules) {
  256. if (module->leftExpander.messageFlipRequested) {
  257. std::swap(module->leftExpander.producerMessage, module->leftExpander.consumerMessage);
  258. module->leftExpander.messageFlipRequested = false;
  259. }
  260. if (module->rightExpander.messageFlipRequested) {
  261. std::swap(module->rightExpander.producerMessage, module->rightExpander.consumerMessage);
  262. module->rightExpander.messageFlipRequested = false;
  263. }
  264. }
  265. // Step modules along with workers
  266. internal->workerModuleIndex = 0;
  267. internal->engineBarrier.wait();
  268. Engine_stepModules(that, 0);
  269. internal->workerBarrier.wait();
  270. }
  271. static void Engine_updateExpander(Engine *that, Module::Expander *expander) {
  272. if (expander->moduleId >= 0) {
  273. if (!expander->module || expander->module->id != expander->moduleId) {
  274. expander->module = that->getModule(expander->moduleId);
  275. }
  276. }
  277. else {
  278. if (expander->module) {
  279. expander->module = NULL;
  280. }
  281. }
  282. }
  283. static void Engine_relaunchWorkers(Engine *that) {
  284. Engine::Internal *internal = that->internal;
  285. assert(1 <= internal->threadCount);
  286. // Stop all workers
  287. for (EngineWorker &worker : internal->workers) {
  288. worker.stop();
  289. }
  290. internal->engineBarrier.wait();
  291. // Destroy all workers
  292. for (EngineWorker &worker : internal->workers) {
  293. worker.join();
  294. }
  295. internal->workers.resize(0);
  296. // Configure main thread
  297. system::setThreadRealTime(internal->realTime);
  298. // Set barrier counts
  299. internal->engineBarrier.total = internal->threadCount;
  300. internal->workerBarrier.total = internal->threadCount;
  301. // Create workers
  302. internal->workers.resize(internal->threadCount - 1);
  303. for (int id = 1; id < internal->threadCount; id++) {
  304. EngineWorker &worker = internal->workers[id - 1];
  305. worker.id = id;
  306. worker.engine = that;
  307. worker.start();
  308. }
  309. }
  310. static void Engine_run(Engine *that) {
  311. Engine::Internal *internal = that->internal;
  312. // Set up thread
  313. system::setThreadName("Engine");
  314. // system::setThreadRealTime();
  315. disableDenormals();
  316. // Every time the that waits and locks a mutex, it steps this many frames
  317. const int mutexSteps = 128;
  318. // Time in seconds that the that is rushing ahead of the estimated clock time
  319. double aheadTime = 0.0;
  320. auto lastTime = std::chrono::high_resolution_clock::now();
  321. while (internal->running) {
  322. internal->vipMutex.wait();
  323. // Set sample rate
  324. if (internal->sampleRate != settings::sampleRate) {
  325. internal->sampleRate = settings::sampleRate;
  326. internal->sampleTime = 1 / internal->sampleRate;
  327. for (Module *module : internal->modules) {
  328. module->onSampleRateChange();
  329. }
  330. aheadTime = 0.0;
  331. }
  332. // Launch workers
  333. if (internal->threadCount != settings::threadCount || internal->realTime != settings::realTime) {
  334. internal->threadCount = settings::threadCount;
  335. internal->realTime = settings::realTime;
  336. Engine_relaunchWorkers(that);
  337. }
  338. if (!internal->paused) {
  339. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  340. // Update expander pointers
  341. for (Module *module : internal->modules) {
  342. Engine_updateExpander(that, &module->leftExpander);
  343. Engine_updateExpander(that, &module->rightExpander);
  344. }
  345. // Step modules
  346. for (int i = 0; i < mutexSteps; i++) {
  347. Engine_step(that);
  348. }
  349. }
  350. double stepTime = mutexSteps * internal->sampleTime;
  351. aheadTime += stepTime;
  352. auto currTime = std::chrono::high_resolution_clock::now();
  353. const double aheadFactor = 2.0;
  354. aheadTime -= aheadFactor * std::chrono::duration<double>(currTime - lastTime).count();
  355. lastTime = currTime;
  356. aheadTime = std::fmax(aheadTime, 0.0);
  357. // Avoid pegging the CPU at 100% when there are no "blocking" modules like AudioInterface, but still step audio at a reasonable rate
  358. // The number of steps to wait before possibly sleeping
  359. const double aheadMax = 1.0; // seconds
  360. if (aheadTime > aheadMax) {
  361. std::this_thread::sleep_for(std::chrono::duration<double>(stepTime));
  362. }
  363. }
  364. // Stop workers
  365. internal->threadCount = 1;
  366. Engine_relaunchWorkers(that);
  367. }
  368. void Engine::start() {
  369. internal->running = true;
  370. internal->thread = std::thread([&] {
  371. random::init();
  372. Engine_run(this);
  373. });
  374. }
  375. void Engine::stop() {
  376. internal->running = false;
  377. internal->thread.join();
  378. }
  379. void Engine::setPaused(bool paused) {
  380. VIPLock vipLock(internal->vipMutex);
  381. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  382. internal->paused = paused;
  383. }
  384. bool Engine::isPaused() {
  385. // No lock
  386. return internal->paused;
  387. }
  388. float Engine::getSampleRate() {
  389. return internal->sampleRate;
  390. }
  391. float Engine::getSampleTime() {
  392. return internal->sampleTime;
  393. }
  394. void Engine::yieldWorkers() {
  395. internal->workerBarrier.yield = true;
  396. }
  397. void Engine::addModule(Module *module) {
  398. assert(module);
  399. VIPLock vipLock(internal->vipMutex);
  400. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  401. // Check that the module is not already added
  402. auto it = std::find(internal->modules.begin(), internal->modules.end(), module);
  403. assert(it == internal->modules.end());
  404. // Set ID
  405. if (module->id < 0) {
  406. // Automatically assign ID
  407. module->id = internal->nextModuleId++;
  408. }
  409. else {
  410. // Manual ID
  411. // Check that the ID is not already taken
  412. for (Module *m : internal->modules) {
  413. assert(module->id != m->id);
  414. }
  415. if (module->id >= internal->nextModuleId) {
  416. internal->nextModuleId = module->id + 1;
  417. }
  418. }
  419. // Add module
  420. internal->modules.push_back(module);
  421. // Trigger Add event
  422. module->onAdd();
  423. // Update ParamHandles
  424. for (ParamHandle *paramHandle : internal->paramHandles) {
  425. if (paramHandle->moduleId == module->id)
  426. paramHandle->module = module;
  427. }
  428. }
  429. void Engine::removeModule(Module *module) {
  430. assert(module);
  431. VIPLock vipLock(internal->vipMutex);
  432. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  433. // Check that the module actually exists
  434. auto it = std::find(internal->modules.begin(), internal->modules.end(), module);
  435. assert(it != internal->modules.end());
  436. // If a param is being smoothed on this module, stop smoothing it immediately
  437. if (module == internal->smoothModule) {
  438. internal->smoothModule = NULL;
  439. }
  440. // Check that all cables are disconnected
  441. for (Cable *cable : internal->cables) {
  442. assert(cable->outputModule != module);
  443. assert(cable->inputModule != module);
  444. }
  445. // Update ParamHandles
  446. for (ParamHandle *paramHandle : internal->paramHandles) {
  447. if (paramHandle->moduleId == module->id)
  448. paramHandle->module = NULL;
  449. }
  450. // Update expander pointers
  451. for (Module *m : internal->modules) {
  452. if (m->leftExpander.module == module) {
  453. m->leftExpander.moduleId = -1;
  454. m->leftExpander.module = NULL;
  455. }
  456. if (m->rightExpander.module == module) {
  457. m->rightExpander.moduleId = -1;
  458. m->rightExpander.module = NULL;
  459. }
  460. }
  461. // Trigger Remove event
  462. module->onRemove();
  463. // Remove module
  464. internal->modules.erase(it);
  465. }
  466. Module *Engine::getModule(int moduleId) {
  467. VIPLock vipLock(internal->vipMutex);
  468. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  469. // Find module
  470. for (Module *module : internal->modules) {
  471. if (module->id == moduleId)
  472. return module;
  473. }
  474. return NULL;
  475. }
  476. void Engine::resetModule(Module *module) {
  477. assert(module);
  478. VIPLock vipLock(internal->vipMutex);
  479. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  480. module->onReset();
  481. }
  482. void Engine::randomizeModule(Module *module) {
  483. assert(module);
  484. VIPLock vipLock(internal->vipMutex);
  485. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  486. module->onRandomize();
  487. }
  488. void Engine::bypassModule(Module *module, bool bypass) {
  489. assert(module);
  490. VIPLock vipLock(internal->vipMutex);
  491. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  492. if (module->bypass == bypass)
  493. return;
  494. // Clear outputs and set to 1 channel
  495. for (Output &output : module->outputs) {
  496. // This zeros all voltages, but the channel is set to 1 if connected
  497. output.setChannels(0);
  498. }
  499. module->cpuTime = 0.f;
  500. module->bypass = bypass;
  501. }
  502. static void Port_setDisconnected(Port *that) {
  503. that->channels = 0;
  504. for (int c = 0; c < PORT_MAX_CHANNELS; c++) {
  505. that->voltages[c] = 0.f;
  506. }
  507. }
  508. static void Port_setConnected(Port *that) {
  509. if (that->channels > 0)
  510. return;
  511. that->channels = 1;
  512. }
  513. static void Engine_updateConnected(Engine *that) {
  514. // Find disconnected ports
  515. std::set<Port*> disconnectedPorts;
  516. for (Module *module : that->internal->modules) {
  517. for (Output &output : module->outputs) {
  518. disconnectedPorts.insert(&output);
  519. }
  520. for (Input &input : module->inputs) {
  521. disconnectedPorts.insert(&input);
  522. }
  523. }
  524. for (Cable *cable : that->internal->cables) {
  525. // Connect output
  526. Output &output = cable->outputModule->outputs[cable->outputId];
  527. auto outputIt = disconnectedPorts.find(&output);
  528. if (outputIt != disconnectedPorts.end())
  529. disconnectedPorts.erase(outputIt);
  530. Port_setConnected(&output);
  531. // Connect input
  532. Input &input = cable->inputModule->inputs[cable->inputId];
  533. auto inputIt = disconnectedPorts.find(&input);
  534. if (inputIt != disconnectedPorts.end())
  535. disconnectedPorts.erase(inputIt);
  536. Port_setConnected(&input);
  537. }
  538. // Disconnect ports that have no cable
  539. for (Port *port : disconnectedPorts) {
  540. Port_setDisconnected(port);
  541. }
  542. }
  543. void Engine::addCable(Cable *cable) {
  544. assert(cable);
  545. VIPLock vipLock(internal->vipMutex);
  546. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  547. // Check cable properties
  548. assert(cable->outputModule);
  549. assert(cable->inputModule);
  550. // Check that the cable is not already added, and that the input is not already used by another cable
  551. for (Cable *cable2 : internal->cables) {
  552. assert(cable2 != cable);
  553. assert(!(cable2->inputModule == cable->inputModule && cable2->inputId == cable->inputId));
  554. }
  555. // Set ID
  556. if (cable->id < 0) {
  557. // Automatically assign ID
  558. cable->id = internal->nextCableId++;
  559. }
  560. else {
  561. // Manual ID
  562. // Check that the ID is not already taken
  563. for (Cable *w : internal->cables) {
  564. assert(cable->id != w->id);
  565. }
  566. if (cable->id >= internal->nextCableId) {
  567. internal->nextCableId = cable->id + 1;
  568. }
  569. }
  570. // Add the cable
  571. internal->cables.push_back(cable);
  572. Engine_updateConnected(this);
  573. }
  574. void Engine::removeCable(Cable *cable) {
  575. assert(cable);
  576. VIPLock vipLock(internal->vipMutex);
  577. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  578. // Check that the cable is already added
  579. auto it = std::find(internal->cables.begin(), internal->cables.end(), cable);
  580. assert(it != internal->cables.end());
  581. // Remove the cable
  582. internal->cables.erase(it);
  583. Engine_updateConnected(this);
  584. }
  585. void Engine::setParam(Module *module, int paramId, float value) {
  586. // TODO Does this need to be thread-safe?
  587. // If being smoothed, cancel smoothing
  588. if (internal->smoothModule == module && internal->smoothParamId == paramId) {
  589. internal->smoothModule = NULL;
  590. internal->smoothParamId = 0;
  591. }
  592. module->params[paramId].value = value;
  593. }
  594. float Engine::getParam(Module *module, int paramId) {
  595. return module->params[paramId].value;
  596. }
  597. void Engine::setSmoothParam(Module *module, int paramId, float value) {
  598. // If another param is being smoothed, jump value
  599. if (internal->smoothModule && !(internal->smoothModule == module && internal->smoothParamId == paramId)) {
  600. internal->smoothModule->params[internal->smoothParamId].value = internal->smoothValue;
  601. }
  602. internal->smoothParamId = paramId;
  603. internal->smoothValue = value;
  604. // Set this last so the above values are valid as soon as it is set
  605. internal->smoothModule = module;
  606. }
  607. float Engine::getSmoothParam(Module *module, int paramId) {
  608. if (internal->smoothModule == module && internal->smoothParamId == paramId)
  609. return internal->smoothValue;
  610. return getParam(module, paramId);
  611. }
  612. void Engine::addParamHandle(ParamHandle *paramHandle) {
  613. VIPLock vipLock(internal->vipMutex);
  614. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  615. // Check that the ParamHandle is not already added
  616. auto it = std::find(internal->paramHandles.begin(), internal->paramHandles.end(), paramHandle);
  617. assert(it == internal->paramHandles.end());
  618. // New ParamHandles must be blank
  619. assert(paramHandle->moduleId < 0);
  620. internal->paramHandles.push_back(paramHandle);
  621. }
  622. void Engine::removeParamHandle(ParamHandle *paramHandle) {
  623. VIPLock vipLock(internal->vipMutex);
  624. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  625. paramHandle->module = NULL;
  626. // Check that the ParamHandle is already added
  627. auto it = std::find(internal->paramHandles.begin(), internal->paramHandles.end(), paramHandle);
  628. assert(it != internal->paramHandles.end());
  629. internal->paramHandles.erase(it);
  630. }
  631. ParamHandle *Engine::getParamHandle(Module *module, int paramId) {
  632. // VIPLock vipLock(internal->vipMutex);
  633. // std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  634. for (ParamHandle *paramHandle : internal->paramHandles) {
  635. if (paramHandle->module == module && paramHandle->paramId == paramId)
  636. return paramHandle;
  637. }
  638. return NULL;
  639. }
  640. void Engine::updateParamHandle(ParamHandle *paramHandle, int moduleId, int paramId, bool overwrite) {
  641. VIPLock vipLock(internal->vipMutex);
  642. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  643. // Set IDs
  644. paramHandle->moduleId = moduleId;
  645. paramHandle->paramId = paramId;
  646. paramHandle->module = NULL;
  647. auto it = std::find(internal->paramHandles.begin(), internal->paramHandles.end(), paramHandle);
  648. if (it != internal->paramHandles.end() && paramHandle->moduleId >= 0) {
  649. // Remove existing ParamHandles pointing to the same param
  650. for (ParamHandle *p : internal->paramHandles) {
  651. if (p != paramHandle && p->moduleId == moduleId && p->paramId == paramId) {
  652. if (overwrite)
  653. p->reset();
  654. else
  655. paramHandle->reset();
  656. }
  657. }
  658. // Find module with same moduleId
  659. for (Module *module : internal->modules) {
  660. if (module->id == paramHandle->moduleId) {
  661. paramHandle->module = module;
  662. }
  663. }
  664. }
  665. }
  666. void EngineWorker::run() {
  667. system::setThreadName("Engine worker");
  668. system::setThreadRealTime(engine->internal->realTime);
  669. disableDenormals();
  670. while (1) {
  671. engine->internal->engineBarrier.wait();
  672. if (!running)
  673. return;
  674. Engine_stepModules(engine, id);
  675. engine->internal->workerBarrier.wait();
  676. }
  677. }
  678. } // namespace engine
  679. } // namespace rack