connect 过程中 slot 的创建
template<
typename R,
typename T1, typename T2
,
typename Combiner,
typename Group,
typename GroupCompare,
typename SlotFunction
>
signals::connection
signal2<
R, T1, T2
,
Combiner, Group, GroupCompare, SlotFunction
>::connect(const slot_type& in_slot,
signals::connect_position at)
{
using boost::signals::detail::stored_group;
if (!in_slot.is_active()) {
return signals::connection();
}
return impl->connect_slot(in_slot.get_slot_function(), stored_group(),
in_slot.get_data(), at);
}
template<
typename R,
typename T1, typename T2
,
typename Combiner = last_value<R>,
typename Group = int,
typename GroupCompare = std::less<Group>,
typename SlotFunction = function2<
R ,
T1, T2>
>
class signal2 :
public signals::detail::signal_base,
public signals::trackable
{
public:
typedef SlotFunction slot_function_type;
typedef typename signals::detail::slot_result_type<R>::type
slot_result_type;
typedef T1 arg2_type; typedef T2 arg3_type;
typedef T1 first_argument_type;
typedef T2 second_argument_type;
private:
typedef signals::detail::group_bridge_compare<GroupCompare, Group>
real_group_compare_type;
typedef signals::detail::call_bound2<R>
outer_bound_slot_caller;
typedef typename outer_bound_slot_caller::template
caller<T1, T2
,
slot_function_type>
call_bound_slot;
public:
typedef typename Combiner::result_type result_type;
typedef Combiner combiner_type;
typedef slot<slot_function_type> slot_type;
typedef Group group_type;
typedef GroupCompare group_compare_type;
typedef signals::detail::slot_call_iterator<
call_bound_slot, iterator> slot_call_iterator;
explicit
signal2(const Combiner& c = Combiner(),
const GroupCompare& comp = GroupCompare()) :
signals::detail::signal_base(real_group_compare_type(comp),
c)
{
}
signals::connection
connect(const slot_type&,
signals::connect_position at
= signals::at_back);
signals::connection
connect(const group_type&, const slot_type&,
signals::connect_position at
= signals::at_back);
# 220 "/home/Administrator/boost_1_34_1/boost/signals/signaltemplate.hpp"
template<typename T>
void disconnect(const T& t)
{
typedef mpl::bool<(is_convertible<T, group_type>::value)> is_group;
this->do_disconnect(t, is_group());
}
private:
void do_disconnect(const grouptype& group, mpl::bool<true>)
{
impl->disconnect(group);
}
template<typename Function>
void dodisconnect(const Function& f, mpl::bool<false>)
{
signals::detail::callnotification notification(this->impl);
for (iterator i = impl->slots.begin(); i != impl->slots_.end(); ++i) {
slot_function_type& s = unsafe_any_cast<slot_function_type>(&i->second);
if (s == f) i->first.disconnect();
}
}
public:
result_type operator()(T1 a1, T2 a2);
result_type operator()(T1 a1, T2 a2) const;
Combiner& combiner()
{ return unsafe_anycast<Combiner>(&impl->combiner); }
const Combiner& combiner() const
{ return unsafe_anycast<const Combiner>(&impl->combiner); }
};
template<typename SlotFunction>
class slot : public signals::detail::slot_base {
typedef signals::detail::slot_base inherited;
typedef typename inherited::data_t data_t;
public:
template<typename F>
slot(const F& f) : slot_function(signals::get_invocable_slot(f, signals::tag_type(f)))
{
this->data.reset(new data_t);
signals::detail::bound_objects_visitor
do_bind(this->data->bound_objects);
visit_each(do_bind,
signals::get_inspectable_slot
(f, signals::tag_type(f)));
create_connection();
}
# 139 "slot.hpp"
public:
const SlotFunction& get_slot_function() const { return slot_function; }
void release() const { data->watch_bound_objects.set_controlling(false); }
private:
slot();
slot& operator=(const slot&);
SlotFunction slot_function;
};
class slot_base {
public:
struct data_t {
std::vector<const trackable> bound_objects;
connection watch_bound_objects;
};
shared_ptr<data_t> get_data() const { return data; }
std::vector<const trackable>& get_bound_objects() const
{ return data->bound_objects; }
bool is_active() const
{ return data->watch_bound_objects.connected(); }
protected:
void create_connection();
shared_ptr<data_t> data;
private:
static void bound_object_destructed(void, void) {}
};
template<typename Visitor, typename T>
inline void visit_each(Visitor& visitor, const T& t, long)
{
visitor(t);
}
template<typename Visitor, typename T>
inline void visit_each(Visitor& visitor, const T& t)
{
visit_each(visitor, t, 0);
}
// bind.hpp 当 T 为 bind 类型时的特化,负责添加 bind 中的所有 trackable 的子对象
template<class V, class R, class F, class L> void visit_each( V & v, bind_t<R, F, L> const & t, int )
{
t.accept( v );
}
template<bool Cond> struct truth {};
class bound_objects_visitor {
public:
bound_objects_visitor(std::vector<const trackable>& v) :
bound_objects(v)
{
}
template<typename T>
void operator()(const T& t) const
{
decode(t, 0);
}
private:
template<typename T>
void decode(const reference_wrapper<T>& t, int) const
{
add_if_trackable(t.get_pointer());
}
template<typename T>
void decode(const T& t, long) const
{
typedef truth<(is_pointer<T>::value)> is_a_pointer;
maybe_get_pointer(t, is_a_pointer());
}
template<typename T>
void maybe_get_pointer(const T& t, truth<true>) const
{
add_if_trackable(t);
}
template<typename T>
void maybe_get_pointer(const T& t, truth<false>) const
{
add_if_trackable(boost::addressof(t));
}
inline void add_if_trackable(const trackable b) const
{
if (b) {
bound_objects.push_back(b);
}
}
inline void add_if_trackable(const void) const
{
}
template<typename R>
inline void add_if_trackable(R ()()) const
{
}
template<typename R, typename T1>
inline void add_if_trackable(R ()(T1)) const
{
}
… …
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8, typename T9,
typename T10>
inline void
add_if_trackable(R ()(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)) const
{
}
std::vector<const trackable>& bound_objects;
};
class trackable {
private:
static void signal_disconnected(void obj, void data);
friend class detail::signal_base_impl;
friend class detail::slot_base;
void signal_connected(connection, signals::detail::bound_object&) const;
protected:
trackable() : connected_signals(), dying(false) {}
trackable(const trackable&) : connected_signals(), dying(false) {}
~trackable();
trackable& operator=(const trackable&)
{
connected_signals.clear();
return this;
}
private:
typedef std::list<connection> connection_list;
typedef connection_list::iterator connection_iterator;
mutable connection_list connected_signals;
mutable bool dying;
};
void trackable::signal_disconnected(void obj, void data)
{
trackable self = reinterpret_cast<trackable>(obj);
connection_iterator signal =
reinterpret_cast<connection_iterator>(data);
// If we’re dying, don’t bother erasing the connection from the list;
// it’ll be gone anyway
if (!self->dying) {
self->connected_signals.erase(signal);
}
// This iterator pointer won’t ever be used again
delete signal;
}
void
trackable::signal_connected(connection c,
BOOST_SIGNALS_NAMESPACE::detail::bound_object& binding) const
{
// Insert the connection
connection_iterator pos =
connected_signals.insert(connected_signals.end(), c);
// Make this copy of the object disconnect when destroyed
pos->set_controlling();
binding.obj = const_cast<void>(reinterpret_cast<const void>(this));
binding.data = reinterpret_cast<void>(new connection_iterator(pos));
binding.disconnect = &signal_disconnected;
}
trackable::~trackable()
{
dying = true;
}
void slot_base::create_connection()
{
// Create a new connection object
basic_connection con = new basic_connection();
/ nothrow / {
// The signal portion isn’t really necessary, except that we need a
// signal for the connection to be connected.
con->signal = static_cast<void>(this);
con->signaldata = 0;
con->blocked = false ;
con->signal_disconnect = &bound_object_destructed;
}
// This connection watches for destruction of bound objects. Note
// that the reset routine will delete con if an allocation throws
data->watch_bound_objects.reset(con);
// We create a scoped connection, so that exceptions thrown while
// adding bound objects will cause a cleanup of the bound objects
// already connected.
scoped_connection safe_connection(data->watch_bound_objects);
// Now notify each of the bound objects that they are connected to this
// slot.
for(std::vector<const trackable>::iterator i =
data->bound_objects.begin();
i != data->bound_objects.end(); ++i) {
// Notify the object that the slot is connecting to it
BOOST_SIGNALS_NAMESPACE::detail::bound_object binding;
(i)->signal_connected(data->watch_bound_objects, binding);
// This will notify the bound object that the connection just made
// should be disconnected if an exception is thrown before the
// end of this iteration
BOOST_SIGNALS_NAMESPACE::detail::auto_disconnect_bound_object
disconnector(binding);
// Add the binding to the list of bindings for the connection
con->bound_objects.push_back(binding);
// The connection object now knows about the bound object, so if an
// exception is thrown later the connection object will notify the
// bound object of the disconnection automatically
disconnector.release();
}
// No exceptions will be thrown past this point.
safe_connection.release();
data->watch_bound_objects.set_controlling(true);
}
struct basic_connection {
void signal;
void signal_data;
void (signaldisconnect)(void, void);
bool blocked;
std::list<bound_object> bound_objects;
};
class connection :
private less_than_comparable1<connection>,
private equality_comparable1<connection>
{
public:
connection() : con(), controlling_connection(false) {}
connection(const connection&);
~connection();
void block(bool shouldblock = true) { con->blocked = shouldblock; }
void unblock() { con->blocked = false; }
bool blocked() const { return !connected() || con->blocked_; }
void disconnect() const;
bool connected() const { return con.get() && con->signal_disconnect; }
bool operator==(const connection& other) const;
bool operator<(const connection& other) const;
connection& operator=(const connection& other) ;
void swap(connection& other);
public:
void set_controlling(bool control = true)
{ controlling_connection = control; }
shared_ptr<signals::detail::basic_connection>
get_connection() const
{ return con; }
private:
friend class detail::signal_base_impl;
friend class detail::slot_base;
friend class trackable;
void reset(signals::detail::basic_connection);
void add_bound_object(const signals::detail::bound_object& b);
friend class signals::detail::bound_objects_visitor;
shared_ptr<signals::detail::basic_connection> con;
bool controlling_connection;
};
void connection::disconnect() const
{
if (this->connected()) {
// Make sure we have a reference to the basic_connection object,
// because ‘this’ may disappear
shared_ptr<detail::basic_connection> local_con = con;
void (signal_disconnect)(void, void) = local_con->signal_disconnect;
// Note that this connection no longer exists
// Order is important here: we could get into an infinite loop if this
// isn’t cleared before we try the disconnect.
local_con->signal_disconnect = 0;
// Disconnect signal
signal_disconnect(local_con->signal, local_con->signal_data);
// Disconnect all bound objects
typedef std::list<BOOST_SIGNALS_NAMESPACE::detail::bound_object>::iterator iterator;
for (iterator i = local_con->bound_objects.begin();
i != local_con->bound_objects.end(); ++i) {
assert(i->disconnect != 0);
i->disconnect(i->obj, i->data);
}
}
}