feat(signal): added signal holder to automatically disconnect signals + instance AncestryChanged
This commit is contained in:
parent
0acc2d8857
commit
3b60b3b0ec
4 changed files with 41 additions and 0 deletions
|
@ -72,6 +72,19 @@ void CSignalConnection::Call(std::vector<Data::Variant> args) {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
SignalConnectionHolder::SignalConnectionHolder() : heldConnection() {}
|
||||||
|
SignalConnectionHolder::SignalConnectionHolder(std::shared_ptr<SignalConnection> connection) : heldConnection(connection) {}
|
||||||
|
SignalConnectionHolder::SignalConnectionHolder(Data::SignalConnectionRef other) : heldConnection(other) {}
|
||||||
|
|
||||||
|
SignalConnectionHolder::~SignalConnectionHolder() {
|
||||||
|
// printf("Prediscon!\n");
|
||||||
|
// if (!heldConnection.expired()) printf("Disconnected!\n");
|
||||||
|
if (!heldConnection.expired())
|
||||||
|
heldConnection.lock()->Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
SignalConnectionRef Signal::Connect(std::function<void(std::vector<Data::Variant>)> callback) {
|
SignalConnectionRef Signal::Connect(std::function<void(std::vector<Data::Variant>)> callback) {
|
||||||
auto conn = std::dynamic_pointer_cast<SignalConnection>(std::make_shared<CSignalConnection>(callback, weak_from_this()));
|
auto conn = std::dynamic_pointer_cast<SignalConnection>(std::make_shared<CSignalConnection>(callback, weak_from_this()));
|
||||||
connections.push_back(conn);
|
connections.push_back(conn);
|
||||||
|
@ -96,6 +109,8 @@ SignalConnectionRef Signal::Once(lua_State* state) {
|
||||||
return SignalConnectionRef(conn);
|
return SignalConnectionRef(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
int __waitingThreads = 0;
|
int __waitingThreads = 0;
|
||||||
int Signal::Wait(lua_State* thread) {
|
int Signal::Wait(lua_State* thread) {
|
||||||
// If the table hasn't been constructed yet, make it
|
// If the table hasn't been constructed yet, make it
|
||||||
|
|
|
@ -56,6 +56,27 @@ public:
|
||||||
~LuaSignalConnection();
|
~LuaSignalConnection();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Holds a signal connection such that when the holder is deleted (either via its parent object being deleted, or being overwritten),
|
||||||
|
// the connection is disconnected. Useful to prevent lingering connections that no longer contain valid objects
|
||||||
|
class SignalConnectionHolder {
|
||||||
|
std::weak_ptr<SignalConnection> heldConnection;
|
||||||
|
public:
|
||||||
|
SignalConnectionHolder();
|
||||||
|
SignalConnectionHolder(std::shared_ptr<SignalConnection>);
|
||||||
|
SignalConnectionHolder(Data::SignalConnectionRef other);
|
||||||
|
~SignalConnectionHolder();
|
||||||
|
|
||||||
|
// Prevent SignalConnectionHolder being accidentally copied, making it useless
|
||||||
|
// https://stackoverflow.com/a/10473009/16255372
|
||||||
|
SignalConnectionHolder(const SignalConnectionHolder&) = delete;
|
||||||
|
SignalConnectionHolder& operator=(const SignalConnectionHolder&) = delete;
|
||||||
|
SignalConnectionHolder(SignalConnectionHolder&&) = default;
|
||||||
|
SignalConnectionHolder& operator=(SignalConnectionHolder&&) = default;
|
||||||
|
|
||||||
|
inline bool Connected() { return !heldConnection.expired() && heldConnection.lock()->Connected(); }
|
||||||
|
inline void Disconnect() { if (!heldConnection.expired()) heldConnection.lock()->Disconnect(); }
|
||||||
|
};
|
||||||
|
|
||||||
class Signal : public std::enable_shared_from_this<Signal> {
|
class Signal : public std::enable_shared_from_this<Signal> {
|
||||||
std::vector<std::shared_ptr<SignalConnection>> connections;
|
std::vector<std::shared_ptr<SignalConnection>> connections;
|
||||||
std::vector<std::shared_ptr<SignalConnection>> onceConnections;
|
std::vector<std::shared_ptr<SignalConnection>> onceConnections;
|
||||||
|
|
|
@ -96,6 +96,7 @@ void Instance::updateAncestry(std::optional<std::shared_ptr<Instance>> updatedCh
|
||||||
}
|
}
|
||||||
|
|
||||||
OnAncestryChanged(updatedChild, newParent);
|
OnAncestryChanged(updatedChild, newParent);
|
||||||
|
AncestryChanged->Fire({updatedChild.has_value() ? Data::InstanceRef(updatedChild.value()) : Data::InstanceRef(), newParent.has_value() ? Data::InstanceRef(newParent.value()) : Data::InstanceRef()});
|
||||||
|
|
||||||
// Old workspace used to exist, and workspaces differ
|
// Old workspace used to exist, and workspaces differ
|
||||||
if (!oldWorkspace.expired() && oldWorkspace != _workspace) {
|
if (!oldWorkspace.expired() && oldWorkspace != _workspace) {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "datatypes/signal.h"
|
||||||
#include "error/instance.h"
|
#include "error/instance.h"
|
||||||
#include "error/result.h"
|
#include "error/result.h"
|
||||||
#include "member.h"
|
#include "member.h"
|
||||||
|
@ -93,6 +94,9 @@ public:
|
||||||
const static InstanceType TYPE;
|
const static InstanceType TYPE;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
|
// Signals
|
||||||
|
SignalSource AncestryChanged;
|
||||||
|
|
||||||
// Instance is abstract, so it should not implement GetClass directly
|
// Instance is abstract, so it should not implement GetClass directly
|
||||||
virtual const InstanceType* GetClass() = 0;
|
virtual const InstanceType* GetClass() = 0;
|
||||||
bool SetParent(std::optional<std::shared_ptr<Instance>> newParent);
|
bool SetParent(std::optional<std::shared_ptr<Instance>> newParent);
|
||||||
|
|
Loading…
Add table
Reference in a new issue