如何将管理器的引用传递给处理程序对象
How to pass a reference of manager to the handler object?
我想做的是写一个小的Manager/Handler类。管理器分发和管理句柄。这样的句柄可以是一个简单的文件句柄。
如果消费者想要获得一个已经存在的句柄,管理器只返回一个shared_ptr。如果句柄不存在,管理器创建一个新的句柄,然后返回shared_ptr。
在管理器内部,这些shared_ptr存储在一个简单的STL-Map中。如果最后一个分配的shared_ptr被删除了,我希望我的管理器删除相关的映射元素,这样处理程序对象就会自动被销毁。
这听起来有点像垃圾收集(例如:worker线程,它检查指针的使用计数),但我相信它可以做得更优雅。
如何将管理器实例的引用传递给处理程序对象?(例如,将unique_ptr(this)传递给新处理程序的构造函数)
#include <memory>
#include <iostream>
#include <map>
using namespace std;
/*
* Simple handler class, that actually does nothing.
* This could be e.g. a Filehandler class or sth. like that
*/
class Handler {
private:
int i;
public:
Handler(int i) :i(i) {}
~Handler() {}
// Say who you are.
void print(void) { cout << "I am handler # " << i << endl; }
};
/*
* This is the "manager" class, that manages all handles. A handle is identified
* by an integer value. If a handle already exists, the Manager returns a shared_ptr,
* if it does not exist, the manager creates a new handle.
*/
class Manager {
private:
map<int, shared_ptr<Handler> > handles;
public:
Manager() {}
~Manager() {}
shared_ptr<Handler> get_handler(int identifier) {
shared_ptr<Handler> retval;
auto it = handles.find(identifier);
if(it != handles.end() ) {
retval = it->second;
} else {
retval = shared_ptr<Handler>(new Handler(identifier));
handles.insert( pair<int, shared_ptr<Handler>>(identifier, retval) );
}
return retval;
}
};
int main(int argc, char** argv) {
Manager m;
// Handler 13 doesn't exist, so it gets allocated
auto h = m.get_handler(13);
// Manager knows about handler 13, so it returns the already existing shared_ptr
auto i = m.get_handler(13);
h.reset(); // Well... Let's assume we don't need h any more...
// do some stuff...
i->print();
// ...
i.reset(); // We also loose i. This is exactly the point where i want the manager to forget about the handle 13
return 0;
}
您可能希望在管理器中保留非拥有的指针以跟踪现有句柄,并通过自定义删除器放弃拥有的shared_ptr
。自定义删除器将确保在对象最终销毁时删除管理器中相应的观察指针。
我将此模式称为跟踪工厂,下面是它的工作原理。给定object
类(在您的情况下将是Handler
):
class object
{
public:
size_t get_id() const
{
return _id;
}
private:
friend class tracking_factory;
object(size_t id) : _id(id) { }
size_t _id = static_cast<size_t>(-1);
};
我定义了一个类,它创建object
的实例并存储对它们的非拥有引用(weak_ptr
)。这个类是唯一一个可以创建object
实例的类——这就是为什么object
的构造函数是私有的,而tracking_factory
被声明为friend
,以便能够访问它:
class tracking_factory
{
public:
std::shared_ptr<object> get_object(size_t id,
bool createIfNotFound = true)
{
auto i = std::find_if(
begin(_objects),
end(_objects),
[id] (std::pair<size_t const, std::weak_ptr<object>> const& p)
-> bool
{
return (p.first == id);
});
if (i != end(_objects))
{
return i->second.lock();
}
else if (createIfNotFound)
{
return make_object(id);
}
else
{
return std::shared_ptr<object>();
}
}
size_t count_instances() const
{
return _objects.size();
}
private:
std::shared_ptr<object> make_object(size_t id)
{
std::shared_ptr<object> sp(
new object(id),
[this, id] (object* p)
{
_objects.erase(id);
delete p;
});
_objects[id] = sp;
return sp;
}
std::map<size_t, std::weak_ptr<object>> _objects;
};
然后,程序的其余部分将通过object_factory
获得shared_ptr
s到object
s:如果已经创建了具有所需特征的对象(这里是id
成员),则将返回其shared_ptr
,而无需实例化新对象。下面是一些测试功能的代码:
#include <iostream>
int main()
{
tracking_factory f;
auto print_object_count = [&f] ()
{
std::cout << "Number of objects: " << f.count_instances() << std::endl;
};
print_object_count();
auto p1 = f.get_object(42);
print_object_count();
{
auto p2 = f.get_object(42);
print_object_count();
p1 = f.get_object(0);
print_object_count();
}
print_object_count();
p1.reset();
print_object_count();
}
最后,这里是一个实际的例子
在地图中存储std::weak_ptr
对象;它们不保留所有权,所以当最后一个std::shared_ptr
对象消失时,资源将被销毁。但是它们会跟踪是否有任何剩余的指向原始对象的std::shared_ptr
对象,因此将它们放入映射中可以让您稍后检查那里是否还有资源。
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 为什么我的 IExtractIcon 处理程序没有被调用?
- 在遍历处理程序的向量时注册和注销处理程序
- 有可能在信号处理程序中设置promise吗
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 通过安装信号处理程序关闭多线程应用程序
- QDateTime::toString() 在退出处理程序中使用时失败
- 如何在 WindowProc 处理程序中区分箭头键和数字键盘?
- async_write完成处理程序最早何时完成?
- C++事件系统 - 多态事件和事件处理程序
- 具有shared_ptr的处理程序中的分段错误
- 为什么我的信号处理程序只执行一次?
- GTK C++:找不到信号处理程序 您是否使用 -rdynamic 进行了编译?
- 如何使用从处理程序调度的最终回调将响应异步返回给调用方on_read?
- C++ 在信号处理程序后继续执行
- wxWidgets 拖放文件事件处理程序初始化问题(无效static_cast)
- 某些 boost::asio 异步函数是否将处理程序连接到操作,以便处理程序被触发一次?
- 没有信号处理程序的POSIX定时器的目的是什么?
- 处理程序的模块列表中有一个错误的模块"WebSocketModule"