|
|
|
|
|
#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) |
|
{ |
|
|
|
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 |
|
); |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
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); |
|
|
|
|
|
for (unsigned long i = 0; i < num_incoming_connections; ++i) |
|
{ |
|
|
|
|
|
|
|
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); |
|
} |
|
|
|
|
|
|
|
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 |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
|
|
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++)); |
|
|
|
item.data.reset(); |
|
sig.signal(); |
|
} |
|
|
|
bool pop ( |
|
msg_data& item |
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
|
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 |
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
|
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 |
|
) |
|
{ |
|
|
|
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) |
|
{ |
|
|
|
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(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
) |
|
{ |
|
|
|
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 |
|
) |
|
{ |
|
|
|
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 |
|
) |
|
{ |
|
|
|
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 |
|
) |
|
{ |
|
|
|
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 |
|
) |
|
{ |
|
|
|
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 |
|
|
|
|