1 /*
2     Copyright (c) 2007-2010 iMatix Corporation
3 
4     This file is part of 0MQ.
5 
6     0MQ is free software; you can redistribute it and/or modify it under
7     the terms of the GNU Lesser General Public License as published by
8     the Free Software Foundation; either version 3 of the License, or
9     (at your option) any later version.
10 
11     0MQ is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU Lesser General Public License for more details.
15 
16     You should have received a copy of the GNU Lesser General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "poller_base.hpp"
21 #include "i_poll_events.hpp"
22 #include "err.hpp"
23 
poller_base_t()24 zmq::poller_base_t::poller_base_t ()
25 {
26 }
27 
~poller_base_t()28 zmq::poller_base_t::~poller_base_t ()
29 {
30     //  Make sure there is no more load on the shutdown.
31     zmq_assert (get_load () == 0);
32 }
33 
get_load()34 int zmq::poller_base_t::get_load ()
35 {
36     return load.get ();
37 }
38 
adjust_load(int amount_)39 void zmq::poller_base_t::adjust_load (int amount_)
40 {
41     if (amount_ > 0)
42         load.add (amount_);
43     else if (amount_ < 0)
44         load.sub (-amount_);
45 }
46 
add_timer(int timeout_,i_poll_events * sink_,int id_)47 void zmq::poller_base_t::add_timer (int timeout_, i_poll_events *sink_, int id_)
48 {
49     uint64_t expiration = clock.now_ms () + timeout_;
50     timer_info_t info = {sink_, id_};
51     timers.insert (timers_t::value_type (expiration, info));
52 }
53 
cancel_timer(i_poll_events * sink_,int id_)54 void zmq::poller_base_t::cancel_timer (i_poll_events *sink_, int id_)
55 {
56     //  Complexity of this operation is O(n). We assume it is rarely used.
57     for (timers_t::iterator it = timers.begin (); it != timers.end (); ++it)
58         if (it->second.sink == sink_ && it->second.id == id_) {
59             timers.erase (it);
60             return;
61         }
62 
63     //  Timer not found.
64     zmq_assert (false);
65 }
66 
execute_timers()67 uint64_t zmq::poller_base_t::execute_timers ()
68 {
69     //  Fast track.
70     if (timers.empty ())
71         return 0;
72 
73     //  Get the current time.
74     uint64_t current = clock.now_ms ();
75 
76     //   Execute the timers that are already due.
77     timers_t::iterator it = timers.begin ();
78     while (it != timers.end ()) {
79 
80         //  If we have to wait to execute the item, same will be true about
81         //  all the following items (multimap is sorted). Thus we can stop
82         //  checking the subsequent timers and return the time to wait for
83         //  the next timer (at least 1ms).
84         if (it->first > current)
85             return it->first - current;
86 
87         //  Trigger the timer.
88         it->second.sink->timer_event (it->second.id);
89 
90         //  Remove it from the list of active timers.
91         timers_t::iterator o = it;
92         ++it;
93         timers.erase (o);
94     }
95 
96     //  There are no more timers.
97     return 0;
98 }
99