34#define WIN32_LEAN_AND_MEAN
36#undef WIN32_LEAN_AND_MEAN
40#include <condition_variable>
81 bool AddComponent(
const Component::SPtr& component );
83 bool RemoveComponent(
const Component::SPtr& component );
84 void RemoveAllComponents();
86 int GetComponentCount()
const;
88 bool ConnectOutToIn(
const Component::SPtr& fromComponent,
int fromOutput,
const Component::SPtr& toComponent,
int toInput );
90 bool DisconnectComponent(
const Component::SPtr& component );
91 void DisconnectAllComponents();
93 void SetBufferCount(
int bufferCount );
94 int GetBufferCount()
const;
96 void SetThreadCount(
int threadCount );
97 int GetThreadCount()
const;
102 void StartAutoTick();
104 void PauseAutoTick();
105 void ResumeAutoTick();
110 class AutoTickThread final
113 AutoTickThread(
const AutoTickThread& ) =
delete;
114 AutoTickThread& operator=(
const AutoTickThread& ) =
delete;
116 inline AutoTickThread() =
default;
118 inline ~AutoTickThread()
137 _thread = std::thread( &AutoTickThread::_Run,
this );
144 if ( _thread.joinable() )
152 if ( !_stopped && ++pauseCount == 1 )
154 std::unique_lock<std::mutex> lock( _resumeMutex );
156 _pauseCondt.wait( lock );
162 if ( _pause && --pauseCount == 0 )
165 _resumeCondt.notify_all();
166 std::this_thread::yield();
181 std::unique_lock<std::mutex> lock( _resumeMutex );
183 _pauseCondt.notify_all();
184 _resumeCondt.wait( lock );
197 bool _stopped =
true;
198 std::mutex _resumeMutex;
199 std::condition_variable _resumeCondt, _pauseCondt;
202 class CircuitThread final
205 CircuitThread(
const CircuitThread& ) =
delete;
206 CircuitThread& operator=(
const CircuitThread& ) =
delete;
208 inline CircuitThread() =
default;
211 inline CircuitThread( CircuitThread&& )
215 inline ~CircuitThread()
220 inline void Start( std::vector<DSPatch::Component*>* components,
int bufferNo )
222 _components = components;
223 _bufferNo = bufferNo;
228 _thread = std::thread( &CircuitThread::_Run,
this );
237 if ( _thread.joinable() )
245 std::unique_lock<std::mutex> lock( _syncMutex );
249 _syncCondt.wait( lock );
256 _resumeCondt.notify_all();
257 std::this_thread::yield();
260 inline void SyncAndResume()
270 SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST );
272 sched_param sch_params;
273 sch_params.sched_priority = sched_get_priority_max( SCHED_RR );
274 pthread_setschedparam( pthread_self(), SCHED_RR, &sch_params );
282 std::unique_lock<std::mutex> lock( _syncMutex );
285 _syncCondt.notify_all();
286 _resumeCondt.wait( lock );
301 for (
auto component : *_components )
303 component->Tick( _bufferNo );
311 std::vector<DSPatch::Component*>* _components =
nullptr;
314 bool _gotSync =
false;
315 std::mutex _syncMutex;
316 std::condition_variable _resumeCondt, _syncCondt;
319 class CircuitThreadParallel final
322 CircuitThreadParallel(
const CircuitThreadParallel& ) =
delete;
323 CircuitThreadParallel& operator=(
const CircuitThreadParallel& ) =
delete;
325 inline CircuitThreadParallel() =
default;
328 inline CircuitThreadParallel( CircuitThreadParallel&& )
332 inline ~CircuitThreadParallel()
337 inline void Start( std::vector<DSPatch::Component*>* components,
int bufferNo,
int threadNo,
int threadCount )
339 _components = components;
340 _bufferNo = bufferNo;
341 _threadNo = threadNo;
342 _threadCount = threadCount;
347 _thread = std::thread( &CircuitThreadParallel::_Run,
this );
356 if ( _thread.joinable() )
364 std::unique_lock<std::mutex> lock( _syncMutex );
368 _syncCondt.wait( lock );
375 _resumeCondt.notify_all();
376 std::this_thread::yield();
383 SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST );
385 sched_param sch_params;
386 sch_params.sched_priority = sched_get_priority_max( SCHED_RR );
387 pthread_setschedparam( pthread_self(), SCHED_RR, &sch_params );
395 std::unique_lock<std::mutex> lock( _syncMutex );
398 _syncCondt.notify_all();
399 _resumeCondt.wait( lock );
405 for (
auto it = _components->begin() + _threadNo; it < _components->end(); it += _threadCount )
407 ( *it )->TickParallel( _bufferNo );
415 std::vector<DSPatch::Component*>* _components =
nullptr;
418 int _threadCount = 0;
420 bool _gotSync =
false;
421 std::mutex _syncMutex;
422 std::condition_variable _resumeCondt, _syncCondt;
427 int _bufferCount = 0;
428 int _threadCount = 0;
429 int _currentBuffer = 0;
431 AutoTickThread _autoTickThread;
433 std::set<DSPatch::Component::SPtr> _componentsSet;
435 std::vector<DSPatch::Component*> _components;
436 std::vector<DSPatch::Component*> _componentsParallel;
438 std::vector<CircuitThread> _circuitThreads;
439 std::vector<std::vector<CircuitThreadParallel>> _circuitThreadsParallel;
441 bool _circuitDirty =
false;
444inline Circuit::Circuit() =
default;
446inline Circuit::~Circuit()
449 DisconnectAllComponents();
452inline bool Circuit::AddComponent(
const Component::SPtr& component )
454 if ( !component || _componentsSet.find( component ) != _componentsSet.end() )
460 component->SetBufferCount( _bufferCount, _currentBuffer );
463 _components.emplace_back( component.get() );
464 _componentsParallel.emplace_back( component.get() );
467 _componentsSet.emplace( component );
472inline bool Circuit::RemoveComponent(
const Component::SPtr& component )
474 if ( _componentsSet.find( component ) == _componentsSet.end() )
479 auto findFn = [&component](
auto comp ) {
return comp == component.get(); };
481 if (
auto it = std::find_if( _components.begin(), _components.end(), findFn ); it != _components.end() )
485 DisconnectComponent( component );
487 _components.erase( it );
491 _componentsSet.erase( component );
500inline void Circuit::RemoveAllComponents()
504 DisconnectAllComponents();
507 _componentsParallel.clear();
511 _componentsSet.clear();
514inline int Circuit::GetComponentCount()
const
516 return (
int)_components.size();
519inline bool Circuit::ConnectOutToIn(
const Component::SPtr& fromComponent,
521 const Component::SPtr& toComponent,
524 if ( _componentsSet.find( fromComponent ) == _componentsSet.end() ||
525 _componentsSet.find( toComponent ) == _componentsSet.end() )
532 bool result = toComponent->ConnectInput( fromComponent, fromOutput, toInput );
534 _circuitDirty = result;
541inline bool Circuit::DisconnectComponent(
const Component::SPtr& component )
543 if ( _componentsSet.find( component ) == _componentsSet.end() )
550 component->DisconnectAllInputs();
553 for (
auto comp : _components )
555 comp->DisconnectInput( component );
558 _circuitDirty =
true;
565inline void Circuit::DisconnectAllComponents()
569 for (
auto component : _components )
571 component->DisconnectAllInputs();
577inline void Circuit::SetBufferCount(
int bufferCount )
581 _bufferCount = bufferCount;
584 for (
auto& circuitThread : _circuitThreads )
586 circuitThread.Stop();
590 if ( _threadCount != 0 )
592 _circuitThreads.resize( 0 );
593 SetThreadCount( _threadCount );
597 _circuitThreads.resize( _bufferCount );
600 for (
int i = 0; i < _bufferCount; ++i )
602 _circuitThreads[i].Start( &_components, i );
606 if ( _currentBuffer >= _bufferCount )
612 for (
auto component : _components )
614 component->SetBufferCount( _bufferCount, _currentBuffer );
620inline int Circuit::GetBufferCount()
const
625inline void Circuit::SetThreadCount(
int threadCount )
629 if ( _threadCount == 0 && threadCount != 0 )
631 _circuitDirty =
true;
634 _threadCount = threadCount;
637 for (
auto& circuitThreads : _circuitThreadsParallel )
639 for (
auto& circuitThread : circuitThreads )
641 circuitThread.Stop();
646 if ( _threadCount == 0 )
648 _circuitThreadsParallel.resize( 0 );
649 SetBufferCount( _bufferCount );
653 _circuitThreadsParallel.resize( _bufferCount == 0 ? 1 : _bufferCount );
654 for (
auto& circuitThread : _circuitThreadsParallel )
656 circuitThread.resize( _threadCount );
661 for (
auto& circuitThreads : _circuitThreadsParallel )
664 for (
auto& circuitThread : circuitThreads )
666 circuitThread.Start( &_componentsParallel, i, j++, _threadCount );
676inline int Circuit::GetThreadCount()
const
681inline void Circuit::Tick()
690 if ( _bufferCount == 0 && _threadCount == 0 )
693 for (
auto component : _components )
695 component->Tick( 0 );
702 else if ( _threadCount != 0 )
704 auto& circuitThreads = _circuitThreadsParallel[_currentBuffer];
706 for (
auto& circuitThread : circuitThreads )
708 circuitThread.Sync();
710 for (
auto& circuitThread : circuitThreads )
712 circuitThread.Resume();
717 _circuitThreads[_currentBuffer].SyncAndResume();
720 if ( _bufferCount != 0 && ++_currentBuffer == _bufferCount )
726inline void Circuit::Sync()
729 for (
auto& circuitThread : _circuitThreads )
731 circuitThread.Sync();
733 for (
auto& circuitThreads : _circuitThreadsParallel )
735 for (
auto& circuitThread : circuitThreads )
737 circuitThread.Sync();
742inline void Circuit::StartAutoTick()
744 _autoTickThread.Start(
this );
747inline void Circuit::StopAutoTick()
749 _autoTickThread.Stop();
753inline void Circuit::PauseAutoTick()
755 _autoTickThread.Pause();
759inline void Circuit::ResumeAutoTick()
761 _autoTickThread.Resume();
764inline void Circuit::Optimize()
774inline void Circuit::_Optimize()
778 std::vector<DSPatch::Component*> orderedComponents;
779 orderedComponents.reserve( _components.size() );
781 for (
auto component : _components )
783 component->Scan( orderedComponents );
785 for (
auto component : _components )
787 component->EndScan();
790 _components = std::move( orderedComponents );
794 if ( _threadCount != 0 )
796 std::vector<std::vector<DSPatch::Component*>> componentsMap;
797 componentsMap.reserve( _components.size() );
800 for (
int i = (
int)_components.size() - 1; i >= 0; --i )
802 _components[i]->ScanParallel( componentsMap, scanPosition );
804 for (
auto component : _components )
806 component->EndScan();
809 _componentsParallel.clear();
810 _componentsParallel.reserve( _components.size() );
811 for (
auto& componentsMapEntry : componentsMap )
813 _componentsParallel.insert( _componentsParallel.end(), componentsMapEntry.begin(), componentsMapEntry.end() );
818 _circuitDirty =
false;
Workspace for adding and routing components.