renamed from beacon to beacons, bumped version to 0.1.1 for that.
[beacon-ss.git] / src / beacons / event_queue.cpp
blob3947ac9b7cb8b9987827e3d73b81ac937fd1da67
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 <beacons/event_queue.hpp>
8 #include <beacons/detail/quick_wait.hpp>
10 #include <algorithm>
12 namespace beacons {
15 //used by dequeue method to decide whether to remove an invokable from the queue
16 bool token_not_equal(invokable::token_ptr & token, event_queue::ev_ptr inv) {
17 return token.get() != inv->token().get();
20 void invoke_and_delete(event_queue::ev_ptr inv) {
21 try {
22 invokable::token_ptr const & token = inv->token();
24 invokable::token_type::lock_t lock(token->guard());
26 if (token->valid()) {
27 inv->invoke();
30 } catch (...) {
31 //TODO figure out what to do here
33 delete inv;
36 void delete_invokable(event_queue::ev_ptr inv) {
37 delete inv;
40 event_queue::~event_queue() {
41 detail::wait(_queue_guard);
43 std::for_each(_events.begin(), _events.end(), &invoke_and_delete);
44 _events.clear();
46 std::for_each(_dequeued.begin(), _dequeued.end(), &delete_invokable);
47 _dequeued.clear();
49 //don't unlock the queue so that nothing can modify it anymore...
52 void event_queue::enqueue(ev_ptr inv) {
53 //enter the critical section
54 detail::wait(_queue_guard);
56 _events.push_back(inv);
58 //leave the critical section
59 detail::notify(_queue_guard);
62 void event_queue::dequeue(invokable::token_ptr token) {
63 //enter the critical section
64 detail::wait(_queue_guard);
66 std::deque<ev_ptr>::iterator end = _events.end();
68 std::deque<ev_ptr>::iterator first_bad =
69 stable_partition(_events.begin(), end,
70 boost::bind(&token_not_equal, token, _1));
72 _dequeued.insert(first_bad, end);
74 _events.erase(first_bad, end);
76 //leave the critical section
77 detail::notify(_queue_guard);
80 void event_queue::invoke_enqueued() {
81 detail::wait(_queue_guard);
83 std::deque<ev_ptr> evs_cpy;
84 std::set<ev_ptr> deq_cpy;
86 unsigned evs = _events.size();
87 unsigned des = _dequeued.size();
89 //check if there's anything to do at all...
90 if ((evs | des) == 0) {
91 detail::notify(_queue_guard);
92 return;
95 //copy the current events... this is to block the enquing as little
96 //as possible.
97 if (evs > 0) {
98 evs_cpy = _events;
99 _events.clear();
102 if (des > 0) {
103 deq_cpy = _dequeued;
104 _dequeued.clear();
107 detail::notify(_queue_guard);
109 if (evs > 0) {
110 std::for_each(evs_cpy.begin(), evs_cpy.end(), &invoke_and_delete);
113 if (des > 0) {
114 std::for_each(deq_cpy.begin(), deq_cpy.end(), &delete_invokable);
118 void event_queue::invoke_synchronously() {
119 detail::wait(_queue_guard);
121 std::for_each(_events.begin(), _events.end(), &invoke_and_delete);
122 _events.clear();
124 std::for_each(_dequeued.begin(), _dequeued.end(), &delete_invokable);
125 _dequeued.clear();
127 detail::notify(_queue_guard);
130 } //namespace beacons