Weak pointer for VST
This commit is contained in:
parent
0d6f1b0837
commit
66dec90846
4 changed files with 133 additions and 3 deletions
|
|
@ -35,7 +35,8 @@ set(VSTPLUGIN_HEADERS
|
|||
SfizzSettings.h
|
||||
X11RunLoop.h
|
||||
NativeHelpers.h
|
||||
FileTrie.h)
|
||||
FileTrie.h
|
||||
WeakPtr.h)
|
||||
|
||||
if(APPLE)
|
||||
set(VSTPLUGIN_MAC_SOURCES
|
||||
|
|
|
|||
|
|
@ -143,7 +143,6 @@ IPlugView* PLUGIN_API SfizzVstController::createView(FIDString _name)
|
|||
withStateLock([this]() {
|
||||
_uiState = _editor->getCurrentUiState();
|
||||
});
|
||||
_editor.reset();
|
||||
}
|
||||
|
||||
SfizzVstEditor* editor = new SfizzVstEditor(this);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
#include "SfizzVstController.h"
|
||||
#include "editor/EditorController.h"
|
||||
#include "WeakPtr.h"
|
||||
#include "public.sdk/source/vst/vstguieditor.h"
|
||||
#include <mutex>
|
||||
class Editor;
|
||||
|
|
@ -18,8 +19,11 @@ using namespace Steinberg;
|
|||
using namespace VSTGUI;
|
||||
|
||||
class SfizzVstEditor : public Vst::VSTGUIEditor,
|
||||
public EditorController {
|
||||
public EditorController,
|
||||
public Weakable<SfizzVstEditor> {
|
||||
public:
|
||||
using Self = SfizzVstEditor;
|
||||
|
||||
explicit SfizzVstEditor(SfizzVstController* controller);
|
||||
~SfizzVstEditor();
|
||||
|
||||
|
|
@ -41,6 +45,10 @@ public:
|
|||
SfizzUiState getCurrentUiState() const;
|
||||
void receiveMessage(const void* data, uint32_t size);
|
||||
|
||||
void remember() override { SfizzVstEditor::addRef(); }
|
||||
void forget() override { SfizzVstEditor::release(); }
|
||||
WEAKABLE_REFCOUNT_METHODS(SfizzVstEditor)
|
||||
|
||||
private:
|
||||
void processOscQueue();
|
||||
|
||||
|
|
|
|||
122
vst/WeakPtr.h
Normal file
122
vst/WeakPtr.h
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#pragma once
|
||||
#include "base/source/fobject.h"
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
/**
|
||||
* A weak reference implementation for Steinberg FObject.
|
||||
*
|
||||
* Implementation
|
||||
* ==============
|
||||
*
|
||||
* This takes over the ordinary addRef() and release() methods.
|
||||
* The variable `refCount` is accessed manually, under a shared mutex.
|
||||
* There is a unique data block which is shared with all weak pointers, the
|
||||
* system will null it atomically when the reference count hits zero.
|
||||
*
|
||||
* Usage
|
||||
* =====
|
||||
*
|
||||
* class MyObject : public FObject, public Weakable<MyObject> {
|
||||
* [...]
|
||||
* WEAKABLE_REFCOUNT_METHODS(MyObject)
|
||||
* };
|
||||
*
|
||||
* WeakPtr<MyObject> ptr = myObject.getWeakPtr();
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
class Weakable;
|
||||
|
||||
#define WEAKABLE_REFCOUNT_METHODS(T) \
|
||||
public: \
|
||||
Steinberg::uint32 PLUGIN_API addRef() SMTG_OVERRIDE { return weakAddRef(); } \
|
||||
Steinberg::uint32 PLUGIN_API release() SMTG_OVERRIDE { return weakRelease(); } \
|
||||
private: \
|
||||
friend class Weakable<T>; \
|
||||
friend class WeakPtr<T>;
|
||||
|
||||
///
|
||||
template <class T>
|
||||
struct WeakPtrSharedData : public std::enable_shared_from_this<WeakPtrSharedData<T>> {
|
||||
explicit WeakPtrSharedData(T* self) : self_(self) {}
|
||||
std::mutex mutex_;
|
||||
T* self_ = nullptr;
|
||||
};
|
||||
|
||||
///
|
||||
template <class T>
|
||||
class WeakPtr {
|
||||
friend class Weakable<T>;
|
||||
using SharedData = WeakPtrSharedData<T>;
|
||||
|
||||
public:
|
||||
WeakPtr() = default;
|
||||
|
||||
Steinberg::IPtr<T> lock()
|
||||
{
|
||||
std::shared_ptr<SharedData> data = data_.lock();
|
||||
if (!data)
|
||||
return nullptr;
|
||||
std::lock_guard<std::mutex> lock { data->mutex_ };
|
||||
T* self = data->self_;
|
||||
if (self)
|
||||
++self->refCount; // manually because we are holding the lock
|
||||
return Steinberg::IPtr<T>(self, false);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit WeakPtr(std::weak_ptr<SharedData> data) : data_(data) {}
|
||||
std::weak_ptr<SharedData> data_;
|
||||
};
|
||||
|
||||
///
|
||||
template <class T>
|
||||
class Weakable {
|
||||
using SharedData = WeakPtrSharedData<T>;
|
||||
|
||||
public:
|
||||
Weakable()
|
||||
: weakData_(new SharedData(static_cast<T*>(this)))
|
||||
{
|
||||
}
|
||||
|
||||
WeakPtr<T> getWeakPtr()
|
||||
{
|
||||
return WeakPtr<T>(weakData_);
|
||||
}
|
||||
|
||||
protected:
|
||||
Steinberg::uint32 weakAddRef() //override
|
||||
{
|
||||
T* self = static_cast<T*>(this);
|
||||
std::lock_guard<std::mutex> lock { weakData_->mutex_ };
|
||||
return ++self->refCount;
|
||||
}
|
||||
|
||||
Steinberg::uint32 weakRelease() //override
|
||||
{
|
||||
T* self = static_cast<T*>(this);
|
||||
std::shared_ptr<SharedData> data = weakData_;
|
||||
std::unique_lock<std::mutex> lock { data->mutex_ };
|
||||
Steinberg::uint32 count = --self->refCount;
|
||||
if (count == 0) {
|
||||
data->self_ = nullptr;
|
||||
weakData_.reset();
|
||||
self->refCount = -1000;
|
||||
lock.unlock();
|
||||
delete self;
|
||||
return 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<SharedData> weakData_;
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue