70 using SPtr = std::shared_ptr<Component>;
72 enum class ProcessOrder
78 Component( ProcessOrder processOrder = ProcessOrder::InOrder );
81 bool ConnectInput(
const Component::SPtr& fromComponent,
int fromOutput,
int toInput );
83 void DisconnectInput(
int inputNo );
84 void DisconnectInput(
const Component::SPtr& fromComponent );
85 void DisconnectAllInputs();
87 int GetInputCount()
const;
88 int GetOutputCount()
const;
90 std::string GetInputName(
int inputNo )
const;
91 std::string GetOutputName(
int outputNo )
const;
93 void SetBufferCount(
int bufferCount,
int startBuffer );
94 int GetBufferCount()
const;
97 void Tick(
int bufferNo );
99 void TickParallel(
int bufferNo );
101 void Scan( std::vector<Component*>& components );
102 void ScanParallel( std::vector<std::vector<DSPatch::Component*>>& componentsMap,
int& scanPosition );
108 void SetInputCount_(
int inputCount,
const std::vector<std::string>& inputNames = {} );
109 void SetOutputCount_(
int outputCount,
const std::vector<std::string>& outputNames = {} );
112 class AtomicFlag final
115 AtomicFlag(
const AtomicFlag& ) =
delete;
116 AtomicFlag& operator=(
const AtomicFlag& ) =
delete;
118 inline AtomicFlag() =
default;
120 inline AtomicFlag( AtomicFlag&& )
124 inline void WaitAndClear()
126 while ( flag.test_and_set( std::memory_order_acquire ) )
128 std::this_thread::yield();
134 flag.clear( std::memory_order_release );
139 flag.test_and_set( std::memory_order_acquire );
143 std::atomic_flag flag = {
true };
146 struct RefCounter final
150 AtomicFlag readyFlag;
160 void _WaitForRelease(
int bufferNo );
161 void _ReleaseNextBuffer(
int bufferNo );
164 void _GetOutput(
int bufferNo,
int fromOutput,
int toInput,
DSPatch::SignalBus& toBus );
166 void _GetOutputParallel(
int bufferNo,
int fromOutput,
int toInput,
DSPatch::SignalBus& toBus );
168 void _IncRefs(
int output );
169 void _DecRefs(
int output );
171 const DSPatch::Component::ProcessOrder _processOrder;
173 int _bufferCount = 0;
175 std::vector<DSPatch::SignalBus> _inputBuses;
176 std::vector<DSPatch::SignalBus> _outputBuses;
178 std::vector<std::vector<RefCounter>> _refs;
180 std::vector<Wire> _inputWires;
182 std::vector<AtomicFlag> _releaseFlags;
184 std::vector<std::string> _inputNames;
185 std::vector<std::string> _outputNames;
187 int _scanPosition = -1;
190inline Component::Component( ProcessOrder processOrder )
191 : _processOrder( processOrder )
193 SetBufferCount( 1, 0 );
196inline Component::~Component() =
default;
198inline bool Component::ConnectInput(
const Component::SPtr& fromComponent,
int fromOutput,
int toInput )
200 if ( fromOutput >= fromComponent->GetOutputCount() || toInput >= GetInputCount() )
206 auto findFn = [&toInput](
const auto& wire ) {
return wire.toInput == toInput; };
208 if (
auto it = std::find_if( _inputWires.begin(), _inputWires.end(), findFn ); it != _inputWires.end() )
210 if ( it->fromComponent == fromComponent.get() && it->fromOutput == fromOutput )
217 it->fromComponent->_DecRefs( it->fromOutput );
220 for (
auto& inputBus : _inputBuses )
222 inputBus.ClearValue( toInput );
226 it->fromComponent = fromComponent.get();
227 it->fromOutput = fromOutput;
232 _inputWires.emplace_back( Wire{ fromComponent.get(), fromOutput, toInput } );
236 fromComponent->_IncRefs( fromOutput );
241inline void Component::DisconnectInput(
int inputNo )
244 auto findFn = [&inputNo](
const auto& wire ) {
return wire.toInput == inputNo; };
246 if (
auto it = std::find_if( _inputWires.begin(), _inputWires.end(), findFn ); it != _inputWires.end() )
249 it->fromComponent->_DecRefs( it->fromOutput );
252 for (
auto& inputBus : _inputBuses )
254 inputBus.ClearValue( inputNo );
258 _inputWires.erase( it );
262inline void Component::DisconnectInput(
const Component::SPtr& fromComponent )
265 auto findFn = [&fromComponent](
const auto& wire ) {
return wire.fromComponent == fromComponent.get(); };
267 for (
auto it = std::find_if( _inputWires.begin(), _inputWires.end(), findFn ); it != _inputWires.end();
268 it = std::find_if( it, _inputWires.end(), findFn ) )
271 fromComponent->_DecRefs( it->fromOutput );
274 for (
auto& inputBus : _inputBuses )
276 inputBus.ClearValue( it->toInput );
280 it = _inputWires.erase( it );
284inline void Component::DisconnectAllInputs()
287 for (
const auto& wire : _inputWires )
289 wire.fromComponent->_DecRefs( wire.fromOutput );
293 for (
auto& inputBus : _inputBuses )
295 inputBus.ClearAllValues();
302inline int Component::GetInputCount()
const
304 return _inputBuses[0].GetSignalCount();
307inline int Component::GetOutputCount()
const
309 return _outputBuses[0].GetSignalCount();
313inline std::string Component::GetInputName(
int inputNo )
const
315 if ( inputNo < (
int)_inputNames.size() )
317 return _inputNames[inputNo];
323inline std::string Component::GetOutputName(
int outputNo )
const
325 if ( outputNo < (
int)_outputNames.size() )
327 return _outputNames[outputNo];
332inline void Component::SetBufferCount(
int bufferCount,
int startBuffer )
336 if ( bufferCount <= 0 )
341 if ( startBuffer >= bufferCount )
347 _inputBuses.resize( bufferCount );
348 _outputBuses.resize( bufferCount );
350 _releaseFlags.resize( bufferCount );
352 _refs.resize( bufferCount );
354 const auto inputCount = GetInputCount();
355 const auto outputCount = GetOutputCount();
356 const auto refCount = _refs[0].size();
359 for (
int i = 0; i < bufferCount; ++i )
361 _inputBuses[i].SetSignalCount( inputCount );
362 _outputBuses[i].SetSignalCount( outputCount );
364 if ( i == startBuffer )
366 _releaseFlags[i].Set();
370 _releaseFlags[i].Clear();
373 _refs[i].resize( refCount );
374 for (
size_t j = 0; j < refCount; ++j )
377 _refs[i][j].total = _refs[0][j].total;
381 _bufferCount = bufferCount;
384inline int Component::GetBufferCount()
const
389inline void Component::Tick()
391 auto& inputBus = _inputBuses.front();
393 for (
const auto& wire : _inputWires )
396 wire.fromComponent->_GetOutput( wire.fromOutput, wire.toInput, inputBus );
400 Process_( inputBus, _outputBuses.front() );
403inline void Component::Tick(
int bufferNo )
405 auto& inputBus = _inputBuses[bufferNo];
407 for (
const auto& wire : _inputWires )
410 wire.fromComponent->_GetOutput( bufferNo, wire.fromOutput, wire.toInput, inputBus );
413 if ( _bufferCount != 1 && _processOrder == ProcessOrder::InOrder )
416 _WaitForRelease( bufferNo );
419 Process_( inputBus, _outputBuses[bufferNo] );
422 _ReleaseNextBuffer( bufferNo );
427 Process_( inputBus, _outputBuses[bufferNo] );
431inline void Component::TickParallel()
433 auto& inputBus = _inputBuses.front();
435 for (
const auto& wire : _inputWires )
438 wire.fromComponent->_GetOutputParallel( wire.fromOutput, wire.toInput, inputBus );
442 Process_( inputBus, _outputBuses.front() );
445 for (
auto& ref : _refs.front() )
448 if ( ref.total != 0 )
455inline void Component::TickParallel(
int bufferNo )
457 auto& inputBus = _inputBuses[bufferNo];
459 for (
const auto& wire : _inputWires )
462 wire.fromComponent->_GetOutputParallel( bufferNo, wire.fromOutput, wire.toInput, inputBus );
465 if ( _bufferCount != 1 && _processOrder == ProcessOrder::InOrder )
468 _WaitForRelease( bufferNo );
471 Process_( inputBus, _outputBuses[bufferNo] );
474 _ReleaseNextBuffer( bufferNo );
479 Process_( inputBus, _outputBuses[bufferNo] );
483 for (
auto& ref : _refs[bufferNo] )
486 if ( ref.total != 0 )
493inline void Component::Scan( std::vector<Component*>& components )
496 if ( _scanPosition != -1 )
504 for (
const auto& wire : _inputWires )
507 wire.fromComponent->Scan( components );
510 components.emplace_back(
this );
513inline void Component::ScanParallel( std::vector<std::vector<DSPatch::Component*>>& componentsMap,
int& scanPosition )
516 if ( _scanPosition != -1 )
518 scanPosition = _scanPosition;
526 for (
const auto& wire : _inputWires )
529 wire.fromComponent->ScanParallel( componentsMap, scanPosition );
532 _scanPosition = std::max( _scanPosition, ++scanPosition );
536 while ( (
int)componentsMap.size() <= _scanPosition )
538 componentsMap.emplace_back( std::vector<DSPatch::Component*>{} );
539 componentsMap.back().reserve( componentsMap.capacity() );
541 componentsMap[_scanPosition].emplace_back(
this );
544inline void Component::EndScan()
550inline void Component::SetInputCount_(
int inputCount,
const std::vector<std::string>& inputNames )
552 _inputNames = inputNames;
554 for (
auto& inputBus : _inputBuses )
556 inputBus.SetSignalCount( inputCount );
559 _inputWires.reserve( inputCount );
562inline void Component::SetOutputCount_(
int outputCount,
const std::vector<std::string>& outputNames )
564 _outputNames = outputNames;
566 for (
auto& outputBus : _outputBuses )
568 outputBus.SetSignalCount( outputCount );
572 for (
auto& ref : _refs )
574 ref.resize( outputCount );
578inline void Component::_WaitForRelease(
int bufferNo )
580 _releaseFlags[bufferNo].WaitAndClear();
583inline void Component::_ReleaseNextBuffer(
int bufferNo )
585 if ( ++bufferNo == _bufferCount )
587 _releaseFlags[0].Set();
591 _releaseFlags[bufferNo].Set();
595inline void Component::_GetOutput(
int fromOutput,
int toInput,
DSPatch::SignalBus& toBus )
597 auto& signal = *_outputBuses.front().GetSignal( fromOutput );
599 if ( !signal.has_value() )
601 toBus.ClearValue( toInput );
605 auto& ref = _refs.front()[fromOutput];
607 if ( ref.total == 1 )
610 toBus.MoveSignal( toInput, signal );
612 else if ( ++ref.count != ref.total )
615 toBus.SetSignal( toInput, signal );
621 toBus.MoveSignal( toInput, signal );
625inline void Component::_GetOutput(
int bufferNo,
int fromOutput,
int toInput,
DSPatch::SignalBus& toBus )
627 auto& signal = *_outputBuses[bufferNo].GetSignal( fromOutput );
629 if ( !signal.has_value() )
631 toBus.ClearValue( toInput );
635 auto& ref = _refs[bufferNo][fromOutput];
637 if ( ref.total == 1 )
640 toBus.MoveSignal( toInput, signal );
642 else if ( ++ref.count != ref.total )
645 toBus.SetSignal( toInput, signal );
651 toBus.MoveSignal( toInput, signal );
655inline void Component::_GetOutputParallel(
int fromOutput,
int toInput,
DSPatch::SignalBus& toBus )
657 auto& signal = *_outputBuses.front().GetSignal( fromOutput );
658 auto& ref = _refs.front()[fromOutput];
661 ref.readyFlag.WaitAndClear();
663 if ( !signal.has_value() )
665 toBus.ClearValue( toInput );
667 if ( ref.total != 1 )
669 if ( ++ref.count != ref.total )
681 else if ( ref.total == 1 )
684 toBus.MoveSignal( toInput, signal );
686 else if ( ++ref.count != ref.total )
689 toBus.SetSignal( toInput, signal );
696 toBus.MoveSignal( toInput, signal );
700inline void Component::_GetOutputParallel(
int bufferNo,
int fromOutput,
int toInput,
DSPatch::SignalBus& toBus )
702 auto& signal = *_outputBuses[bufferNo].GetSignal( fromOutput );
703 auto& ref = _refs[bufferNo][fromOutput];
706 ref.readyFlag.WaitAndClear();
708 if ( !signal.has_value() )
710 toBus.ClearValue( toInput );
712 if ( ref.total != 1 )
714 if ( ++ref.count != ref.total )
726 else if ( ref.total == 1 )
729 toBus.MoveSignal( toInput, signal );
731 else if ( ++ref.count != ref.total )
734 toBus.SetSignal( toInput, signal );
741 toBus.MoveSignal( toInput, signal );
745inline void Component::_IncRefs(
int output )
747 for (
auto& ref : _refs )
753inline void Component::_DecRefs(
int output )
755 for (
auto& ref : _refs )
Abstract base class for DSPatch components.