Audacity 3.2.0
Public Types | Public Member Functions | Private Attributes | List of all members
internal::ComponentHandler Class Reference

#include <ComponentHandler.h>

Inheritance diagram for internal::ComponentHandler:
[legend]
Collaboration diagram for internal::ComponentHandler:
[legend]

Public Types

using PendingChangesPtr = std::unique_ptr< Steinberg::Vst::IParameterChanges, std::function< void(Steinberg::Vst::IParameterChanges *)> >
 

Public Member Functions

 ComponentHandler ()
 
virtual ~ComponentHandler ()
 
Steinberg::tresult PLUGIN_API beginEdit (Steinberg::Vst::ParamID id) override
 
Steinberg::tresult PLUGIN_API performEdit (Steinberg::Vst::ParamID id, Steinberg::Vst::ParamValue valueNormalized) override
 
Steinberg::tresult PLUGIN_API endEdit (Steinberg::Vst::ParamID id) override
 
Steinberg::tresult PLUGIN_API restartComponent (Steinberg::int32 flags) override
 
PendingChangesPtr getPendingChanges ()
 

Private Attributes

std::atomic< Steinberg::Vst::IParameterChanges * > mFirst { nullptr }
 
std::atomic< Steinberg::Vst::IParameterChanges * > mSecond { nullptr }
 
std::atomic< Steinberg::Vst::IParameterChanges * > mPendingChanges { nullptr }
 

Detailed Description

Stores all pending changes from the editor, and safely transfers them to the processing thread on request. It's lock and wait free (given that there are two threads), but it's theoretically possible that processing thread will never get pending changes, but in real life should never be the case. Current implementation isn't strict about begin/perform/endEdit order correctness(actually it's completely ignored right now, but that might change in future).

Definition at line 40 of file ComponentHandler.h.

Member Typedef Documentation

◆ PendingChangesPtr

using internal::ComponentHandler::PendingChangesPtr = std::unique_ptr< Steinberg::Vst::IParameterChanges, std::function<void (Steinberg::Vst::IParameterChanges*)> >

Definition at line 47 of file ComponentHandler.h.

Constructor & Destructor Documentation

◆ ComponentHandler()

internal::ComponentHandler::ComponentHandler ( )

Definition at line 19 of file ComponentHandler.cpp.

20{
21 //We use two instances of ParameterChanges to ensure
22 //that read/write is lock and wait free.
23 //Once parameter value change is requested, they are
24 //written either to the pending outgoing parameters,
25 //if they are not yet requested, or to any of those
26 //two instances whichever of them is available.
27 //When done writing, parameter changes become pending.
28
29 using namespace Steinberg;
30
31 FUNKNOWN_CTOR
32 auto first = owned(safenew internal::ParameterChanges);
33 auto second = owned(safenew internal::ParameterChanges);
34 if(first && second)
35 {
36 mFirst = first.take();
37 mSecond = second.take();
38 }
39}
#define safenew
Definition: MemoryX.h:10
std::atomic< Steinberg::Vst::IParameterChanges * > mSecond
std::atomic< Steinberg::Vst::IParameterChanges * > mFirst

References mFirst, mSecond, and safenew.

◆ ~ComponentHandler()

internal::ComponentHandler::~ComponentHandler ( )
virtual

Definition at line 41 of file ComponentHandler.cpp.

42{
43 Steinberg::Vst::IParameterChanges* ptr { nullptr };
44 if(ptr = mFirst.load())
45 ptr->release();
46 if(ptr = mSecond.load())
47 ptr->release();
48 if(ptr = mPendingChanges.load())
49 ptr->release();
50
51 FUNKNOWN_DTOR;
52}
std::atomic< Steinberg::Vst::IParameterChanges * > mPendingChanges

Member Function Documentation

◆ beginEdit()

Steinberg::tresult internal::ComponentHandler::beginEdit ( Steinberg::Vst::ParamID  id)
override

Definition at line 54 of file ComponentHandler.cpp.

55{
56 return Steinberg::kResultOk;
57}

◆ endEdit()

Steinberg::tresult internal::ComponentHandler::endEdit ( Steinberg::Vst::ParamID  id)
override

Definition at line 99 of file ComponentHandler.cpp.

100{
101 return Steinberg::kResultOk;
102}

◆ getPendingChanges()

internal::ComponentHandler::PendingChangesPtr internal::ComponentHandler::getPendingChanges ( )

Definition at line 109 of file ComponentHandler.cpp.

110{
111 using namespace Steinberg;
112
113 const auto pendingChanges = mPendingChanges.exchange(nullptr);
114 if(pendingChanges != nullptr)
115 {
116 return PendingChangesPtr { pendingChanges, [handler = IPtr { this }](Vst::IParameterChanges* ptr)
117 {
118 //once the processing thread done reading changes
119 //pointer is moved back
120 ptr = handler->mFirst.exchange(ptr);
121 if(ptr != nullptr)
122 handler->mSecond.exchange(ptr);
123 }};
124 }
125 return { nullptr };
126}
std::unique_ptr< Steinberg::Vst::IParameterChanges, std::function< void(Steinberg::Vst::IParameterChanges *)> > PendingChangesPtr

◆ performEdit()

Steinberg::tresult internal::ComponentHandler::performEdit ( Steinberg::Vst::ParamID  id,
Steinberg::Vst::ParamValue  valueNormalized 
)
override

Definition at line 59 of file ComponentHandler.cpp.

61{
62 using namespace Steinberg;
63
64 //Try grab pending changes first (processing thread will not
65 //see them until they are applied)
66 auto lock = mPendingChanges.exchange(nullptr);
67 if(lock == nullptr)
68 {
69 //There is no pending changes, then try grab
70 //any of the containers. At least one of them always should be
71 //available, but another one may be grabbed by the processing thread
72 lock = mFirst.exchange(nullptr);
73 if(lock == nullptr)
74 lock = mSecond.exchange(nullptr);
75
76 //Grabbed object may contain some old data, clean it.
77 //We surely don't want to delay the processing thread with cleanup
78 //routines
79 static_cast<ParameterChanges*>(lock)->clear();
80 }
81
82 int32 index;
83 tresult result = kInternalError;
84
85 if(const auto queue = lock->addParameterData(id, index))
86 //Since we don't yet have a support for automation,
87 //sampleOffset is always 0
88 result = queue->addPoint(0, valueNormalized, index);
89 //else
90 // for some unknown reason we have failed to
91 // find/create appropriate queue for this parameter
92
93 //now processing thread can see changes
94 mPendingChanges.exchange(lock);
95
96 return result;
97}

◆ restartComponent()

Steinberg::tresult internal::ComponentHandler::restartComponent ( Steinberg::int32  flags)
override

Definition at line 104 of file ComponentHandler.cpp.

105{
106 return Steinberg::kNotImplemented;
107}

Member Data Documentation

◆ mFirst

std::atomic<Steinberg::Vst::IParameterChanges*> internal::ComponentHandler::mFirst { nullptr }
private

Definition at line 42 of file ComponentHandler.h.

Referenced by ComponentHandler().

◆ mPendingChanges

std::atomic<Steinberg::Vst::IParameterChanges*> internal::ComponentHandler::mPendingChanges { nullptr }
private

Definition at line 44 of file ComponentHandler.h.

◆ mSecond

std::atomic<Steinberg::Vst::IParameterChanges*> internal::ComponentHandler::mSecond { nullptr }
private

Definition at line 43 of file ComponentHandler.h.

Referenced by ComponentHandler().


The documentation for this class was generated from the following files: