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.

860 lines
22KB

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