VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gclientptr.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
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 gclientptr.h
19 ///
20 
21 #ifndef G_SMTP_CLIENT_PTR_H
22 #define G_SMTP_CLIENT_PTR_H
23 
24 #include "gdef.h"
25 #include "gnet.h"
26 #include "gclient.h"
27 #include "gexception.h"
28 #include "gassert.h"
29 #include "gslot.h"
30 #include <memory>
31 
32 namespace GNet
33 {
34 
35 /// \class ClientPtr
36 /// A smart pointer class for GNet::HeapClient that keeps track of when the
37 /// contained instance deletes itself. When the smart pointer goes out of
38 /// scope the HeapClient object is told to delete itself asynchronously
39 /// using its doDelete() mechanism. The HeapClient's slots-and-signals
40 /// are managed automatically so that client code does not have to
41 /// disconnect and reconnect them.
42 ///
43 template <typename TClient>
44 class ClientPtr
45 {
46 public:
47  G_EXCEPTION( InvalidState , "invalid state of smtp client" ) ;
48 
49  explicit ClientPtr( TClient * p = nullptr ) ;
50  ///< Constructor. Takes ownership of the new-ed client.
51 
52  ~ClientPtr() ;
53  ///< Destructor.
54 
55  bool busy() const ;
56  ///< Returns true if the pointer is not nullptr.
57 
58  void reset( TClient * p = nullptr ) ;
59  ///< Resets the pointer.
60 
61  TClient * get() ;
62  ///< Returns the pointer, or nullptr if deleted.
63 
64  TClient * operator->() ;
65  ///< Returns the pointer. Throws if deleted.
66 
67  const TClient * operator->() const ;
68  ///< Returns the pointer. Throws if deleted.
69 
71  ///< Returns a signal which indicates that client processing
72  ///< is complete and the client instance has deleted
73  ///< itself. The signal parameter is the failure
74  ///< reason.
75 
77  ///< Returns a signal which indicates something interesting.
78 
80  ///< Returns a signal which indicates that the
81  ///< connection has been established successfully.
82 
83  void releaseForExit() ;
84  ///< Can be called on program termination when there may
85  ///< be no TimerList or EventLoop instances.
86  ///< The client object leaks.
87 
88  void cleanupForExit() ;
89  ///< Can be called on program termination when there may
90  ///< be no TimerList or EventLoop instances. The client
91  ///< is destructed so all relevant destructors should
92  ///< avoid doing anything with timers or the network
93  ///< (possibly even just closing sockets).
94 
95 private:
96  ClientPtr( const ClientPtr & ) ; // not implemented
97  void operator=( const ClientPtr & ) ; // not implemented
98  void doneSlot( std::string ) ;
99  void eventSlot( std::string , std::string ) ;
100  void connectedSlot() ;
101  void connectSignalsToSlots() ;
102  void disconnectSignals() ;
103 
104 private:
105  TClient * m_p ;
106  G::Slot::Signal1<std::string> m_done_signal ;
108  G::Slot::Signal0 m_connected_signal ;
109 } ;
110 
111 template <typename TClient>
113  m_p(p)
114 {
115  try
116  {
117  connectSignalsToSlots() ;
118  }
119  catch(...)
120  {
121  // should p->doDelete() here
122  throw ;
123  }
124 }
125 
126 template <typename TClient>
128 {
129  if( m_p != nullptr )
130  {
131  disconnectSignals() ;
132  m_p->doDelete(std::string()) ;
133  }
134 }
135 
136 template <typename TClient>
138 {
139  if( m_p != nullptr )
140  {
141  disconnectSignals() ;
142  m_p = nullptr ;
143  }
144 }
145 
146 template <typename TClient>
148 {
149  if( m_p != nullptr )
150  {
151  disconnectSignals() ;
152  TClient * p = m_p ;
153  m_p = nullptr ;
154  p->doDeleteForExit() ;
155  }
156 }
157 
158 template <typename TClient>
160 {
161  if( m_p != nullptr )
162  {
163  m_p->doneSignal().connect( G::Slot::slot(*this,&ClientPtr::doneSlot) ) ;
164  m_p->eventSignal().connect( G::Slot::slot(*this,&ClientPtr::eventSlot) ) ;
165  m_p->connectedSignal().connect( G::Slot::slot(*this,&ClientPtr::connectedSlot) ) ;
166  }
167 }
168 
169 template <typename TClient>
170 void ClientPtr<TClient>::reset( TClient * p )
171 {
172  disconnectSignals() ;
173 
174  TClient * old = m_p ;
175  m_p = p ;
176  if( old != nullptr )
177  {
178  old->doDelete( std::string() ) ;
179  }
180 
181  connectSignalsToSlots() ;
182 }
183 
184 template <typename TClient>
186 {
187  return m_done_signal ;
188 }
189 
190 template <typename TClient>
192 {
193  return m_event_signal ;
194 }
195 
196 template <typename TClient>
198 {
199  return m_connected_signal ;
200 }
201 
202 template <typename TClient>
203 void ClientPtr<TClient>::doneSlot( std::string reason )
204 {
205  G_ASSERT( m_p != nullptr ) ;
206  disconnectSignals() ;
207  m_p = nullptr ;
208  m_done_signal.emit( reason ) ;
209 }
210 
211 template <typename TClient>
212 void ClientPtr<TClient>::disconnectSignals()
213 {
214  if( m_p != nullptr )
215  {
216  m_p->doneSignal().disconnect() ;
217  m_p->eventSignal().disconnect() ;
218  m_p->connectedSignal().disconnect() ;
219  }
220 }
221 
222 template <typename TClient>
223 void ClientPtr<TClient>::connectedSlot()
224 {
225  G_ASSERT( m_p != nullptr ) ;
226  m_connected_signal.emit() ;
227 }
228 
229 template <typename TClient>
230 void ClientPtr<TClient>::eventSlot( std::string s1 , std::string s2 )
231 {
232  m_event_signal.emit( s1 , s2 ) ;
233 }
234 
235 template <typename TClient>
237 {
238  return m_p ;
239 }
240 
241 template <typename TClient>
243 {
244  return m_p != nullptr ;
245 }
246 
247 template <typename TClient>
249 {
250  if( m_p == nullptr )
251  throw InvalidState() ;
252  return m_p ;
253 }
254 
255 template <typename TClient>
256 const TClient * ClientPtr<TClient>::operator->() const
257 {
258  if( m_p == nullptr )
259  throw InvalidState() ;
260  return m_p ;
261 }
262 
263 }
264 
265 #endif
TClient * get()
Returns the pointer, or nullptr if deleted.
Definition: gclientptr.h:236
G::Slot::Signal0 & connectedSignal()
Returns a signal which indicates that the connection has been established successfully.
Definition: gclientptr.h:197
void releaseForExit()
Can be called on program termination when there may be no TimerList or EventLoop instances.
Definition: gclientptr.h:137
G::Slot::Signal2< std::string, std::string > & eventSignal()
Returns a signal which indicates something interesting.
Definition: gclientptr.h:191
void reset(TClient *p=nullptr)
Resets the pointer.
Definition: gclientptr.h:170
void cleanupForExit()
Can be called on program termination when there may be no TimerList or EventLoop instances.
Definition: gclientptr.h:147
~ClientPtr()
Destructor.
Definition: gclientptr.h:127
Slot0 slot(T &object, void(T::*fn)())
A slot factory function overloaded for a zero-parameter callback.
Definition: gslot.h:209
ClientPtr(TClient *p=nullptr)
Constructor. Takes ownership of the new-ed client.
Definition: gclientptr.h:112
G::Slot::Signal1< std::string > & doneSignal()
Returns a signal which indicates that client processing is complete and the client instance has delet...
Definition: gclientptr.h:185
A signal class for zero-parameter callbacks.
Definition: gslot.h:193
A smart pointer class for GNet::HeapClient that keeps track of when the contained instance deletes it...
Definition: gclientptr.h:44
TClient * operator->()
Returns the pointer. Throws if deleted.
Definition: gclientptr.h:248
bool busy() const
Returns true if the pointer is not nullptr.
Definition: gclientptr.h:242