55 static void start(
ResolverImp * , FutureEvent::handle_type ) noexcept ;
61 static std::size_t zcount() noexcept ;
65 void onFutureEvent()
override ;
77 using Pair = ResolverFuture::Pair ;
79 std::unique_ptr<FutureEvent> m_future_event ;
83 G::threading::thread_type m_thread ;
84 static std::size_t m_zcount ;
87std::size_t GNet::ResolverImp::m_zcount = 0U ;
90 m_resolver(&resolver) ,
93 m_location(location) ,
94 m_future(location.host(),location.service(),location.family(),false,true)
96 G_ASSERT( G::threading::works() ) ;
98 m_thread = G::threading::thread_type( ResolverImp::start ,
this , m_future_event->handle() ) ;
101GNet::ResolverImp::~ResolverImp()
106 if( m_thread.joinable() )
114std::size_t GNet::ResolverImp::zcount() noexcept
119void GNet::ResolverImp::start( ResolverImp * This , FutureEvent::handle_type handle )
noexcept
124 This->m_future.run() ;
134void GNet::ResolverImp::onFutureEvent()
136 G_DEBUG(
"GNet::ResolverImp::onFutureEvent: future event: ptr=" << m_resolver ) ;
138 Pair result = m_future.get() ;
139 if( !m_future.error() )
140 m_location.update( result.first , result.second ) ;
142 if( m_thread.joinable() )
145 Resolver * resolver = m_resolver ;
146 m_resolver = nullptr ;
148 resolver->done( std::string(m_future.reason()) , Location(m_location) ) ;
151bool GNet::ResolverImp::zombify()
153 m_resolver = nullptr ;
154 m_timer.startTimer( 0U ) ;
159void GNet::ResolverImp::onTimeout()
161 if( m_thread.joinable() )
163 m_timer.startTimer( 1U ) ;
175 m_callback(callback) ,
183 if( m_imp && m_imp->zombify() )
185 G_DEBUG(
"GNet::Resolver::dtor: zcount=" << ResolverImp::zcount() ) ;
186 if( ResolverImp::zcount() == 100U )
187 G_WARNING_ONCE(
"GNet::Resolver::dtor: large number of threads waiting for dns results" ) ;
190 GDEF_IGNORE_RETURN m_imp.release() ;
197 using Pair = ResolverFuture::Pair ;
198 G_DEBUG(
"GNet::Resolver::resolve: resolve request [" << location.
displayString() <<
"]"
199 <<
" (" << location.
family() <<
")" ) ;
202 Pair result = future.
get() ;
205 G_DEBUG(
"GNet::Resolver::resolve: resolve error [" << future.
reason() <<
"]" ) ;
210 G_DEBUG(
"GNet::Resolver::resolve: resolve result [" << result.first.displayString() <<
"]"
211 <<
"[" << result.second <<
"]" ) ;
212 location.
update( result.first , result.second ) ;
213 return std::string() ;
218 int family ,
bool dgram )
221 G_DEBUG(
"GNet::Resolver::resolve: resolve-request [" << host <<
"/"
222 << service <<
"/" << (family==AF_UNSPEC?
"ip":(family==AF_INET?
"ipv4":
"ipv6")) <<
"]" ) ;
227 G_DEBUG(
"GNet::Resolver::resolve: resolve result: list of " << list.size() ) ;
235 if( !async() )
throw Error(
"not multi-threaded" ) ;
236 if( busy() )
throw BusyError() ;
237 G_DEBUG(
"GNet::Resolver::start: resolve start [" << location.
displayString() <<
"]" ) ;
238 m_imp = std::make_unique<ResolverImp>( *
this , m_es , location ) ;
241void GNet::Resolver::done(
const std::string & error ,
const Location & location )
244 G_DEBUG(
"GNet::Resolver::done: resolve done: error=[" << error <<
"] "
247 m_callback.onResolved( error , location ) ;
252 return m_imp != nullptr ;
257 if( G::threading::works() )
263 G_DEBUG(
"GNet::Resolver::async: not multi-threaded: using synchronous domain name lookup");
virtual bool running() const =0
Returns true if called from within run().
static EventLoop & instance()
Returns a reference to an instance of the class, if any.
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
A callback interface for GNet::FutureEvent.
A FutureEvent object can be used to send a one-shot event via the event loop to the relevant event ha...
static bool send(handle_type handle, bool close=true) noexcept
Pokes an event into the main event loop so that the FutureEventHandler callback is called asynchronou...
A class that represents the remote target for out-going client connections.
int family() const
Returns the preferred name resolution address family as passed to the constructor.
std::string displayString() const
Returns a string representation for logging and debug.
void update(const Address &address, const std::string &canonical_name)
Updates the address and canonical name, typically after doing a name lookup on host() and service().
std::string service() const
Returns the remote service name derived from the constructor parameter.
std::string host() const
Returns the remote host name derived from the constructor parameter.
A 'future' shared-state class for asynchronous name resolution that holds parameters and results of a...
bool error() const
Returns true if name resolution failed or no suitable address was returned.
std::string reason() const
Returns the reason for the error().
Pair get()
Returns the resolved address/name pair after run() has completed.
ResolverFuture & run() noexcept
Does the synchronous name resolution and stores the result.
A private "pimple" implementation class used by GNet::Resolver to do asynchronous name resolution.
A class for synchronous or asynchronous network name to address resolution.
static std::string resolve(Location &)
Does synchronous name resolution.
Resolver(Callback &, ExceptionSink)
Constructor taking a callback interface reference.
static bool async()
Returns true if the resolver supports asynchronous operation.
void start(const Location &)
Starts asynchronous name-to-address resolution.
bool busy() const
Returns true if there is a pending resolve request.
A timer class template in which the timeout is delivered to the specified method.
An interface used for GNet::Resolver callbacks.
A RAII class to temporarily block signal delivery.