E-MailRelay
gexceptionsink.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2023 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 gexceptionsink.h
19///
20
21#ifndef G_NET_EXCEPTION_SINK_H
22#define G_NET_EXCEPTION_SINK_H
23
24#include "gdef.h"
25#include "gexceptionhandler.h"
26#include "gexceptionsource.h"
27#include <exception>
28#include <typeinfo>
29
30namespace GNet
31{
32 class ExceptionSink ;
33 class ExceptionSinkUnbound ;
34}
35
36//| \class GNet::ExceptionSink
37/// A tuple containing an ExceptionHandler interface pointer and
38/// a bound 'exception source' pointer.
39///
40/// The EventEmitter and TimerList classes associate an
41/// event handler and ExceptionSink with each event source
42/// (file descriptor or timer). If the event handler throws
43/// an exception then the associated ExceptionHandler's
44/// onException() method is called, via ExceptionSink::call().
45///
46/// An onException() implementation normally just rethrows the
47/// exception to terminate the event loop, but sometimes the
48/// exception can be handled less drastically, perhaps by
49/// deleting the object identified as the exception source.
50///
51/// For example, Server objects create and contain ServerPeer
52/// objects:
53///
54/// \code
55/// class ServerPeer : public ExceptionSource { ... } ;
56/// class Server : private ExceptionHandler
57/// {
58/// void init() { m_peer = newServerPeer(...) ; }
59/// void onException( ExceptionSource * source ... ) override
60/// {
61/// assert( source == m_peer ) ;
62/// delete source ;
63/// }
64/// ServerPeer * m_peer ;
65/// } ;
66/// \endcode
67///
68/// The ExceptionSinkUnbound class is used as a device to force
69/// factory methods to plumb-in an ExceptionSource pointer to
70/// the newly-created object as soon as its address is available
71/// (ie. before the constructor body runs).
72///
73/// \code
74/// class FooServerPeer : public ServerPeer
75/// {
76/// public:
77/// FooServerPeer * newServerPeer( ExceptionSinkUnbound esu , ... ) override
78/// {
79/// return new FooServerPeer( esu , ... ) ;
80/// }
81/// private:
82/// FooServerPeer( ExceptionSinkUnbound esu , ... ) :
83/// ServerPeer( esu.bind(this) , ... )
84/// {
85/// }
86/// } ;
87/// \endcode
88///
89/// So then the ServerPeer constructor has a bound ExceptionSink that
90/// it can pass to its timers and other event-handling objects:
91///
92/// \code
93/// ServerPeer::ServerPeer( ExceptionSink es , ... ) :
94/// m_timer(*this,...,es) ,
95/// m_other(es,...)
96/// {
97/// }
98/// \endcode
99///
101{
102public:
103 ExceptionSink() noexcept ;
104 ///< Default constructor for an exception handler that rethrows.
105 ///< Postcondition: !set()
106
107 ExceptionSink( ExceptionHandler & eh , ExceptionSource * source ) noexcept ;
108 ///< Constructor. The ExceptionHandler reference must
109 ///< remain valid as the ExceptionSink is copied around.
110 ///< Postcondition: set()
111
112 ExceptionSink( ExceptionHandler * eh , ExceptionSource * source ) noexcept ;
113 ///< Constructor. The ExceptionHandler pointer must
114 ///< remain valid as the ExceptionSink is copied around.
115 ///< Precondition: eh != nullptr
116 ///< Postcondition: set()
117
118 ExceptionSink( std::nullptr_t , ExceptionSource * ) = delete ;
119 ///< Deleted override to prohibit a null ExceptionHandler.
120
121 static ExceptionSink logOnly() ;
122 ///< A factory function for an exception handler that logs the
123 ///< exception as an error but does not re-throw. This can
124 ///< be a convenient alternative to a try/catch block for
125 ///< code that might throw but should not terminate a
126 ///< long-running server process.
127
128 static ExceptionSink rethrow() ;
129 ///< A factory function for an exception handler that rethrows.
130
131 ExceptionHandler * eh() const noexcept ;
132 ///< Returns the exception handler pointer.
133
134 ExceptionSource * esrc() const noexcept ;
135 ///< Returns the exception source pointer.
136
137 void call( std::exception & e , bool done ) ;
138 ///< Calls the exception handler's onException() method.
139 ///< Used by EventEmitter and TimerList when handling
140 ///< an exception thrown from an event handler.
141 ///< Precondition: set()
142
143 void reset() noexcept ;
144 ///< Resets the object as if default constructed.
145 ///< Postcondition: !set()
146
147 bool set() const noexcept ;
148 ///< Returns true if eh() is not null.
149
150private:
151 ExceptionHandler * m_eh {nullptr} ;
152 ExceptionSource * m_esrc {nullptr} ;
153} ;
154
155//| \class GNet::ExceptionSinkUnbound
156/// A potential ExceptionSink that is realised by bind()ing an
157/// exception source pointer. This is used in factory functions
158/// such as GNet::Server::newPeer() where the container that
159/// uses the factory function to create a containee needs to
160/// know which containee a subsequent exception came from.
161///
163{
164public:
165 explicit ExceptionSinkUnbound( ExceptionHandler * eh ) ;
166 ///< Constructor.
167
168 explicit ExceptionSinkUnbound( ExceptionHandler & eh ) ;
169 ///< Constructor.
170
171 ExceptionSink bind( ExceptionSource * source ) const ;
172 ///< Returns a sink object with the source pointer set.
173
174private:
175 ExceptionHandler * m_eh {nullptr} ;
176} ;
177
178#endif
An abstract interface for handling exceptions thrown out of event-loop callbacks (socket/future event...
A potential ExceptionSink that is realised by bind()ing an exception source pointer.
ExceptionSinkUnbound(ExceptionHandler *eh)
Constructor.
ExceptionSink bind(ExceptionSource *source) const
Returns a sink object with the source pointer set.
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
ExceptionHandler * eh() const noexcept
Returns the exception handler pointer.
ExceptionSource * esrc() const noexcept
Returns the exception source pointer.
void call(std::exception &e, bool done)
Calls the exception handler's onException() method.
void reset() noexcept
Resets the object as if default constructed.
bool set() const noexcept
Returns true if eh() is not null.
static ExceptionSink logOnly()
A factory function for an exception handler that logs the exception as an error but does not re-throw...
ExceptionSink() noexcept
Default constructor for an exception handler that rethrows.
static ExceptionSink rethrow()
A factory function for an exception handler that rethrows.
A mixin base class that identifies the source of an exception when delivered to GNet::ExceptionHandle...
Network classes.
Definition: gdef.h:1144
STL namespace.