- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gtimerlist.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gtimerlist.cpp
19 //
20
21 #include "gdef.h"
22 #include "gtimerlist.h"
23 #include "gtimer.h"
24 #include "geventloop.h"
25 #include "glog.h"
26
27 GNet::TimerList * GNet::TimerList::m_this = NULL ;
28
29 GNet::TimerList::TimerList() :
30 m_run_on_destruction(true) ,
31 m_list_changed(false) ,
32 m_empty_set_timeout_hint(false) ,
33 m_soonest_changed(true) ,
34 m_soonest(99U)
35 {
36 if( m_this == NULL )
37 m_this = this ;
38 }
39
40 GNet::TimerList::~TimerList()
41 {
42 if( m_run_on_destruction )
43 {
44 try
45 {
46 doTimeouts() ;
47 }
48 catch(...)
49 {
50 }
51 }
52
53 if( m_this == this )
54 m_this = NULL ;
55 }
56
57 void GNet::TimerList::add( AbstractTimer & t )
58 {
59 m_list_changed = true ;
60 m_list.push_back( &t ) ;
61 }
62
63 void GNet::TimerList::remove( AbstractTimer & t )
64 {
65 for( List::iterator p = m_list.begin() ; p != m_list.end() ; ++p )
66 {
67 if( *p == &t )
68 {
69 *p = NULL ;
70 break ;
71 }
72 }
73 }
74
75 void GNet::TimerList::update( G::DateTime::EpochTime t_old )
76 {
77 // after any change in the soonest() time notify the event loop
78
79 G::DateTime::EpochTime t_new = soonest() ;
80 if( t_old != t_new )
81 {
82 m_soonest_changed = true ;
83 if( EventLoop::exists() )
84 {
85 G_DEBUG( "GNet::TimerList::update: " << t_old << " -> " << t_new ) ;
86 EventLoop::instance().setTimeout( t_new , m_empty_set_timeout_hint ) ;
87 }
88 }
89 }
90
91 void GNet::TimerList::update()
92 {
93 // this overload just assumes that the soonest() time has probably changed
94
95 m_soonest_changed = true ;
96 if( EventLoop::exists() )
97 {
98 G::DateTime::EpochTime t_new = soonest() ;
99 G_DEBUG( "GNet::TimerList::update: ? -> " << t_new ) ;
100 EventLoop::instance().setTimeout( t_new , m_empty_set_timeout_hint ) ;
101 }
102 }
103
104 G::DateTime::EpochTime GNet::TimerList::soonest() const
105 {
106 G::DateTime::EpochTime result = 0U ;
107 const List::const_iterator end = m_list.end() ;
108 for( List::const_iterator p = m_list.begin() ; p != end ; ++p )
109 {
110 if( *p != NULL && (*p)->t() != 0UL && ( result == 0U || (*p)->t() < result ) )
111 result = (*p)->t() ;
112 }
113 return result ;
114 }
115
116 G::DateTime::EpochTime GNet::TimerList::soonest( int ) const
117 {
118 // this optimised overload is for interval() which
119 // gets called on _every_ fd event
120
121 if( m_soonest_changed )
122 {
123 TimerList * This = const_cast<TimerList*>(this) ;
124 This->m_soonest = soonest() ;
125 This->m_soonest_changed = false ;
126 }
127 //G_ASSERT( valid() ) ; // optimisation lost if this is active
128 return m_soonest ;
129 }
130
131 bool GNet::TimerList::valid() const
132 {
133 if( soonest() != m_soonest )
134 {
135 G_ERROR( "GNet::TimerList::valid: soonest()=" << soonest() << ", m_soonest=" << m_soonest ) ;
136 return false ;
137 }
138 return true ;
139 }
140
141 unsigned int GNet::TimerList::interval( bool & infinite ) const
142 {
143 G::DateTime::EpochTime then = soonest(0) ; // fast
144 infinite = then == 0U ;
145 if( infinite )
146 {
147 return 0U ;
148 }
149 else
150 {
151 G::DateTime::EpochTime now = G::DateTime::now() ;
152 return now >= then ? 0U : static_cast<unsigned int>(then-now) ;
153 }
154 }
155
156 GNet::TimerList * GNet::TimerList::instance( const NoThrow & )
157 {
158 return m_this ;
159 }
160
161 GNet::TimerList & GNet::TimerList::instance()
162 {
163 if( m_this == NULL )
164 throw NoInstance() ;
165
166 return * m_this ;
167 }
168
169 void GNet::TimerList::doTimeouts()
170 {
171 G_DEBUG( "GNet::TimerList::doTimeouts" ) ;
172 G::DateTime::EpochTime now = G::DateTime::now() ;
173
174 for( List::iterator p = m_list.begin() ; p != m_list.end() ; ++p )
175 {
176 if( *p != NULL )
177 {
178 G::DateTime::EpochTime t = (*p)->t() ;
179 if( t != 0U && now >= t )
180 {
181 (*p)->doTimeout() ;
182 }
183 }
184 }
185
186 // deal with any change in the soonest() time
187 update() ;
188 }
189
190 void GNet::TimerList::collectGarbage()
191 {
192 for( List::iterator p = m_list.begin() ; p != m_list.end() ; )
193 {
194 if( *p == NULL )
195 p = m_list.erase( p ) ;
196 else
197 ++p ;
198 }
199 }
200
G::DateTime::now
static EpochTime now()
Returns the current epoch time.
Definition: gdatetime.cpp:34
GNet::TimerList::remove
void remove(AbstractTimer &)
Removes a timer from the list.
Definition: gtimerlist.cpp:63
GNet::TimerList::add
void add(AbstractTimer &)
Adds a timer. Used by Timer::Timer().
Definition: gtimerlist.cpp:57
G::DateTime::EpochTime
std::time_t EpochTime
Definition: gdatetime.h:41
GNet::TimerList::update
void update(G::DateTime::EpochTime previous_soonest)
Called when one of the list's timers has changed.
Definition: gtimerlist.cpp:75
glog.h
gtimerlist.h
GNet::TimerList::soonest
G::DateTime::EpochTime soonest() const
Returns the time of the first timer to expire, or zero if none.
Definition: gtimerlist.cpp:104
GNet::TimerList::TimerList
TimerList()
Default constructor.
Definition: gtimerlist.cpp:29
GNet::TimerList::NoThrow
Overload discriminator class for TimerList.
Definition: gtimerlist.h:47
GNet::TimerList
A singleton which maintains a list of all Timer objects, and interfaces to the event loop on their be...
Definition: gtimerlist.h:42
geventloop.h
GNet::TimerList::interval
unsigned int interval(bool &infinite) const
Returns the interval to the next timer expiry.
Definition: gtimerlist.cpp:141
GNet::TimerList::instance
static TimerList & instance()
Singleton access. Throws an exception if none.
Definition: gtimerlist.cpp:161
gtimer.h
G_ERROR
#define G_ERROR(expr)
Definition: glog.h:108
GNet::EventLoop::setTimeout
virtual void setTimeout(G::DateTime::EpochTime t, bool &empty_implementation_hint)=0
Used by GNet::TimerList.
GNet::TimerList::doTimeouts
void doTimeouts()
Triggers the timeout callbacks of any expired timers.
Definition: gtimerlist.cpp:169
G_DEBUG
#define G_DEBUG(expr)
Definition: glog.h:95
GNet::TimerList::~TimerList
~TimerList()
Destructor.
Definition: gtimerlist.cpp:40
GNet::EventLoop::exists
static bool exists()
Returns true if an instance exists.
Definition: geventloop.cpp:51
GNet::EventLoop::instance
static EventLoop & instance()
Returns a reference to an instance of the class, if any.
Definition: geventloop.cpp:43
GNet::AbstractTimer
A timer base class that calls a pure virtual method on expiry.
Definition: gtimer.h:41