Commit 6503f874 authored by Davis King's avatar Davis King

Added the start_async() function to the server object.

parent e0813cbf
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <string> #include <string>
#include "../algs.h" #include "../algs.h"
#include "../logger.h" #include "../logger.h"
#include "../smart_pointers.h"
namespace dlib namespace dlib
...@@ -135,9 +136,17 @@ namespace dlib ...@@ -135,9 +136,17 @@ namespace dlib
int get_max_connections ( int get_max_connections (
) const; ) const;
void start_async (
);
private: private:
void start_async_helper (
);
void open_listening_socket (
);
virtual void on_connect ( virtual void on_connect (
connection& new_connection connection& new_connection
)=0; )=0;
...@@ -169,8 +178,8 @@ namespace dlib ...@@ -169,8 +178,8 @@ namespace dlib
set_of_connections cons; set_of_connections cons;
mutex listening_port_mutex; mutex listening_port_mutex;
mutex listening_ip_mutex; mutex listening_ip_mutex;
mutex running_mutex; rmutex running_mutex;
signaler running_signaler; rsignaler running_signaler;
mutex shutting_down_mutex; mutex shutting_down_mutex;
mutex cons_mutex; mutex cons_mutex;
int thread_count; int thread_count;
...@@ -179,6 +188,8 @@ namespace dlib ...@@ -179,6 +188,8 @@ namespace dlib
int max_connections; int max_connections;
mutex max_connections_mutex; mutex max_connections_mutex;
signaler thread_count_zero; signaler thread_count_zero;
scoped_ptr<thread_function> async_start_thread;
scoped_ptr<listener> sock;
// restricted functions // restricted functions
...@@ -324,47 +335,103 @@ namespace dlib ...@@ -324,47 +335,103 @@ namespace dlib
typename set_of_connections typename set_of_connections
> >
void server_kernel_1<set_of_connections>:: void server_kernel_1<set_of_connections>::
start ( start_async_helper (
) )
{ {
try
listener* sock;
int status = create_listener(sock,listening_port,listening_ip);
// if there was an error then clear this object
if (status < 0)
{ {
max_connections_mutex.lock(); start();
listening_port_mutex.lock(); }
listening_ip_mutex.lock(); catch (std::exception& e)
listening_ip = ""; {
listening_port = 0; sdlog << LERROR << e.what();
max_connections = 0;
listening_port_mutex.unlock();
listening_ip_mutex.unlock();
max_connections_mutex.unlock();
} }
}
// ----------------------------------------------------------------------------------------
// throw an exception for the error template <
if (status == PORTINUSE) typename set_of_connections
>
void server_kernel_1<set_of_connections>::
start_async (
)
{
auto_mutex lock(running_mutex);
if (running)
return;
// Any exceptions likely to be thrown by the server are going to be
// thrown when trying to bind the port. So calling this here rather
// than in the thread we are about to make will cause start_async()
// to report errors back to the user in a very straight forward way.
open_listening_socket();
member_function_pointer<>::kernel_1a mfp;
mfp.set(*this,&server_kernel_1::start_async_helper);
async_start_thread.reset(new thread_function(mfp));
}
// ----------------------------------------------------------------------------------------
template <
typename set_of_connections
>
void server_kernel_1<set_of_connections>::
open_listening_socket (
)
{
if (!sock)
{ {
throw dlib::socket_error( int status = create_listener(sock,listening_port,listening_ip);
EPORT_IN_USE,
"error occurred in server_kernel_1::start()\nport already in use" // if there was an error then clear this object
if (status < 0)
{
max_connections_mutex.lock();
listening_port_mutex.lock();
listening_ip_mutex.lock();
listening_ip = "";
listening_port = 0;
max_connections = 0;
listening_port_mutex.unlock();
listening_ip_mutex.unlock();
max_connections_mutex.unlock();
}
// throw an exception for the error
if (status == PORTINUSE)
{
throw dlib::socket_error(
EPORT_IN_USE,
"error occurred in server_kernel_1::start()\nport already in use"
); );
} }
else if (status == OTHER_ERROR) else if (status == OTHER_ERROR)
{ {
throw dlib::socket_error( throw dlib::socket_error(
"error occurred in server_kernel_1::start()\nunable to create listener" "error occurred in server_kernel_1::start()\nunable to create listener"
); );
}
} }
running_mutex.lock(); running_mutex.lock();
running = true; running = true;
running_mutex.unlock(); running_mutex.unlock();
}
// ----------------------------------------------------------------------------------------
template <
typename set_of_connections
>
void server_kernel_1<set_of_connections>::
start (
)
{
open_listening_socket();
// determine the listening port // determine the listening port
bool port_assigned = false; bool port_assigned = false;
...@@ -380,6 +447,7 @@ namespace dlib ...@@ -380,6 +447,7 @@ namespace dlib
int status = 0;
connection* client; connection* client;
bool exit = false; bool exit = false;
...@@ -430,7 +498,7 @@ namespace dlib ...@@ -430,7 +498,7 @@ namespace dlib
try{cons.add(client_temp);} try{cons.add(client_temp);}
catch(...) catch(...)
{ {
delete sock; sock.reset();;
delete client; delete client;
cons_mutex.unlock(); cons_mutex.unlock();
...@@ -456,7 +524,7 @@ namespace dlib ...@@ -456,7 +524,7 @@ namespace dlib
); );
} catch (...) } catch (...)
{ {
delete sock; sock.reset();
delete client; delete client;
running_mutex.lock(); running_mutex.lock();
running = false; running = false;
...@@ -472,7 +540,7 @@ namespace dlib ...@@ -472,7 +540,7 @@ namespace dlib
{ {
delete temp; delete temp;
// close the listening socket // close the listening socket
delete sock; sock.reset();
// close the new connection and remove it from cons // close the new connection and remove it from cons
cons_mutex.lock(); cons_mutex.lock();
...@@ -546,7 +614,7 @@ namespace dlib ...@@ -546,7 +614,7 @@ namespace dlib
// close the socket // close the socket
delete sock; sock.reset();
// signal that the listener has closed // signal that the listener has closed
running_mutex.lock(); running_mutex.lock();
......
...@@ -136,6 +136,33 @@ namespace dlib ...@@ -136,6 +136,33 @@ namespace dlib
will be unusable until clear() is called and succeeds will be unusable until clear() is called and succeeds
!*/ !*/
void start_async (
);
/*!
ensures
- starts listening on the port and ip specified by get_listening_ip()
and #get_listening_port() for new connections.
- if (get_listening_port() == 0) then
- a port to listen on will be automatically selected
- #get_listening_port() == the selected port being used
- if (get_listening_ip() == "" ) then
- all local IPs will be listened on
- does NOT block. That is, this function will return right away and
the server will run on a background thread until clear() or this
object's destructor is called (or until some kind of fatal error
occurs).
- if an error occurs in the background thread while the server is
running then it will shut itself down, set is_running() to false, and
log the error to a dlib::logger object.
- calling start_async() on a running server has no effect.
throws
- dlib::socket_error
start_async() will throw this exception if there is some problem binding
ports and/or starting the server.
If this happens then
- The server will be cleared and returned to its initial value.
!*/
bool is_running ( bool is_running (
) const; ) const;
/*! /*!
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment