E-MailRelay

gtimerlist.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2021 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/// \file gtimerlist.h
19///
20
21#ifndef G_NET_TIMER_LIST_H
22#define G_NET_TIMER_LIST_H
23
24#include "gdef.h"
25#include "gdatetime.h"
26#include "gtimer.h"
27#include "geventhandler.h"
28#include "gexception.h"
29#include "gexceptionsink.h"
30#include <utility>
31#include <vector>
32
33 namespace GNet
34{
35 class TimerList ;
36 class TimerBase ;
37 class TimerListTest ;
38}
39
40//| \class GNet::TimerList
41/// A singleton which maintains a list of all Timer objects, and interfaces
42/// to the event loop on their behalf.
43///
44/// Event loops should call TimerList::interval() to determine how long to
45/// wait before the first Timer goes off. If the timed-wait times-out or
46/// if the interval was zero then they must call TimerList::doTimeouts().
47///
48/// There can be a race where this class incorrectly sees no expired timers
49/// in doTimeouts() if, for example, the system clock is being stretched.
50/// However, the interval() or setTimer() time will be very small and the
51/// race will resolve itself naturally.
52///
53/// Every timer has an associated exception handler, typically a
54/// more long-lived object that has the timer as a sub-object.
55/// If the timer callback throws an exception then timer list catches
56/// it and invokes the exception handler -- and if that throws then the
57/// exception escapes the event loop. This is safe even if the exception
58/// handler object is destroyed by the original exception because the
59/// exception handler base-class destructor uses the timer list's disarm()
60/// mechanism. This is the same behaviour as in the EventHandlerList.
61///
62/// Exception handlers are combined with an additional 'source' pointer
63/// in an ExceptionSink tuple. The source pointer can be used to
64/// provide additional information to the exception handler, typically
65/// as a pointer to the event handler (sic) object.
66///
67/// The implementation maintains a pointer to the timer that will
68/// expire soonest so that interval() is fast and O(1) when the set
69/// of timers is stable and most events are non-timer events.
70///
71/// Zero-length timers expire in the same order as they were started,
72/// which allows them to be used as a mechanism for asynchronous
73/// message-passing.
74///
75 class GNet::TimerList
76{
77 public:
78 G_EXCEPTION( NoInstance , "no TimerList instance" ) ;
79
80 TimerList() ;
81 ///< Default constructor.
82
83 ~TimerList() ;
84 ///< Destructor.
85
86 void add( TimerBase & , ExceptionSink ) ;
87 ///< Adds a timer. Called from the Timer constructor.
88
89 void remove( TimerBase & ) noexcept ;
90 ///< Removes a timer from the list. Called from the
91 ///< Timer destructor.
92
93 void updateOnStart( TimerBase & ) ;
94 ///< Called by Timer when a timer is started.
95
96 void updateOnCancel( TimerBase & ) ;
97 ///< Called by Timer when a timer is cancelled.
98
99 std::pair<G::TimeInterval,bool> interval() const ;
100 ///< Returns the interval to the first timer expiry. The second
101 ///< part is an 'infinite' flag that is set if there are no
102 ///< timers running. In pathological cases the interval
103 ///< will be capped at the type's maximum value.
104
105 void doTimeouts() ;
106 ///< Triggers the timeout callbacks of any expired timers.
107 ///< Called by the event loop (GNet::EventLoop). Any exception
108 ///< thrown out of an expired timer's callback is caught and
109 ///< delivered back to the ExceptionSink associated with
110 ///< the timer.
111
112 static bool exists() ;
113 ///< Returns true if instance() exists.
114
115 static TimerList * ptr() noexcept ;
116 ///< Singleton access. Returns nullptr if none.
117
118 static TimerList & instance() ;
119 ///< Singleton access. Throws an exception if none.
120
121 std::string report() const ;
122 ///< Returns a line of text reporting the status of the timer list.
123 ///< Used in debugging and diagnostics.
124
125 void disarm( ExceptionHandler * ) noexcept ;
126 ///< Resets any matching ExceptionHandler pointers.
127
128 private:
129 struct Value /// A value type for the GNet::TimerList.
130 {
131 TimerBase * m_timer{nullptr} ; // handler for the timeout event
132 ExceptionSink m_es ; // handler for any exception thrown
133 Value() ; // for uclibc++
134 Value( TimerBase * t , ExceptionSink es ) ;
135 bool operator==( const Value & v ) const noexcept ;
136 void resetIf( TimerBase * p ) noexcept ;
137 void disarmIf( ExceptionHandler * eh ) noexcept ;
138 } ;
139 using List = std::vector<Value> ;
140 struct Lock /// A RAII class to lock and unlock GNet::TimerList.
141 {
142 explicit Lock( TimerList & ) ;
143 ~Lock() ;
144 Lock( const Lock & ) = delete ;
145 Lock( Lock && ) = delete ;
146 void operator=( const Lock & ) = delete ;
147 void operator=( Lock && ) = delete ;
148 TimerList & m_timer_list ;
149 } ;
150
151 public:
152 TimerList( const TimerList & ) = delete ;
153 TimerList( TimerList && ) = delete ;
154 void operator=( const TimerList & ) = delete ;
155 void operator=( TimerList && ) = delete ;
156
157 private:
158 friend class GNet::TimerListTest ;
159 friend struct Lock ;
160 const TimerBase * findSoonest() const ;
161 void lock() ;
162 void unlock() ;
163 void purgeRemoved() ;
164 void mergeAdded() ;
165 static void removeFrom( List & , TimerBase * ) noexcept ;
166 static void disarmIn( List & , ExceptionHandler * ) noexcept ;
167
168 private:
169 static TimerList * m_this ;
170 mutable const TimerBase * m_soonest{nullptr} ;
171 unsigned int m_adjust{0} ;
172 bool m_locked{false} ;
173 bool m_removed{false} ;
174 List m_list ;
175 List m_list_added ; // temporary list for when add()ed from within doTimeouts()
176} ;
177
178#endif
GNet::ExceptionHandler
An abstract interface for handling exceptions thrown out of event-loop callbacks (socket/future event...
Definition: gexceptionhandler.h:44
GNet::ExceptionSink
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
Definition: gexceptionsink.h:100
GNet::TimerBase
An interface used by GNet::TimerList to keep track of pending timeouts and to deliver timeout events.
Definition: gtimer.h:41
GNet::TimerList
A singleton which maintains a list of all Timer objects, and interfaces to the event loop on their be...
Definition: gtimerlist.h:76
GNet::TimerList::interval
std::pair< G::TimeInterval, bool > interval() const
Returns the interval to the first timer expiry.
Definition: gtimerlist.cpp:149
GNet::TimerList::remove
void remove(TimerBase &) noexcept
Removes a timer from the list.
Definition: gtimerlist.cpp:93
GNet::TimerList::doTimeouts
void doTimeouts()
Triggers the timeout callbacks of any expired timers.
Definition: gtimerlist.cpp:221
GNet::TimerList::exists
static bool exists()
Returns true if instance() exists.
Definition: gtimerlist.cpp:175
GNet::TimerList::disarm
void disarm(ExceptionHandler *) noexcept
Resets any matching ExceptionHandler pointers.
Definition: gtimerlist.cpp:107
GNet::TimerList::updateOnStart
void updateOnStart(TimerBase &)
Called by Timer when a timer is started.
Definition: gtimerlist.cpp:119
GNet::TimerList::instance
static TimerList & instance()
Singleton access. Throws an exception if none.
Definition: gtimerlist.cpp:180
GNet::TimerList::ptr
static TimerList * ptr() noexcept
Singleton access. Returns nullptr if none.
Definition: gtimerlist.cpp:170
GNet::TimerList::TimerList
TimerList()
Default constructor.
Definition: gtimerlist.cpp:76
GNet::TimerList::updateOnCancel
void updateOnCancel(TimerBase &)
Called by Timer when a timer is cancelled.
Definition: gtimerlist.cpp:131
GNet::TimerList::~TimerList
~TimerList()
Destructor.
Definition: gtimerlist.cpp:82
GNet::TimerList::add
void add(TimerBase &, ExceptionSink)
Adds a timer. Called from the Timer constructor.
Definition: gtimerlist.cpp:88
GNet::TimerList::report
std::string report() const
Returns a line of text reporting the status of the timer list.
Definition: gtimerlist.cpp:256
gdatetime.h
geventhandler.h
gexception.h
gexceptionsink.h
gtimer.h
GNet
Network classes.
Definition: gdef.h:1115