包装的boost :: signals2与终身管理的通用插槽 [英] wrapper for boost::signals2 with lifetime management for generic slots
问题描述
我想为发射信号到插槽的模块(线程)创建一个包装类boost :: signals2。也就是说模块应该通过继承我的Signal类来获得典型的简单信令能力(例如公共连接(...)方法)。我还想隐藏所使用的实际信号时隙实现。
I would like to create a wrapper class for boost::signals2 for modules (threads) that emits signals to slots. I.e. a module should gain typical simple signalling capabilities (e.g. a public connect(...) method) by inheriting from my Signal class. I would also like to hide the actual signal-slot implementation that is used.
一个具体的插槽继承自一个通用的Slot基类,它具有定义其签名的模板参数。
A concrete slot inherits from a generic Slot base class which has a template parameter defining its signature. A slot is just a functor with the suitable signature.
这个问题在某种程度上与这个问题。槽被存储为shared_ptr并且需要生命周期管理。也就是说Signal类应该保持对槽的引用以保持其活动,只要信号本身退出。因此我不能连接std ::函数或类似。
This question is somewhat related to this question. Slots are stored as shared_ptr and lifetime management is required. I.e. the Signal class should hold a reference to the slot to keep it alive as long as the signal itself exits. Hence I cannot connect std::functions or similar. I have to connect shared_ptrs of the slot base class.
我目前的方法,没有线程安全性(MSVC 2010):
My current approach, without thread safety so far (MSVC 2010):
template<class FunSig>
class Slot;
template<class R>
class Slot<R()>
{
public:
typedef R Ret_type;
public:
virtual ~Slot() {}
virtual Ret_type operator()() = 0;
};
template<class R, class A1>
class Slot<R(A1)>
{
public:
typedef R Ret_type;
typedef A1 Arg1_type;
public:
virtual ~Slot() {}
virtual Ret_type operator()(Arg1_type) = 0;
};
// and so forth for more arguments
/*
Signalling class.
This class is basically a wrapper for the boost::signals2 class with
lifetime management for slots.
Slots are connected by a shared_ptr which gets stored
in a std::vector to ensure that a slot exists at least as long as the signal.
*/
template<class FunSig>
class Signal
{
public:
typedef Slot<FunSig> Slot_type;
typedef boost::signals2::signal<FunSig> BoostSignal;
typedef typename BoostSignal::slot_type BoostSlot;
public:
virtual ~Signal() {}
void connectSlot(std::shared_ptr<Slot_type> slot_ptr);
protected:
//void emitSignal( ... );
//void disconnectAllSlots();
private:
BoostSignal sig_;
/// vector of shared_ptr to slots for lifetime management
std::vector<std::shared_ptr<Slot_type> > slotsVec_;
};
template<class FunSig>
void Signal<FunSig>::connectSlot(std::shared_ptr<Slot_type> slot_ptr)
{
sig_.connect(*slot_ptr); // version A: compiler error
// OR
sig_.connect(boost::ref(*slot_ptr)); // version B: warning, but compiles and runs
// add slot pointer to vector of slots
slotsVec_.push_back(slot_ptr);
}
此代码(A版)它打破了内部提升槽slot_template.hpp和在connectSlot方法中标记的行:
This code (version A) does not compile. It breaks inside boosts slot_template.hpp and at the line marked in the connectSlot method:
error C2679: binary '=' : no operator found which takes a right-hand operand of type 'const Slot<FunSig>' (or there is no acceptable conversion)
1> with
1> [
1> FunSig=void (const float &)
有趣的是,如果使用版本B, - 即,一个boost :: ref通过槽。虽然有一个编译器警告使用可能不安全的参数的函数调用 - 这个调用依赖调用者来检查传递的值是否正确。在boost的singals2 auto_buffer.hpp。
Interestingly this code compiles and runs if version B is used instead - i.e. a boost::ref is passed of the slot. Though there is a compiler warning "Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct." in boost's singals2 auto_buffer.hpp.
那么这里的实际问题是什么,如何解决呢?为什么这与boost :: ref工作,为什么它不编译没有它?
So what is the actual problem here and how to solve it? Why does this work with boost::ref and why does it not compile without it?
我甚至不确定整个设计的想法是有用的。最初的想法是将整个信令/槽的东西隐藏在超类中,并专注于签名(并包括生命周期管理)。
I am even unsure it the whole design idea is useful. The original idea was to hide the whole signalling/slot stuff in a superclass and focus on the signature (and include lifetime management).
关于boost信号的另一个问题2: singals2 connect()方法引用一个槽。这是如何处理内部。它使用连接插槽的引用还是制作插槽的副本?这是很重要的,因为我的插槽处理动态分配的内存。
An additional question regarding boost's signals2: the singals2 connect() method takes a reference to a slot. How is this handled internally. Does it use a reference of the connected slot or does it make a copy of the slot? This is important as my slots handle dynamically allocated memory.
推荐答案
此问题已在不同的上下文中回答在这里。
This question has been answered in a different context here.
实际上,必须使用std :: ref或boost :: ref,因为boost :: signals2 connect方法会复制其参数。但类Slot是不可复制的,因为它是一个抽象类。因此,使用boost :: ref是推荐的解决方案,因为它使插槽可复制。
Actually std::ref or boost::ref have to be used because boost::signals2 connect method copies its arguments. But the class Slot is not copyable as it is an abstract class. Hence using boost::ref is the recommended solution because it makes the slot copyable.
这篇关于包装的boost :: signals2与终身管理的通用插槽的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!