如何解决指向 this 的回调智能指针,以便对象在回调中保持活动状态
高达 C++17
我想确保对象在其回调运行期间一直处于活动状态。
这是重要的一点。考虑一个回调函数,它需要来自发出回调的对象的数据。现在我希望让发射对象保持活动状态,直到所说的回调函数得到它需要的东西。这可能不是所有回调的情况,并非所有回调都处理接下来可能被删除的对象。
这是我想出来的。使用命名构造函数习惯用法,我可以确保创建的对象是一个 shared_ptr,然后我可以将一个 weak_ptr 用于它等等。
我想知道是否有更好的方法来解决这个问题?
// Example program
#include <memory>
#include <functional>
#include <iostream>
class Callback
{
public:
using t_callback_func = std::function<void(std::shared_ptr < Callback>)>;
using t_shared = std::shared_ptr<Callback>;
std::vector<t_callback_func> callbacks;
std::weak_ptr<Callback> uglyhax;
static std::shared_ptr<Callback> make()
{
auto shared = std::shared_ptr<Callback>(new Callback());
shared->uglyhax = shared;
return shared;
}
void register_callback(std::function<void(std::shared_ptr<Callback>)> && p_callback)
{
callbacks.emplace_back(std::forward<t_callback_func>(p_callback));
}
void notify()
{
if (auto shared = uglyhax.lock())
{
for (auto & callback : callbacks)
{
callback(shared);
}
}
}
void remove_callbacks()
{
callbacks.clear();
}
void hello()
{
std::cout << "hello " << this << "\n";
}
~Callback() { std::cout << "dtor " << this << "\n"; }
protected:
Callback() { std::cout << "ctor " << this << "\n"; }
};
class EventList
{
std::vector<std::function<void()>> events;
public:
void call_events()
{
for (auto& event : events)
{
event();
}
events.clear();
}
template<class ...Args>
auto wrap_as_event(std::function<void(Args...)> && p_func)
{
return [this,p_func](Args... args)
{
std::cout << "adding event\n";
this->events.emplace_back(std::move(std::bind(std::move(p_func),std::forward<Args>(args)...)));
};
}
};
int main()
{
EventList list;
{
{
auto thing = Callback::make(); // I want to keep the thing allocated here alive until all its callbacks have been processed
std::function<void(Callback::t_shared)> function = [](Callback::t_shared ptr) {ptr->hello(); ptr->remove_callbacks(); };
thing->register_callback(list.wrap_as_event(std::move(function)));
thing->notify();
}
std::cout << "dtor should be called after this\n";
list.call_events();
}
std::cout << "dtor should be called before this\n";
}
输出:
ctor 013E81C0
adding event
dtor should be called after this
hello 013E81C0
dtor 013E81C0
dtor should be called before this
解决方法
您可以将事件执行的逻辑与事件和事件负载对象分开。
Callable
继承了 enable_shared_from_this<Callable>
,允许安全创建额外的 shared_ptr
。工厂方法 getCallable 将在堆上创建一个 Callable 实例,这是 enible_shared_from_this
工作的先决条件。
Callable
类知道如何生成事件以及如何将它的 shared_ptr
注册到 CallableEvent
中,Event
是专门的 Event
类。然后将 EventHandler
发送到将处理事件的 // Example program
#include <memory>
#include <functional>
#include <iostream>
#include <vector>
class Event;
class Callable;
class CallableEvent;
class Event {
public:
virtual void trigger();
};
class EventHandler {
public:
std::vector<std::shared_ptr<Event>> eventList;
static EventHandler& getInstance() {
static EventHandler instance = EventHandler();
return instance;
}
void registerEvent(std::shared_ptr<Event> event) {
eventList.push_back(event);
}
void processEvents() {
for (auto event : eventList) {
event->trigger();
}
}
};
class CallableEvent : public Event,public std::enable_shared_from_this<CallableEvent> {
public:
using t_callback = std::function<void(std::shared_ptr<Callable>)>;
std::shared_ptr<Callable> callable;
t_callback callback;
void trigger() override;
CallableEvent() { std::cout << "Callable Event Created " << this << "\n"; }
~CallableEvent() { std::cout << "Callable Event Destroyed " << this << "\n"; }
};
class Callable : public std::enable_shared_from_this<Callable> {
public:
int _payload;
void registerEvent(std::function<void(std::shared_ptr<Callable>)> lambda) {
std::shared_ptr<CallableEvent> ev = std::shared_ptr<CallableEvent>(new CallableEvent());
ev->callable = shared_from_this();
ev->callback = std::move(lambda);
EventHandler::getInstance().registerEvent(ev);
}
static std::shared_ptr<Callable> createCallable(int payload) {
return std::shared_ptr<Callable>(new Callable(payload));
}
void sayThis() {
std::cout << "Hello from Callable "<< this << " my payload is " << _payload << "\n";
}
~Callable() {
std::cout << "Callable destroyed " << this << " with payload " << _payload << "\n";
}
private:
Callable(int payload) {
_payload = payload;
std::cout << "Callable created " << this << " with payload " << _payload << "\n";
}
};
void Event::trigger() {
std::cout << "generic event \n";
}
void CallableEvent::trigger() {
callback(callable);
}
int main()
{
{
{
auto cb = Callable::createCallable(15);
CallableEvent::t_callback function = [](std::shared_ptr<Callable> ptr) {
std::cout << "Calling from lambda\n";
ptr->sayThis();
};
cb->registerEvent(function);
}
std::cout << "Callback should be called after this\n";
EventHandler::getInstance().processEvents();
}
std::cout << "Callback should be called before this\n";
}
。
Callable created 0x7f89f4c057d0 with payload 15
Callable Event Created 0x7f89f4c05810
Callback should be called after this
Calling from lambda
Hello from Callable 0x7f89f4c057d0 my payload is 15
Callback should be called before this
Callable Event Destroyed 0x7f89f4c05810
Callable destroyed 0x7f89f4c057d0 with payload 15
Process finished with exit code 0
运行示例时,会生成以下输出:
UIDocumentInteractionController
现在您可以将处理程序移动到另一个线程,并且事件将异步执行。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。