+
+/**
+An asynchronous name resolver. Blocking calls are performed in a thread and
+completion is notified with one of the two signals.
+*/
+class Resolver
+{
+private:
+ struct Task
+ {
+ unsigned tag;
+ std::string host;
+ std::string serv;
+ Family family;
+ SockAddr *addr;
+ std::runtime_error *error;
+
+ Task();
+
+ bool is_complete() const { return addr || error; }
+ };
+
+ class WorkerThread: public Thread
+ {
+ private:
+ std::list<Task> queue;
+ Mutex queue_mutex;
+ Semaphore sem;
+ IO::Pipe notify_pipe;
+ bool done;
+
+ public:
+ WorkerThread();
+ ~WorkerThread();
+
+ void add_task(const Task &);
+ Task *get_complete_task();
+ void pop_complete_task();
+
+ IO::Pipe &get_notify_pipe() { return notify_pipe; }
+
+ private:
+ virtual void main();
+ };
+
+public:
+ sigc::signal<void, unsigned, const SockAddr &> signal_address_resolved;
+ sigc::signal<void, unsigned, const std::exception &> signal_resolve_failed;
+
+private:
+ IO::EventDispatcher *event_disp;
+ WorkerThread thread;
+ unsigned next_tag;
+
+public:
+ Resolver();
+
+ /** Sets the event dispatcher to use. With no event dispatcher, tick() must
+ be called regularly to emit the completion signals. */
+ void use_event_dispatcher(IO::EventDispatcher *);
+
+ /** Resolves host and service names into a socket address. Semantics are
+ the same as the namespace-scope resolve function. */
+ unsigned resolve(const std::string &, const std::string &, Family = UNSPEC);
+
+ unsigned resolve(const std::string &, Family = UNSPEC);
+
+ /** Checks for any completed tasks and emits the appropriate singals. */
+ void tick();
+
+private:
+ void task_done();
+};
+