锘??xml version="1.0" encoding="utf-8" standalone="yes"?>
//slot_base
class BOOST_SIGNALS_DECL 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*) {}
};
//////////////////////////////////////////////////////////////////////////////////
//slot
template<typename SlotFunction>
class slot : public BOOST_SIGNALS_NAMESPACE::detail::slot_base
{
typedef BOOST_SIGNALS_NAMESPACE::detail::slot_base inherited;
typedef typename inherited::data_t data_t;
public:
template<typename F>
slot(const F& f) : slot_function(BOOST_SIGNALS_NAMESPACE::get_invocable_slot(f, BOOST_SIGNALS_NAMESPACE::tag_type(f)))
{
this->data.reset(new data_t);
BOOST_SIGNALS_NAMESPACE::detail::bound_objects_visitor do_bind(this->data->bound_objects);
visit_each(do_bind,
BOOST_SIGNALS_NAMESPACE::get_inspectable_slot
(f, BOOST_SIGNALS_NAMESPACE::tag_type(f)));
create_connection();
}
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;
};
//////////////////////////////////////////////////////////////////////////
//slot_base::create_connection
void slot_base::create_connection()
{
basic_connection* con = new basic_connection();
{
con->signal = static_cast<void*>(this);
con->signal_data = 0;
con->blocked_ = false ;
con->signal_disconnect = &bound_object_destructed;
}
data->watch_bound_objects.reset(con);
scoped_connection safe_connection(data->watch_bound_objects);
for(std::vector<const trackable*>::iterator i = data->bound_objects.begin();
i != data->bound_objects.end(); ++i)
{
BOOST_SIGNALS_NAMESPACE::detail::bound_object binding;
(*i)->signal_connected(data->watch_bound_objects, binding);
BOOST_SIGNALS_NAMESPACE::detail::auto_disconnect_bound_object disconnector(binding);
con->bound_objects.push_back(binding);
disconnector.release();
}
safe_connection.release();
data->watch_bound_objects.set_controlling(true);
}
if (!in_slot.is_active())
{
return BOOST_SIGNALS_NAMESPACE::connection();
}
return impl->connect_slot(in_slot.get_slot_function(), stored_group(),
in_slot.get_data(), at); //璋冪敤浜唖ignal_base_impl鐨刢onnect_slot
}
slot鐨勬瀯閫犲嚱鏁扮畝鐗堜吉鐮?/p>
slot(const function& f) : slot_function(get_invocable_slot(f, tag_type(f)))
{
this->data.reset(new data_t);
basic_connection* con = new basic_connection();
con->signal = static_cast<void*>(this);
con->signal_data = 0;
con->blocked_ = false ;
con->signal_disconnect = &bound_object_destructed;
data->watch_bound_objects.reset(con);
data->watch_bound_objects.set_controlling(true);
}
connection signal_base_impl::connect_slot(const any& slot_, //榪欓噷鍏跺疄浼犲叆鐨勬槸function
銆銆銆銆銆銆銆銆銆銆銆銆銆銆 const stored_group& name,
銆銆銆銆銆銆銆銆銆銆銆銆銆銆 shared_ptr<slot_base::data_t> data, //slot鏋勯犵殑鐢ㄦ潵瀛樺偍淇″彿婧愪俊鎭殑緇撴瀯
銆銆銆銆銆銆銆銆銆銆銆銆銆銆 connect_position at)
{
data->watch_bound_objects.set_controlling(false);
scoped_connection safe_connection(data->watch_bound_objects);
std::auto_ptr<iterator> saved_iter(new iterator);
iterator pos =銆slots_.insert(name, data->watch_bound_objects, slot_, at); //灝嗚繛鎺ヤ笌function鎻掑叆鍒癿ap涓?/p>
*saved_iter = pos;
data->watch_bound_objects.get_connection()->signal = this; //榪炴帴鐨剆ignal
data->watch_bound_objects.get_connection()->signal_data =銆saved_iter.release(); //鍦ㄥ鍣ㄤ腑鐨勮凱浠d綅瀛?br> data->watch_bound_objects.get_connection()->signal_disconnect =銆&signal_base_impl::slot_disconnected; //鏂紑榪炴帴鐨勫嚱鏁?/p>
pos->first.set_controlling();
return safe_connection.release();
}
//map鐨勬彃鍏ワ紝灝嗕竴涓繛鎺ュ拰function緇勬垚涓涓猵air錛屾彃鍏ュ埌map涓?br>named_slot_map::iterator
named_slot_map::insert(const stored_group& name, const connection& con,
const any& slot, connect_position at)
{
group_iterator group;
if (name.empty()) {
switch (at) {
case at_front: group = groups.begin(); break;
case at_back: group = back; break;
}
} else {
group = groups.find(name);
if (group == groups.end()) {
slot_container_type::value_type v(name, group_list());
group = groups.insert(v).first;
}
}
iterator it;
it.group = group;
it.last_group = groups.end();
switch (at) {
case at_back:
group->second.push_back(connection_slot_pair(con, slot));
it.slot_ = group->second.end();
it.slot_assigned = true;
--(it.slot_);
break;
case at_front:
group->second.push_front(connection_slot_pair(con, slot));
it.slot_ = group->second.begin();
it.slot_assigned = true;
break;
}
return it;
}
榪炴帴鐨勭粨鏋?br>struct basic_connection
{
void* signal; //signal瀵硅薄鎸囬拡錛屾槸榪欎釜connection鐨勭鐞嗚?br> void* signal_data; //鍦╯ignal涓殑slot綆$悊鍣ㄤ腑鐨勮凱浠e櫒瀵硅薄鐨勬寚閽?br> void (*signal_disconnect)(void*, void*); //瑙i櫎榪炴帴鐨勫嚱鏁版墽鏀?br> bool blocked_;
std::list<bound_object> bound_objects;
};
class BOOST_SIGNALS_DECL connection :
private less_than_comparable1<connection>,
private equality_comparable1<connection>
{
public:
connection() : con(), controlling_connection(false) {}
connection(const connection&);
~connection();
// Block he connection: if the connection is still active, there
// will be no notification
void block(bool should_block = true) { con->blocked_ = should_block; }
void unblock() { con->blocked_ = false; }
bool blocked() const { return !connected() || con->blocked_; }
// Disconnect the signal and slot, if they are connected
void disconnect() const;
// Returns true if the signal and slot are connected
bool connected() const { return con.get() && con->signal_disconnect; }
// Comparison of connections
bool operator==(const connection& other) const;
bool operator<(const connection& other) const;
// Connection assignment
connection& operator=(const connection& other) ;
// Swap connections
void swap(connection& other);
public: // TBD: CHANGE THIS
// Set whether this connection object is controlling or not
void set_controlling(bool control = true)
{ controlling_connection = control; }
shared_ptr<BOOST_SIGNALS_NAMESPACE::detail::basic_connection>
get_connection() const
{ return con; }
private:
friend class detail::signal_base_impl;
friend class detail::slot_base;
friend class trackable;
// Reset this connection to refer to a different actual connection
void reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection*);
// Add a bound object to this connection (not for users)
void add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b);
friend class BOOST_SIGNALS_NAMESPACE::detail::bound_objects_visitor;
// Pointer to the actual contents of the connection
shared_ptr<BOOST_SIGNALS_NAMESPACE::detail::basic_connection> con;
// True if the destruction of this connection object should disconnect
bool controlling_connection;
};