1044 lines
30 KiB
C++
1044 lines
30 KiB
C++
// Copyright (C) 2012 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#ifndef DLIB_BsP_Hh_
|
|
#define DLIB_BsP_Hh_
|
|
|
|
#include "bsp_abstract.h"
|
|
|
|
#include <memory>
|
|
#include <queue>
|
|
#include <vector>
|
|
|
|
#include "../sockets.h"
|
|
#include "../array.h"
|
|
#include "../sockstreambuf.h"
|
|
#include "../string.h"
|
|
#include "../serialize.h"
|
|
#include "../map.h"
|
|
#include "../ref.h"
|
|
#include "../vectorstream.h"
|
|
|
|
namespace dlib
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
namespace impl1
|
|
{
|
|
inline void null_notify(
|
|
unsigned short
|
|
) {}
|
|
|
|
struct bsp_con
|
|
{
|
|
bsp_con(
|
|
const network_address& dest
|
|
) :
|
|
con(connect(dest)),
|
|
buf(con),
|
|
stream(&buf),
|
|
terminated(false)
|
|
{
|
|
con->disable_nagle();
|
|
}
|
|
|
|
bsp_con(
|
|
std::unique_ptr<connection>& conptr
|
|
) :
|
|
buf(conptr),
|
|
stream(&buf),
|
|
terminated(false)
|
|
{
|
|
// make sure we own the connection
|
|
conptr.swap(con);
|
|
|
|
con->disable_nagle();
|
|
}
|
|
|
|
std::unique_ptr<connection> con;
|
|
sockstreambuf buf;
|
|
std::iostream stream;
|
|
bool terminated;
|
|
};
|
|
|
|
typedef dlib::map<unsigned long, std::unique_ptr<bsp_con> >::kernel_1a_c map_id_to_con;
|
|
|
|
void connect_all (
|
|
map_id_to_con& cons,
|
|
const std::vector<network_address>& hosts,
|
|
unsigned long node_id
|
|
);
|
|
/*!
|
|
ensures
|
|
- creates connections to all the given hosts and stores them into cons
|
|
!*/
|
|
|
|
void send_out_connection_orders (
|
|
map_id_to_con& cons,
|
|
const std::vector<network_address>& hosts
|
|
);
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
|
|
struct hostinfo
|
|
{
|
|
hostinfo() {}
|
|
hostinfo (
|
|
const network_address& addr_,
|
|
unsigned long node_id_
|
|
) :
|
|
addr(addr_),
|
|
node_id(node_id_)
|
|
{
|
|
}
|
|
|
|
network_address addr;
|
|
unsigned long node_id;
|
|
};
|
|
|
|
inline void serialize (
|
|
const hostinfo& item,
|
|
std::ostream& out
|
|
)
|
|
{
|
|
dlib::serialize(item.addr, out);
|
|
dlib::serialize(item.node_id, out);
|
|
}
|
|
|
|
inline void deserialize (
|
|
hostinfo& item,
|
|
std::istream& in
|
|
)
|
|
{
|
|
dlib::deserialize(item.addr, in);
|
|
dlib::deserialize(item.node_id, in);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
|
|
void connect_all_hostinfo (
|
|
map_id_to_con& cons,
|
|
const std::vector<hostinfo>& hosts,
|
|
unsigned long node_id,
|
|
std::string& error_string
|
|
);
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename port_notify_function_type
|
|
>
|
|
void listen_and_connect_all(
|
|
unsigned long& node_id,
|
|
map_id_to_con& cons,
|
|
unsigned short port,
|
|
port_notify_function_type port_notify_function
|
|
)
|
|
{
|
|
cons.clear();
|
|
std::unique_ptr<listener> list;
|
|
const int status = create_listener(list, port);
|
|
if (status == PORTINUSE)
|
|
{
|
|
throw socket_error("Unable to create listening port " + cast_to_string(port) +
|
|
". The port is already in use");
|
|
}
|
|
else if (status != 0)
|
|
{
|
|
throw socket_error("Unable to create listening port " + cast_to_string(port) );
|
|
}
|
|
|
|
port_notify_function(list->get_listening_port());
|
|
|
|
std::unique_ptr<connection> con;
|
|
if (list->accept(con))
|
|
{
|
|
throw socket_error("Error occurred while accepting new connection");
|
|
}
|
|
|
|
std::unique_ptr<bsp_con> temp(new bsp_con(con));
|
|
|
|
unsigned long remote_node_id;
|
|
dlib::deserialize(remote_node_id, temp->stream);
|
|
dlib::deserialize(node_id, temp->stream);
|
|
std::vector<hostinfo> targets;
|
|
dlib::deserialize(targets, temp->stream);
|
|
unsigned long num_incoming_connections;
|
|
dlib::deserialize(num_incoming_connections, temp->stream);
|
|
|
|
cons.add(remote_node_id,temp);
|
|
|
|
// make a thread that will connect to all the targets
|
|
map_id_to_con cons2;
|
|
std::string error_string;
|
|
thread_function thread(connect_all_hostinfo, dlib::ref(cons2), dlib::ref(targets), node_id, dlib::ref(error_string));
|
|
if (error_string.size() != 0)
|
|
throw socket_error(error_string);
|
|
|
|
// accept any incoming connections
|
|
for (unsigned long i = 0; i < num_incoming_connections; ++i)
|
|
{
|
|
// If it takes more than 10 seconds for the other nodes to connect to us
|
|
// then something has gone horribly wrong and it almost certainly will
|
|
// never connect at all. So just give up if that happens.
|
|
const unsigned long timeout_milliseconds = 10000;
|
|
if (list->accept(con, timeout_milliseconds))
|
|
{
|
|
throw socket_error("Error occurred while accepting new connection");
|
|
}
|
|
|
|
temp.reset(new bsp_con(con));
|
|
|
|
dlib::deserialize(remote_node_id, temp->stream);
|
|
cons.add(remote_node_id,temp);
|
|
}
|
|
|
|
|
|
// put all the connections created by the thread into cons
|
|
thread.wait();
|
|
while (cons2.size() > 0)
|
|
{
|
|
unsigned long id;
|
|
std::unique_ptr<bsp_con> temp;
|
|
cons2.remove_any(id,temp);
|
|
cons.add(id,temp);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
|
|
struct msg_data
|
|
{
|
|
std::shared_ptr<std::vector<char> > data;
|
|
unsigned long sender_id;
|
|
char msg_type;
|
|
dlib::uint64 epoch;
|
|
|
|
msg_data() : sender_id(0xFFFFFFFF), msg_type(-1), epoch(0) {}
|
|
|
|
std::string data_to_string() const
|
|
{
|
|
if (data && data->size() != 0)
|
|
return std::string(&(*data)[0], data->size());
|
|
else
|
|
return "";
|
|
}
|
|
};
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
|
|
class thread_safe_message_queue : noncopyable
|
|
{
|
|
/*!
|
|
WHAT THIS OBJECT REPRESENTS
|
|
This is a simple message queue for msg_data objects. Note that it
|
|
has the special property that, while messages will generally leave
|
|
the queue in the order they are inserted, any message with a smaller
|
|
epoch value will always be popped out first. But for all messages
|
|
with equal epoch values the queue functions as a normal FIFO queue.
|
|
!*/
|
|
private:
|
|
struct msg_wrap
|
|
{
|
|
msg_wrap(
|
|
const msg_data& data_,
|
|
const dlib::uint64& sequence_number_
|
|
) : data(data_), sequence_number(sequence_number_) {}
|
|
|
|
msg_wrap() : sequence_number(0){}
|
|
|
|
msg_data data;
|
|
dlib::uint64 sequence_number;
|
|
|
|
// Make it so that when msg_wrap objects are in a std::priority_queue,
|
|
// messages with a smaller epoch number always come first. Then, within an
|
|
// epoch, messages are ordered by their sequence number (so smaller first
|
|
// there as well).
|
|
bool operator<(const msg_wrap& item) const
|
|
{
|
|
if (data.epoch < item.data.epoch)
|
|
{
|
|
return false;
|
|
}
|
|
else if (data.epoch > item.data.epoch)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if (sequence_number < item.sequence_number)
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
}
|
|
};
|
|
|
|
public:
|
|
thread_safe_message_queue() : sig(class_mutex),disabled(false),next_seq_num(1) {}
|
|
|
|
~thread_safe_message_queue()
|
|
{
|
|
disable();
|
|
}
|
|
|
|
void disable()
|
|
{
|
|
auto_mutex lock(class_mutex);
|
|
disabled = true;
|
|
sig.broadcast();
|
|
}
|
|
|
|
unsigned long size() const
|
|
{
|
|
auto_mutex lock(class_mutex);
|
|
return data.size();
|
|
}
|
|
|
|
void push_and_consume( msg_data& item)
|
|
{
|
|
auto_mutex lock(class_mutex);
|
|
data.push(msg_wrap(item, next_seq_num++));
|
|
// do this here so that we don't have to worry about different threads touching the shared_ptr.
|
|
item.data.reset();
|
|
sig.signal();
|
|
}
|
|
|
|
bool pop (
|
|
msg_data& item
|
|
)
|
|
/*!
|
|
ensures
|
|
- if (this function returns true) then
|
|
- #item == the next thing from the queue
|
|
- else
|
|
- this object is disabled
|
|
!*/
|
|
{
|
|
auto_mutex lock(class_mutex);
|
|
while (data.size() == 0 && !disabled)
|
|
sig.wait();
|
|
|
|
if (disabled)
|
|
return false;
|
|
|
|
item = data.top().data;
|
|
data.pop();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool pop (
|
|
msg_data& item,
|
|
const dlib::uint64& max_epoch
|
|
)
|
|
/*!
|
|
ensures
|
|
- if (this function returns true) then
|
|
- #item == the next thing from the queue that has an epoch <= max_epoch
|
|
- else
|
|
- this object is disabled
|
|
!*/
|
|
{
|
|
auto_mutex lock(class_mutex);
|
|
while ((data.size() == 0 || data.top().data.epoch > max_epoch) && !disabled)
|
|
sig.wait();
|
|
|
|
if (disabled)
|
|
return false;
|
|
|
|
item = data.top().data;
|
|
data.pop();
|
|
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
std::priority_queue<msg_wrap> data;
|
|
dlib::mutex class_mutex;
|
|
dlib::signaler sig;
|
|
bool disabled;
|
|
dlib::uint64 next_seq_num;
|
|
};
|
|
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
class bsp_context : noncopyable
|
|
{
|
|
|
|
public:
|
|
|
|
template <typename T>
|
|
void send(
|
|
const T& item,
|
|
unsigned long target_node_id
|
|
)
|
|
{
|
|
// make sure requires clause is not broken
|
|
DLIB_CASSERT(target_node_id < number_of_nodes() &&
|
|
target_node_id != node_id(),
|
|
"\t void bsp_context::send()"
|
|
<< "\n\t Invalid arguments were given to this function."
|
|
<< "\n\t target_node_id: " << target_node_id
|
|
<< "\n\t node_id(): " << node_id()
|
|
<< "\n\t number_of_nodes(): " << number_of_nodes()
|
|
<< "\n\t this: " << this
|
|
);
|
|
|
|
std::vector<char> buf;
|
|
vectorstream sout(buf);
|
|
serialize(item, sout);
|
|
send_data(buf, target_node_id);
|
|
}
|
|
|
|
template <typename T>
|
|
void broadcast (
|
|
const T& item
|
|
)
|
|
{
|
|
std::vector<char> buf;
|
|
vectorstream sout(buf);
|
|
serialize(item, sout);
|
|
for (unsigned long i = 0; i < number_of_nodes(); ++i)
|
|
{
|
|
// Don't send to yourself.
|
|
if (i == node_id())
|
|
continue;
|
|
|
|
send_data(buf, i);
|
|
}
|
|
}
|
|
|
|
unsigned long node_id (
|
|
) const { return _node_id; }
|
|
|
|
unsigned long number_of_nodes (
|
|
) const { return _cons.size()+1; }
|
|
|
|
void receive (
|
|
)
|
|
{
|
|
unsigned long id;
|
|
std::shared_ptr<std::vector<char> > temp;
|
|
if (receive_data(temp,id))
|
|
throw dlib::socket_error("Call to bsp_context::receive() got an unexpected message.");
|
|
}
|
|
|
|
template <typename T>
|
|
void receive (
|
|
T& item
|
|
)
|
|
{
|
|
if(!try_receive(item))
|
|
throw dlib::socket_error("bsp_context::receive(): no messages to receive, all nodes currently blocked.");
|
|
}
|
|
|
|
template <typename T>
|
|
bool try_receive (
|
|
T& item
|
|
)
|
|
{
|
|
unsigned long sending_node_id;
|
|
return try_receive(item, sending_node_id);
|
|
}
|
|
|
|
template <typename T>
|
|
void receive (
|
|
T& item,
|
|
unsigned long& sending_node_id
|
|
)
|
|
{
|
|
if(!try_receive(item, sending_node_id))
|
|
throw dlib::socket_error("bsp_context::receive(): no messages to receive, all nodes currently blocked.");
|
|
}
|
|
|
|
template <typename T>
|
|
bool try_receive (
|
|
T& item,
|
|
unsigned long& sending_node_id
|
|
)
|
|
{
|
|
std::shared_ptr<std::vector<char> > temp;
|
|
if (receive_data(temp, sending_node_id))
|
|
{
|
|
vectorstream sin(*temp);
|
|
deserialize(item, sin);
|
|
if (sin.peek() != EOF)
|
|
throw serialization_error("deserialize() did not consume all bytes produced by serialize(). "
|
|
"This probably means you are calling a receive method with a different type "
|
|
"of object than the one which was sent.");
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
~bsp_context();
|
|
|
|
private:
|
|
|
|
bsp_context();
|
|
|
|
bsp_context(
|
|
unsigned long node_id_,
|
|
impl1::map_id_to_con& cons_
|
|
);
|
|
|
|
void close_all_connections_gracefully();
|
|
/*!
|
|
ensures
|
|
- closes all the connections to other nodes and lets them know that
|
|
we are terminating normally rather than as the result of some kind
|
|
of error.
|
|
!*/
|
|
|
|
bool receive_data (
|
|
std::shared_ptr<std::vector<char> >& item,
|
|
unsigned long& sending_node_id
|
|
);
|
|
|
|
|
|
void notify_control_node (
|
|
char val
|
|
);
|
|
|
|
void broadcast_byte (
|
|
char val
|
|
);
|
|
|
|
void send_data(
|
|
const std::vector<char>& item,
|
|
unsigned long target_node_id
|
|
);
|
|
/*!
|
|
requires
|
|
- target_node_id < number_of_nodes()
|
|
- target_node_id != node_id()
|
|
ensures
|
|
- sends a copy of item to the node with the given id.
|
|
!*/
|
|
|
|
|
|
|
|
|
|
unsigned long outstanding_messages;
|
|
unsigned long num_waiting_nodes;
|
|
unsigned long num_terminated_nodes;
|
|
dlib::uint64 current_epoch;
|
|
|
|
impl1::thread_safe_message_queue msg_buffer;
|
|
|
|
impl1::map_id_to_con& _cons;
|
|
const unsigned long _node_id;
|
|
array<std::unique_ptr<thread_function> > threads;
|
|
|
|
// -----------------------------------
|
|
|
|
template <
|
|
typename funct_type
|
|
>
|
|
friend void bsp_connect (
|
|
const std::vector<network_address>& hosts,
|
|
funct_type funct
|
|
);
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1
|
|
>
|
|
friend void bsp_connect (
|
|
const std::vector<network_address>& hosts,
|
|
funct_type funct,
|
|
ARG1 arg1
|
|
);
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2
|
|
>
|
|
friend void bsp_connect (
|
|
const std::vector<network_address>& hosts,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2
|
|
);
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2,
|
|
typename ARG3
|
|
>
|
|
friend void bsp_connect (
|
|
const std::vector<network_address>& hosts,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2,
|
|
ARG3 arg3
|
|
);
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2,
|
|
typename ARG3,
|
|
typename ARG4
|
|
>
|
|
friend void bsp_connect (
|
|
const std::vector<network_address>& hosts,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2,
|
|
ARG3 arg3,
|
|
ARG4 arg4
|
|
);
|
|
|
|
// -----------------------------------
|
|
|
|
template <
|
|
typename port_notify_function_type,
|
|
typename funct_type
|
|
>
|
|
friend void bsp_listen_dynamic_port (
|
|
unsigned short listening_port,
|
|
port_notify_function_type port_notify_function,
|
|
funct_type funct
|
|
);
|
|
|
|
template <
|
|
typename port_notify_function_type,
|
|
typename funct_type,
|
|
typename ARG1
|
|
>
|
|
friend void bsp_listen_dynamic_port (
|
|
unsigned short listening_port,
|
|
port_notify_function_type port_notify_function,
|
|
funct_type funct,
|
|
ARG1 arg1
|
|
);
|
|
|
|
template <
|
|
typename port_notify_function_type,
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2
|
|
>
|
|
friend void bsp_listen_dynamic_port (
|
|
unsigned short listening_port,
|
|
port_notify_function_type port_notify_function,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2
|
|
);
|
|
|
|
template <
|
|
typename port_notify_function_type,
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2,
|
|
typename ARG3
|
|
>
|
|
friend void bsp_listen_dynamic_port (
|
|
unsigned short listening_port,
|
|
port_notify_function_type port_notify_function,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2,
|
|
ARG3 arg3
|
|
);
|
|
|
|
template <
|
|
typename port_notify_function_type,
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2,
|
|
typename ARG3,
|
|
typename ARG4
|
|
>
|
|
friend void bsp_listen_dynamic_port (
|
|
unsigned short listening_port,
|
|
port_notify_function_type port_notify_function,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2,
|
|
ARG3 arg3,
|
|
ARG4 arg4
|
|
);
|
|
|
|
// -----------------------------------
|
|
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename funct_type
|
|
>
|
|
void bsp_connect (
|
|
const std::vector<network_address>& hosts,
|
|
funct_type funct
|
|
)
|
|
{
|
|
impl1::map_id_to_con cons;
|
|
const unsigned long node_id = 0;
|
|
connect_all(cons, hosts, node_id);
|
|
send_out_connection_orders(cons, hosts);
|
|
bsp_context obj(node_id, cons);
|
|
funct(obj);
|
|
obj.close_all_connections_gracefully();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1
|
|
>
|
|
void bsp_connect (
|
|
const std::vector<network_address>& hosts,
|
|
funct_type funct,
|
|
ARG1 arg1
|
|
)
|
|
{
|
|
impl1::map_id_to_con cons;
|
|
const unsigned long node_id = 0;
|
|
connect_all(cons, hosts, node_id);
|
|
send_out_connection_orders(cons, hosts);
|
|
bsp_context obj(node_id, cons);
|
|
funct(obj,arg1);
|
|
obj.close_all_connections_gracefully();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2
|
|
>
|
|
void bsp_connect (
|
|
const std::vector<network_address>& hosts,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2
|
|
)
|
|
{
|
|
impl1::map_id_to_con cons;
|
|
const unsigned long node_id = 0;
|
|
connect_all(cons, hosts, node_id);
|
|
send_out_connection_orders(cons, hosts);
|
|
bsp_context obj(node_id, cons);
|
|
funct(obj,arg1,arg2);
|
|
obj.close_all_connections_gracefully();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2,
|
|
typename ARG3
|
|
>
|
|
void bsp_connect (
|
|
const std::vector<network_address>& hosts,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2,
|
|
ARG3 arg3
|
|
)
|
|
{
|
|
impl1::map_id_to_con cons;
|
|
const unsigned long node_id = 0;
|
|
connect_all(cons, hosts, node_id);
|
|
send_out_connection_orders(cons, hosts);
|
|
bsp_context obj(node_id, cons);
|
|
funct(obj,arg1,arg2,arg3);
|
|
obj.close_all_connections_gracefully();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2,
|
|
typename ARG3,
|
|
typename ARG4
|
|
>
|
|
void bsp_connect (
|
|
const std::vector<network_address>& hosts,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2,
|
|
ARG3 arg3,
|
|
ARG4 arg4
|
|
)
|
|
{
|
|
impl1::map_id_to_con cons;
|
|
const unsigned long node_id = 0;
|
|
connect_all(cons, hosts, node_id);
|
|
send_out_connection_orders(cons, hosts);
|
|
bsp_context obj(node_id, cons);
|
|
funct(obj,arg1,arg2,arg3,arg4);
|
|
obj.close_all_connections_gracefully();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename funct_type
|
|
>
|
|
void bsp_listen (
|
|
unsigned short listening_port,
|
|
funct_type funct
|
|
)
|
|
{
|
|
// make sure requires clause is not broken
|
|
DLIB_CASSERT(listening_port != 0,
|
|
"\t void bsp_listen()"
|
|
<< "\n\t Invalid arguments were given to this function."
|
|
);
|
|
|
|
bsp_listen_dynamic_port(listening_port, impl1::null_notify, funct);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1
|
|
>
|
|
void bsp_listen (
|
|
unsigned short listening_port,
|
|
funct_type funct,
|
|
ARG1 arg1
|
|
)
|
|
{
|
|
// make sure requires clause is not broken
|
|
DLIB_CASSERT(listening_port != 0,
|
|
"\t void bsp_listen()"
|
|
<< "\n\t Invalid arguments were given to this function."
|
|
);
|
|
|
|
bsp_listen_dynamic_port(listening_port, impl1::null_notify, funct, arg1);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2
|
|
>
|
|
void bsp_listen (
|
|
unsigned short listening_port,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2
|
|
)
|
|
{
|
|
// make sure requires clause is not broken
|
|
DLIB_CASSERT(listening_port != 0,
|
|
"\t void bsp_listen()"
|
|
<< "\n\t Invalid arguments were given to this function."
|
|
);
|
|
|
|
bsp_listen_dynamic_port(listening_port, impl1::null_notify, funct, arg1, arg2);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2,
|
|
typename ARG3
|
|
>
|
|
void bsp_listen (
|
|
unsigned short listening_port,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2,
|
|
ARG3 arg3
|
|
)
|
|
{
|
|
// make sure requires clause is not broken
|
|
DLIB_CASSERT(listening_port != 0,
|
|
"\t void bsp_listen()"
|
|
<< "\n\t Invalid arguments were given to this function."
|
|
);
|
|
|
|
bsp_listen_dynamic_port(listening_port, impl1::null_notify, funct, arg1, arg2, arg3);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2,
|
|
typename ARG3,
|
|
typename ARG4
|
|
>
|
|
void bsp_listen (
|
|
unsigned short listening_port,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2,
|
|
ARG3 arg3,
|
|
ARG4 arg4
|
|
)
|
|
{
|
|
// make sure requires clause is not broken
|
|
DLIB_CASSERT(listening_port != 0,
|
|
"\t void bsp_listen()"
|
|
<< "\n\t Invalid arguments were given to this function."
|
|
);
|
|
|
|
bsp_listen_dynamic_port(listening_port, impl1::null_notify, funct, arg1, arg2, arg3, arg4);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename port_notify_function_type,
|
|
typename funct_type
|
|
>
|
|
void bsp_listen_dynamic_port (
|
|
unsigned short listening_port,
|
|
port_notify_function_type port_notify_function,
|
|
funct_type funct
|
|
)
|
|
{
|
|
impl1::map_id_to_con cons;
|
|
unsigned long node_id;
|
|
listen_and_connect_all(node_id, cons, listening_port, port_notify_function);
|
|
bsp_context obj(node_id, cons);
|
|
funct(obj);
|
|
obj.close_all_connections_gracefully();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename port_notify_function_type,
|
|
typename funct_type,
|
|
typename ARG1
|
|
>
|
|
void bsp_listen_dynamic_port (
|
|
unsigned short listening_port,
|
|
port_notify_function_type port_notify_function,
|
|
funct_type funct,
|
|
ARG1 arg1
|
|
)
|
|
{
|
|
impl1::map_id_to_con cons;
|
|
unsigned long node_id;
|
|
listen_and_connect_all(node_id, cons, listening_port, port_notify_function);
|
|
bsp_context obj(node_id, cons);
|
|
funct(obj,arg1);
|
|
obj.close_all_connections_gracefully();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename port_notify_function_type,
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2
|
|
>
|
|
void bsp_listen_dynamic_port (
|
|
unsigned short listening_port,
|
|
port_notify_function_type port_notify_function,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2
|
|
)
|
|
{
|
|
impl1::map_id_to_con cons;
|
|
unsigned long node_id;
|
|
listen_and_connect_all(node_id, cons, listening_port, port_notify_function);
|
|
bsp_context obj(node_id, cons);
|
|
funct(obj,arg1,arg2);
|
|
obj.close_all_connections_gracefully();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename port_notify_function_type,
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2,
|
|
typename ARG3
|
|
>
|
|
void bsp_listen_dynamic_port (
|
|
unsigned short listening_port,
|
|
port_notify_function_type port_notify_function,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2,
|
|
ARG3 arg3
|
|
)
|
|
{
|
|
impl1::map_id_to_con cons;
|
|
unsigned long node_id;
|
|
listen_and_connect_all(node_id, cons, listening_port, port_notify_function);
|
|
bsp_context obj(node_id, cons);
|
|
funct(obj,arg1,arg2,arg3);
|
|
obj.close_all_connections_gracefully();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename port_notify_function_type,
|
|
typename funct_type,
|
|
typename ARG1,
|
|
typename ARG2,
|
|
typename ARG3,
|
|
typename ARG4
|
|
>
|
|
void bsp_listen_dynamic_port (
|
|
unsigned short listening_port,
|
|
port_notify_function_type port_notify_function,
|
|
funct_type funct,
|
|
ARG1 arg1,
|
|
ARG2 arg2,
|
|
ARG3 arg3,
|
|
ARG4 arg4
|
|
)
|
|
{
|
|
impl1::map_id_to_con cons;
|
|
unsigned long node_id;
|
|
listen_and_connect_all(node_id, cons, listening_port, port_notify_function);
|
|
bsp_context obj(node_id, cons);
|
|
funct(obj,arg1,arg2,arg3,arg4);
|
|
obj.close_all_connections_gracefully();
|
|
}
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#ifdef NO_MAKEFILE
|
|
#include "bsp.cpp"
|
|
#endif
|
|
|
|
#endif // DLIB_BsP_Hh_
|
|
|