First take at making the lot thread-safe.
[beacon-ss.git] / beacon / detail / signal_base.cpp
blobb36d1bbb295ff14428f3e6e9b9eeb0626e4cea4b
1 /**
2 * beacon
3 * Author: Lukas Krejci <krejci.l@centrum.cz>, (C) 2008
4 * Copyright: See COPYING file that comes with this distribution
5 */
7 #include <beacon/detail/signal_base.hpp>
8 #include <beacon/detail/connection_impl.hpp>
10 namespace beacon {
12 namespace detail {
14 //a helper function to signal_base::do_disconnect and signal_base::clear
15 void invalidate_slot(signal_base::slot_list_type::iterator & pos) {
16 if (pos->loop != 0) {
17 pos->loop->dequeue(pos->connection->token());
19 delete pos->slot;
22 //a helper for do_connect methods
23 intrusive_ptr<connection_impl_base> signal_base::_init_connection(signal_base::slot_list_item & item) {
25 _slots.push_back(item);
27 connection_impl * inited = new connection_impl(this, --_slots.end());
29 intrusive_ptr<connection_impl_base> ip(inited);
31 slot_list_item & ret = _slots.back();
32 ret.connection.swap(ip);
34 return intrusive_ptr<connection_impl_base>(ret.connection);
37 intrusive_ptr<connection_impl_base> signal_base::do_connect(slot_base * slot, trackable * obj) {
39 slot_list_item item;
40 item.slot = slot;
41 if (obj != 0) {
42 item.loop = obj->current_event_loop();
45 wait(_slots_guard);
47 intrusive_ptr<connection_impl_base> ret = _init_connection(item);
49 //this must be inside lock so that we can be sure that
50 //we do not disconnect the connection before it was inited
51 //in the trackable, otherwise we could have races.
52 if (obj != 0) {
53 obj->add_connection(ret);
56 notify(_slots_guard);
58 return ret;
61 intrusive_ptr<connection_impl_base> signal_base::do_connect(slot_base * slot, event_loop & loop) {
62 slot_list_item item;
63 item.slot = slot;
64 item.loop = &loop;
66 wait(_slots_guard);
68 intrusive_ptr<connection_impl_base> ret = _init_connection(item);
70 notify(_slots_guard);
72 return ret;
75 void signal_base::do_disconnect(slot_list_type::iterator pos) {
76 wait(_slots_guard);
77 invalidate_slot(pos);
78 _slots.erase(pos);
79 notify(_slots_guard);
82 void signal_base::clear() {
83 wait(_slots_guard);
85 for(slot_list_type::iterator it = _slots.begin(); it != _slots.end(); ++it) {
86 invalidate_slot(it);
89 _slots.clear();
91 notify(_slots_guard);
94 signal_base::slot_list_type signal_base::get_slots_copy() {
95 wait(_slots_guard);
96 slot_list_type ret = _slots;
97 notify(_slots_guard);
98 return ret;
101 } //namespace detail
103 } //namespace beacon