mirror of https://github.com/davisking/dlib.git
Added the start_async() function to the server object.
This commit is contained in:
parent
e0813cbf9f
commit
6503f87480
|
@ -11,6 +11,7 @@
|
|||
#include <string>
|
||||
#include "../algs.h"
|
||||
#include "../logger.h"
|
||||
#include "../smart_pointers.h"
|
||||
|
||||
|
||||
namespace dlib
|
||||
|
@ -135,9 +136,17 @@ namespace dlib
|
|||
int get_max_connections (
|
||||
) const;
|
||||
|
||||
void start_async (
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
void start_async_helper (
|
||||
);
|
||||
|
||||
void open_listening_socket (
|
||||
);
|
||||
|
||||
virtual void on_connect (
|
||||
connection& new_connection
|
||||
)=0;
|
||||
|
@ -169,8 +178,8 @@ namespace dlib
|
|||
set_of_connections cons;
|
||||
mutex listening_port_mutex;
|
||||
mutex listening_ip_mutex;
|
||||
mutex running_mutex;
|
||||
signaler running_signaler;
|
||||
rmutex running_mutex;
|
||||
rsignaler running_signaler;
|
||||
mutex shutting_down_mutex;
|
||||
mutex cons_mutex;
|
||||
int thread_count;
|
||||
|
@ -179,6 +188,8 @@ namespace dlib
|
|||
int max_connections;
|
||||
mutex max_connections_mutex;
|
||||
signaler thread_count_zero;
|
||||
scoped_ptr<thread_function> async_start_thread;
|
||||
scoped_ptr<listener> sock;
|
||||
|
||||
|
||||
// restricted functions
|
||||
|
@ -324,47 +335,103 @@ namespace dlib
|
|||
typename set_of_connections
|
||||
>
|
||||
void server_kernel_1<set_of_connections>::
|
||||
start (
|
||||
start_async_helper (
|
||||
)
|
||||
{
|
||||
|
||||
listener* sock;
|
||||
int status = create_listener(sock,listening_port,listening_ip);
|
||||
|
||||
// if there was an error then clear this object
|
||||
if (status < 0)
|
||||
try
|
||||
{
|
||||
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();
|
||||
start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// throw an exception for the error
|
||||
if (status == PORTINUSE)
|
||||
catch (std::exception& e)
|
||||
{
|
||||
throw dlib::socket_error(
|
||||
EPORT_IN_USE,
|
||||
"error occurred in server_kernel_1::start()\nport already in use"
|
||||
sdlog << LERROR << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
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)
|
||||
{
|
||||
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();
|
||||
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)
|
||||
{
|
||||
throw dlib::socket_error(
|
||||
"error occurred in server_kernel_1::start()\nunable to create listener"
|
||||
}
|
||||
else if (status == OTHER_ERROR)
|
||||
{
|
||||
throw dlib::socket_error(
|
||||
"error occurred in server_kernel_1::start()\nunable to create listener"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
running_mutex.lock();
|
||||
running = true;
|
||||
running_mutex.unlock();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename set_of_connections
|
||||
>
|
||||
void server_kernel_1<set_of_connections>::
|
||||
start (
|
||||
)
|
||||
{
|
||||
open_listening_socket();
|
||||
|
||||
// determine the listening port
|
||||
bool port_assigned = false;
|
||||
|
@ -380,6 +447,7 @@ namespace dlib
|
|||
|
||||
|
||||
|
||||
int status = 0;
|
||||
|
||||
connection* client;
|
||||
bool exit = false;
|
||||
|
@ -430,7 +498,7 @@ namespace dlib
|
|||
try{cons.add(client_temp);}
|
||||
catch(...)
|
||||
{
|
||||
delete sock;
|
||||
sock.reset();;
|
||||
delete client;
|
||||
cons_mutex.unlock();
|
||||
|
||||
|
@ -456,7 +524,7 @@ namespace dlib
|
|||
);
|
||||
} catch (...)
|
||||
{
|
||||
delete sock;
|
||||
sock.reset();
|
||||
delete client;
|
||||
running_mutex.lock();
|
||||
running = false;
|
||||
|
@ -472,7 +540,7 @@ namespace dlib
|
|||
{
|
||||
delete temp;
|
||||
// close the listening socket
|
||||
delete sock;
|
||||
sock.reset();
|
||||
|
||||
// close the new connection and remove it from cons
|
||||
cons_mutex.lock();
|
||||
|
@ -546,7 +614,7 @@ namespace dlib
|
|||
|
||||
|
||||
// close the socket
|
||||
delete sock;
|
||||
sock.reset();
|
||||
|
||||
// signal that the listener has closed
|
||||
running_mutex.lock();
|
||||
|
|
|
@ -136,6 +136,33 @@ namespace dlib
|
|||
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 (
|
||||
) const;
|
||||
/*!
|
||||
|
|
Loading…
Reference in New Issue