VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gvclientholder.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 gvclientholder.h
19 ///
20 
21 #ifndef GV_CLIENT_HOLDER__H
22 #define GV_CLIENT_HOLDER__H
23 
24 #include "gdef.h"
25 #include "gnet.h"
26 #include "gtimer.h"
27 #include "geventloop.h"
28 #include "gclientptr.h"
29 #include "glog.h"
30 
31 namespace Gv
32 {
33 
34 /// \class Gv::ClientHolder
35 /// Manages a network client object so that the network client is
36 /// automatically re-created from a factory when it finishes, or
37 /// alternatively the event loop is quit()ed.
38 ///
39 template <typename TFactory, typename TClient>
41 {
42 public:
43  explicit ClientHolder( TFactory & factory , bool once = false ,
44  bool (*quit_test_fn)(std::string) = nullptr , unsigned int reconnect_timeout = 1U ) ;
45  ///< Constructor that creates a network client object from a factory.
46  ///<
47  ///< The quit-test function should return true if the onDone()
48  ///< reason is a fatal error rather than a retryable connection
49  ///< failure. The default quit-test function is one that always
50  ///< returns false.
51  ///<
52  ///< If the once flag is true then the onDone() event handler
53  ///< quit()s the event loop if the client was previously
54  ///< successfully connected. Otherwise the onDone() event
55  ///< handler calls the quit-test function. If it returns true
56  ///< then the event loop is quit()ed, otherwise the reconnect
57  ///< timer is started.
58 
59  ~ClientHolder() ;
60  ///< Destructor.
61 
62 private:
63  virtual void onTimeout() override ; // GNet::TimerBase
64  virtual void onException( std::exception & ) override ; // GNet::EventExceptionHandler
65  void onDone( std::string ) ;
66  void onConnected() ;
67 
68 private:
69  TFactory & m_factory ;
70  bool m_once ;
71  bool m_once_connected ;
72  bool (*m_quit_test_fn)(std::string) ;
73  unsigned int m_reconnect_timeout ;
75 } ;
76 
77 template <typename TFactory, typename TClient>
78 ClientHolder<TFactory,TClient>::ClientHolder( TFactory & factory , bool once , bool (*quit_test_fn)(std::string) , unsigned int reconnect_timeout ) :
79  m_factory(factory) ,
80  m_once(once) ,
81  m_once_connected(false) ,
82  m_quit_test_fn(quit_test_fn) ,
83  m_reconnect_timeout(reconnect_timeout)
84 {
85  m_ptr.reset( m_factory.create() ) ;
86  m_ptr.doneSignal().connect( G::Slot::slot(*this,&ClientHolder::onDone) ) ;
87  m_ptr.connectedSignal().connect( G::Slot::slot(*this,&ClientHolder::onConnected) ) ;
88 }
89 
90 template <typename TFactory, typename TClient>
92 {
93  m_ptr.doneSignal().disconnect() ;
94  m_ptr.connectedSignal().disconnect() ;
95 }
96 
97 template <typename TFactory, typename TClient>
98 void ClientHolder<TFactory,TClient>::onDone( std::string reason )
99 {
100  G_WARNING( "ClientHolder::onDone: session ended: " << reason ) ;
101  if( (m_once&&m_once_connected) || (m_quit_test_fn!=nullptr && m_quit_test_fn(reason)) )
102  GNet::EventLoop::instance().quit( reason ) ;
103  else
104  startTimer( m_reconnect_timeout ) ;
105 }
106 
107 template <typename TFactory, typename TClient>
108 void ClientHolder<TFactory,TClient>::onConnected()
109 {
110  m_once_connected = true ;
111 }
112 
113 template <typename TFactory, typename TClient>
114 void ClientHolder<TFactory,TClient>::onTimeout()
115 {
116  G_LOG( "ClientHolder::onTimeout: reconnecting to " << m_factory.url().summary() ) ;
117  m_ptr.reset( m_factory.create() ) ;
118 }
119 
120 template <typename TFactory, typename TClient>
121 void ClientHolder<TFactory,TClient>::onException( std::exception & )
122 {
123  // exception thrown from onTimeout() when constructing the client -- this
124  // should not happen for simple connection errors because GNet::Client
125  // does its connection asynchronously wrt. its constructor
126  throw ;
127 }
128 
129 }
130 #endif
Slot0 slot(T &object, void(T::*fn)())
A slot factory function overloaded for a zero-parameter callback.
Definition: gslot.h:209
~ClientHolder()
Destructor.
A smart pointer class for GNet::HeapClient that keeps track of when the contained instance deletes it...
Definition: gclientptr.h:44
An interface used by GNet::TimerList to keep track of pending timeouts and to deliver timeout events...
Definition: gtimer.h:41
Manages a network client object so that the network client is automatically re-created from a factory...
ClientHolder(TFactory &factory, bool once=false, bool(*quit_test_fn)(std::string)=nullptr, unsigned int reconnect_timeout=1U)
Constructor that creates a network client object from a factory.
static EventLoop & instance()
Returns a reference to an instance of the class, if any.
Definition: geventloop.cpp:43
virtual void quit(std::string reason)=0
Causes run() to return (once the call stack has unwound).