E-MailRelay
geventstate.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 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 geventstate.h
19///
20
21#ifndef G_NET_EVENT_STATE_H
22#define G_NET_EVENT_STATE_H
23
24#include "gdef.h"
25#include "gexceptionhandler.h"
26#include "gexceptionsource.h"
27#include "geventlogging.h"
28#include <new>
29#include <exception>
30#include <type_traits>
31
32namespace GNet
33{
34 class EventState ;
35 class EventStateUnbound ;
36 class EventLogging ;
37 class TimerList ;
38 class EventLoopImp ;
39}
40
41//| \class GNet::EventState
42/// A lightweight object containing an ExceptionHandler pointer,
43/// optional ExceptionSource pointer and optional EventLogging
44/// pointer. Instances are used in the event loop and timer
45/// list and they are also copied throughout the containment
46/// hierarchy of network and timer objects: the parent object's
47/// EventState object is passed to the constructor of all the
48/// child objects that it contains. When an object regiters with
49/// the event loop it passes its EventState object for the event
50/// loop to use when it calls back with an event. If an object
51/// can outlast its container (eg. GNet::TaskImp) then it must
52/// create() a fresh EventState object, independent of its container.
53///
54/// An ExceptionHandler implementation normally just rethrows the
55/// exception to terminate the event loop, but sometimes the
56/// exception can be handled less drastically, perhaps by
57/// deleting the object identified as the exception source.
58///
59/// For example, Server objects create and contain ServerPeer
60/// objects:
61///
62/// \code
63/// class ServerPeer : public ExceptionSource { ... } ;
64/// class Server : private ExceptionHandler
65/// {
66/// void init() { m_peer = newServerPeer(...) ; }
67/// void onException( ExceptionSource * source ... ) override
68/// {
69/// assert( source == m_peer ) ;
70/// delete source ;
71/// }
72/// ServerPeer * m_peer ;
73/// } ;
74/// \endcode
75///
76/// The EventStateUnbound class is used as a device to force
77/// factory methods to plumb-in an ExceptionSource pointer into
78/// the newly-created object as soon as its address is available,
79/// before the EventState propagates into base classes and
80/// sub-objects.
81///
82/// \code
83/// class FooServer
84/// {
85/// public:
86/// void accept()
87/// {
88/// std::make_unique<FooServerPeer>( m_es.unbound() , ... ) ;
89/// }
90/// EventState m_es ;
91/// } ;
92/// class FooServerPeer : public FooBase , public ExceptionSource
93/// {
94/// public:
95/// FooServerPeer( EventStateUnbound esu , ... ) :
96/// FooBase(esbind(esu,this),...) ,
97/// m_es(esbind(esu,this)) ,
98/// m_sub_object(m_es)
99/// {
100/// }
101/// EventState m_es ; // first
102/// FooItem m_sub_object ; // eg. timer
103/// } ;
104/// \endcode
105///
106/// To automatically set a G::LogOutput logging context during event
107/// processing certain key classes in the containment tree should
108/// override GNet::EventLogging::eventLoggingString() and set the
109/// logging interface pointer in their EventState:
110///
111/// \code
112/// struct Foo : EventLogging , FooBase
113/// {
114/// Foo( EventState es , ... ) :
115/// EventLogging(es.logging()) ,
116/// FooBase(es.logging(this),...) ,
117/// m_es(es.logging(this)) ,
118/// m_event_logging_string("foo: ")
119/// {
120/// }
121/// std::string_view eventLoggingString() const override
122/// {
123/// return m_event_logging_string ;
124/// }
125/// EventState m_es ;
126/// std::string m_event_logging_string ;
127/// } ;
128/// \endcode
129///
131{
132public:
133 struct Private /// Overload discriminator for GNet::EventState.
134 {
135 private:
136 Private() = default ;
137 friend class GNet::EventState ;
138 friend class GNet::EventStateUnbound ;
139 friend class GNet::TimerList ;
140 friend class GNet::EventLoopImp ;
141 friend class GNet::EventStateUnbound ;
142 } ;
143
144 EventState( Private , ExceptionHandler * eh , ExceptionSource * source ) noexcept ;
145 ///< Constructor used by event loops etc. The ExceptionHandler
146 ///< pointer must remain valid as the EventState is copied around.
147
148 EventState esrc( Private , ExceptionSource * ) const noexcept ;
149 ///< Returns a copy of this object with the ExceptionSource
150 ///< pointer set. Used by EventStateUnbound.
151
152 EventState eh( ExceptionHandler * , ExceptionSource * = nullptr ) const noexcept ;
153 ///< Returns a copy of this object with the ExceptionHandler
154 ///< and ExceptionSource set.
155
156 EventState eh( ExceptionHandler & , ExceptionSource * = nullptr ) const noexcept ;
157 ///< Returns a copy of this object with the ExceptionHandler
158 ///< and ExceptionSource set.
159
160 EventState logging( EventLogging * ) const noexcept ;
161 ///< Returns a copy of this object with the ExceptionLogging
162 ///< pointer set to the given value.
163
164 EventStateUnbound unbound() const noexcept ;
165 ///< Returns a copy of this object as type EventStateUnbound
166 ///< with a null ExceptionSource.
167
168 static EventState create() ;
169 ///< A factory function for an exception handler that rethrows.
170
171 static EventState create( std::nothrow_t ) ;
172 ///< A factory function for an exception handler that logs the
173 ///< exception as an error but does not re-throw. This can
174 ///< be a convenient alternative to a try/catch block for
175 ///< code that might throw but should not terminate a
176 ///< long-running server process.
177
178 ExceptionHandler * eh() const noexcept ;
179 ///< Returns the exception handler pointer.
180
181 ExceptionSource * esrc() const noexcept ;
182 ///< Returns the exception source pointer.
183
184 EventLogging * logging() const noexcept ;
185 ///< Returns the event logging pointer.
186
187 bool hasExceptionHandler() const noexcept ;
188 ///< Returns true if eh() is not null.
189
190 void doOnException( std::exception & e , bool done ) ;
191 ///< Calls the exception handler's onException() method.
192 ///< Used by EventEmitter and TimerList when handling
193 ///< an exception thrown from an event handler.
194 ///< Precondition: hasExceptionHandler()
195
196 void disarm() noexcept ;
197 ///< Resets the exception handler.
198 ///< Postcondition: !hasExceptionHandler()
199
200public:
201 void eh( std::nullptr_t , ExceptionSource * ) const = delete ;
202 void logging( std::nullptr_t ) const = delete ;
203
204private:
205 ExceptionHandler * m_eh {nullptr} ;
206 ExceptionSource * m_esrc {nullptr} ;
207 EventLogging * m_logging {nullptr} ;
208} ;
209
210//| \class GNet::EventStateUnbound
211/// The EventStateUnbound class is used as a device to force
212/// factory methods to plumb-in an ExceptionSource pointer
213/// into the newly-created object as soon as its address is
214/// available, before the EventState propagates into base
215/// classes and sub-objects.
216///
217/// The free function GNet::esbind() can be used to bind() the
218/// new EventState in a way that takes account of the type
219/// of the constructed object (see GNet::EventLogging).
220///
221/// Eg:
222/// \code
223/// Foo::Foo( EventStateUnbound ebu , ... )
224/// FooBase(esbind(ebu,this),...) ,
225/// m_sub_object(esbind(ebu,this),...)
226/// {
227/// }
228/// \endcode
229///
231{
232public:
233 explicit EventStateUnbound( EventState ) noexcept ;
234 ///< Constructor. See also EventState::unbound().
235
236private:
237 friend EventState esbindfriend( EventStateUnbound , ExceptionSource * ) noexcept ;
238 EventState bind( ExceptionSource * source ) const noexcept ;
239
240private:
241 EventState m_es ;
242} ;
243
244inline
246{
247 EventState copy( *this ) ;
248 copy.m_eh = eh ;
249 copy.m_esrc = esrc ;
250 return copy ;
251}
252
253inline
255{
256 EventState copy( *this ) ;
257 copy.m_eh = &eh ;
258 copy.m_esrc = esrc ;
259 return copy ;
260}
261
262inline
264{
265 return m_eh ;
266}
267
268inline
270{
271 return m_esrc ;
272}
273
274inline
276{
277 return EventStateUnbound( *this ) ;
278}
279
280inline
282{
283 return m_logging ;
284}
285
286inline
288{
289 return m_eh != nullptr ;
290}
291
292namespace GNet
293{
294 inline EventState esbindfriend( EventStateUnbound esu ,
295 ExceptionSource * esrc ) noexcept
296 {
297 return esu.bind( esrc ) ;
298 }
299
300 template <typename T>
301 EventState esbind( EventStateUnbound esu , T * p )
302 {
303 return esbindfriend( esu , p ) ;
304 }
305}
306
307#endif
An interface for GNet classes that define a logging context string.
Definition: geventlogging.h:47
The EventStateUnbound class is used as a device to force factory methods to plumb-in an ExceptionSour...
Definition: geventstate.h:231
EventStateUnbound(EventState) noexcept
Constructor. See also EventState::unbound().
Definition: geventstate.cpp:93
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
Definition: geventstate.h:131
EventState(Private, ExceptionHandler *eh, ExceptionSource *source) noexcept
Constructor used by event loops etc.
Definition: geventstate.cpp:44
void doOnException(std::exception &e, bool done)
Calls the exception handler's onException() method.
Definition: geventstate.cpp:79
static EventState create()
A factory function for an exception handler that rethrows.
Definition: geventstate.cpp:58
ExceptionHandler * eh() const noexcept
Returns the exception handler pointer.
Definition: geventstate.h:263
void disarm() noexcept
Resets the exception handler.
Definition: geventstate.cpp:85
EventStateUnbound unbound() const noexcept
Returns a copy of this object as type EventStateUnbound with a null ExceptionSource.
Definition: geventstate.h:275
EventLogging * logging() const noexcept
Returns the event logging pointer.
Definition: geventstate.h:281
bool hasExceptionHandler() const noexcept
Returns true if eh() is not null.
Definition: geventstate.h:287
ExceptionSource * esrc() const noexcept
Returns the exception source pointer.
Definition: geventstate.h:269
An abstract interface for handling exceptions thrown out of event-loop callbacks (socket/future event...
A mixin base class that identifies the source of an exception when delivered to GNet::ExceptionHandle...
A singleton which maintains a list of all Timer objects, and interfaces to the event loop on their be...
Definition: gtimerlist.h:71
Network classes.
Definition: gdef.h:1243
STL namespace.
Overload discriminator for GNet::EventState.
Definition: geventstate.h:134