Commit d7088d90 authored by neverlord's avatar neverlord

fixed select() bug and static initialization/deinitialization

parent 7023a997
...@@ -93,6 +93,8 @@ class mailman_job ...@@ -93,6 +93,8 @@ class mailman_job
}; };
void mailman_loop();
util::single_reader_queue<mailman_job>& mailman_queue(); util::single_reader_queue<mailman_job>& mailman_queue();
}} // namespace cppa::detail }} // namespace cppa::detail
......
#include <atomic>
#include <iostream> #include <iostream>
#include <boost/thread.hpp> // boost::barrier
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/detail/mailman.hpp" #include "cppa/detail/mailman.hpp"
#include "cppa/binary_serializer.hpp" #include "cppa/binary_serializer.hpp"
#include "cppa/detail/post_office.hpp" #include "cppa/detail/post_office.hpp"
#define DEBUG(arg) std::cout << arg << std::endl //#define DEBUG(arg) std::cout << arg << std::endl
#define DEBUG(unused) //
// forward declaration // static queue helper
namespace cppa { namespace detail { namespace { void mailman_loop(); } } }
// static helper
namespace { namespace {
/*
struct mailman_manager struct mailman_manager
{ {
typedef cppa::util::single_reader_queue<cppa::detail::mailman_job> queue_t; typedef cppa::util::single_reader_queue<cppa::detail::mailman_job> queue_t;
boost::thread* m_loop; boost::barrier m_init_handshake;
queue_t* m_queue; boost::barrier m_shutdown_handshake;
queue_t m_queue;
mailman_manager() mailman_manager()
{ {
...@@ -36,6 +38,7 @@ struct mailman_manager ...@@ -36,6 +38,7 @@ struct mailman_manager
} }
s_mailman_manager; s_mailman_manager;
*/
} // namespace <anonymous> } // namespace <anonymous>
// implementation of mailman.hpp // implementation of mailman.hpp
...@@ -106,16 +109,18 @@ mailman_job::~mailman_job() ...@@ -106,16 +109,18 @@ mailman_job::~mailman_job()
} }
} }
/*
// implemented in post_office.cpp
util::single_reader_queue<mailman_job>& mailman_queue() util::single_reader_queue<mailman_job>& mailman_queue()
{ {
return *(s_mailman_manager.m_queue); return *s_queue;
//return *(s_mailman_manager.m_queue);
} }
*/
} } // namespace cppa::detail
namespace cppa { namespace detail { namespace {
void mailman_loop() void mailman_loop()
{ {
// delete s_queue if mailman_loop exits
// serializes outgoing messages // serializes outgoing messages
binary_serializer bs; binary_serializer bs;
// current active job // current active job
...@@ -215,4 +220,5 @@ void mailman_loop() ...@@ -215,4 +220,5 @@ void mailman_loop()
delete job; delete job;
} }
} }
} } } // namespace cppa::detail::<anonymous>
} } // namespace cppa::detail
...@@ -27,6 +27,9 @@ ...@@ -27,6 +27,9 @@
#include "cppa/detail/native_socket.hpp" #include "cppa/detail/native_socket.hpp"
#include "cppa/detail/actor_proxy_cache.hpp" #include "cppa/detail/actor_proxy_cache.hpp"
//#define DEBUG(arg) std::cout << arg << std::endl
#define DEBUG(unused) //
namespace cppa { namespace detail { namespace { namespace cppa { namespace detail { namespace {
// allocate in 1KB chunks (minimize reallocations) // allocate in 1KB chunks (minimize reallocations)
...@@ -52,8 +55,6 @@ constexpr std::uint32_t shutdown_event = 0x04; ...@@ -52,8 +55,6 @@ constexpr std::uint32_t shutdown_event = 0x04;
typedef std::uint32_t pipe_msg[2]; typedef std::uint32_t pipe_msg[2];
constexpr size_t pipe_msg_size = 2 * sizeof(std::uint32_t); constexpr size_t pipe_msg_size = 2 * sizeof(std::uint32_t);
#define DEBUG(arg) std::cout << arg << std::endl
struct add_peer_msg struct add_peer_msg
{ {
...@@ -163,10 +164,12 @@ struct post_office_manager ...@@ -163,10 +164,12 @@ struct post_office_manager
{ {
typedef util::single_reader_queue<post_office_msg> queue_t; typedef util::single_reader_queue<post_office_msg> queue_t;
typedef util::single_reader_queue<mailman_job> mailman_queue_t;
// m_pipe[0] is for reading, m_pipe[1] is for writing // m_pipe[0] is for reading, m_pipe[1] is for writing
int m_pipe[2]; int m_pipe[2];
queue_t* m_queue; mailman_queue_t m_mailman_queue;
queue_t m_queue;
boost::thread* m_loop; boost::thread* m_loop;
post_office_manager() post_office_manager()
...@@ -211,7 +214,6 @@ struct post_office_manager ...@@ -211,7 +214,6 @@ struct post_office_manager
throw std::logic_error("unable to set pipe to O_ASYNC"); throw std::logic_error("unable to set pipe to O_ASYNC");
} }
*/ */
m_queue = new queue_t;
m_loop = new boost::thread(post_office_loop, m_pipe[0]); m_loop = new boost::thread(post_office_loop, m_pipe[0]);
} }
...@@ -222,21 +224,33 @@ struct post_office_manager ...@@ -222,21 +224,33 @@ struct post_office_manager
~post_office_manager() ~post_office_manager()
{ {
std::cout << "~post_office_manager() ..." << std::endl; DEBUG("~post_office_manager() ...");
pipe_msg msg = { shutdown_event, 0 }; pipe_msg msg = { shutdown_event, 0 };
write(write_handle(), msg, pipe_msg_size); write(write_handle(), msg, pipe_msg_size);
// m_loop calls close(m_pipe[0]) // m_loop calls close(m_pipe[0])
m_loop->join(); m_loop->join();
delete m_loop; delete m_loop;
delete m_queue;
close(m_pipe[0]); close(m_pipe[0]);
close(m_pipe[1]); close(m_pipe[1]);
std::cout << "~post_office_manager() done" << std::endl; DEBUG("~post_office_manager() ... done");
} }
} }
s_po_manager; s_po_manager;
} } } // namespace cppa::detail::<anonmyous>
namespace cppa { namespace detail {
util::single_reader_queue<mailman_job>& mailman_queue()
{
return s_po_manager.m_mailman_queue;
}
} } // namespace cppa::detail
namespace cppa { namespace detail { namespace {
class remote_observer : public attachable class remote_observer : public attachable
{ {
...@@ -290,9 +304,92 @@ void handle_message(const message& msg, ...@@ -290,9 +304,92 @@ void handle_message(const message& msg,
} }
} }
struct po_peer class post_office_worker
{ {
size_t m_rc;
native_socket_t m_parent;
protected:
native_socket_t m_socket;
post_office_worker(native_socket_t fd, native_socket_t parent_fd = -1)
: m_rc((parent_fd != -1) ? 1 : 0)
, m_parent(parent_fd)
, m_socket(fd)
{
}
post_office_worker(post_office_worker&& other)
: m_rc(other.m_rc)
, m_parent(other.m_parent)
, m_socket(other.m_socket)
{
other.m_rc = 0;
other.m_socket = -1;
other.m_parent = -1;
}
public:
inline size_t ref_count() const
{
return m_rc;
}
inline void inc_ref_count()
{
++m_rc;
}
inline size_t dec_ref_count()
{
if (m_rc == 0) throw std::runtime_error("dec_ref_count(): underflow");
return --m_rc;
}
inline native_socket_t get_socket()
{
return m_socket;
}
inline bool has_parent() const
{
return m_parent != -1;
}
inline native_socket_t parent() const
{
return m_parent;
}
// @return new reference count
size_t parent_exited(native_socket_t parent_socket)
{
if (has_parent() && parent() == parent_socket)
{
m_parent = -1;
return dec_ref_count();
}
return ref_count();
}
virtual ~post_office_worker()
{
if (m_socket != -1)
{
closesocket(m_socket);
}
}
};
class po_peer : public post_office_worker
{
typedef post_office_worker super;
enum state enum state
{ {
// connection just established; waiting for process information // connection just established; waiting for process information
...@@ -300,100 +397,58 @@ struct po_peer ...@@ -300,100 +397,58 @@ struct po_peer
// wait for the size of the next message // wait for the size of the next message
wait_for_msg_size, wait_for_msg_size,
// currently reading a message // currently reading a message
read_message, read_message
// this po_peer is no longer a valid instance
moved
}; };
state m_state; state m_state;
native_socket_t m_sockfd;
process_information_ptr m_peer; process_information_ptr m_peer;
std::unique_ptr<attachable> m_observer; std::unique_ptr<attachable> m_observer;
buffer<s_chunk_size, s_max_buffer_size> m_rdbuf; buffer<s_chunk_size, s_max_buffer_size> m_rdbuf;
bool m_has_parent; std::list<actor_proxy_ptr> m_children;
native_socket_t m_parent;
// counts how many actors currently have a public:
// "reference" to this peer
size_t m_ref_count;
explicit po_peer(add_peer_msg& from) explicit po_peer(add_peer_msg& from)
: m_state(wait_for_msg_size) : super(from.sockfd)
, m_sockfd(from.sockfd) , m_state(wait_for_msg_size)
, m_peer(std::move(from.peer)) , m_peer(std::move(from.peer))
, m_observer(std::move(from.attachable_ptr)) , m_observer(std::move(from.attachable_ptr))
, m_has_parent(false)
, m_parent(-1)
, m_ref_count(0)
{ {
} }
explicit po_peer(native_socket_t sockfd, native_socket_t parent_socket) explicit po_peer(native_socket_t sockfd, native_socket_t parent_socket)
: m_state(wait_for_process_info) : super(sockfd, parent_socket)
, m_sockfd(sockfd) , m_state(wait_for_process_info)
, m_has_parent(true)
, m_parent(parent_socket)
// implicitly referenced by parent
, m_ref_count(1)
{ {
m_rdbuf.reset( sizeof(std::uint32_t) m_rdbuf.reset( sizeof(std::uint32_t)
+ process_information::node_id_size); + process_information::node_id_size);
} }
po_peer(po_peer&& other) po_peer(po_peer&& other)
: m_state(other.m_state) : super(std::move(other))
, m_sockfd(other.m_sockfd) , m_state(other.m_state)
, m_peer(std::move(other.m_peer)) , m_peer(std::move(other.m_peer))
, m_observer(std::move(other.m_observer)) , m_observer(std::move(other.m_observer))
, m_rdbuf(std::move(other.m_rdbuf)) , m_rdbuf(std::move(other.m_rdbuf))
, m_has_parent(other.m_has_parent) , m_children(std::move(other.m_children))
, m_parent(other.m_parent)
, m_ref_count(other.m_ref_count)
{
other.m_state = moved;
other.m_has_parent = false;
}
~po_peer()
{
if (m_state != moved)
{
closesocket(m_sockfd);
if (m_observer)
{
//m_observer->detach(exit_reason::remote_link_unreachable);
}
}
}
inline bool has_parent() const
{ {
return m_has_parent;
} }
inline native_socket_t parent() void add_child(const actor_proxy_ptr& pptr)
{ {
return m_parent; m_children.push_back(pptr);
} }
// @return new reference count ~po_peer()
size_t parent_exited(native_socket_t parent_socket)
{ {
if (has_parent() && parent() == parent_socket) if (!m_children.empty())
{ {
m_has_parent = false; for (actor_proxy_ptr& pptr : m_children)
return --m_ref_count; {
pptr->enqueue(message(nullptr, nullptr, atom(":KillProxy"),
exit_reason::remote_link_unreachable));
}
} }
return m_ref_count;
}
size_t dec_ref_count()
{
return --m_ref_count;
}
void inc_ref_count()
{
++m_ref_count;
} }
// @return false if an error occured; otherwise true // @return false if an error occured; otherwise true
...@@ -404,7 +459,7 @@ struct po_peer ...@@ -404,7 +459,7 @@ struct po_peer
{ {
case wait_for_process_info: case wait_for_process_info:
{ {
if (!m_rdbuf.append_from(m_sockfd, s_rdflag)) return false; if (!m_rdbuf.append_from(m_socket, s_rdflag)) return false;
if (m_rdbuf.ready() == false) if (m_rdbuf.ready() == false)
{ {
break; break;
...@@ -413,7 +468,7 @@ struct po_peer ...@@ -413,7 +468,7 @@ struct po_peer
{ {
m_peer.reset(new process_information); m_peer.reset(new process_information);
// inform mailman about new peer // inform mailman about new peer
mailman_queue().push_back(new mailman_job(m_sockfd, mailman_queue().push_back(new mailman_job(m_socket,
m_peer)); m_peer));
memcpy(&(m_peer->process_id), memcpy(&(m_peer->process_id),
m_rdbuf.data(), m_rdbuf.data(),
...@@ -436,7 +491,7 @@ struct po_peer ...@@ -436,7 +491,7 @@ struct po_peer
{ {
m_rdbuf.reset(sizeof(std::uint32_t)); m_rdbuf.reset(sizeof(std::uint32_t));
} }
if (!m_rdbuf.append_from(m_sockfd, s_rdflag)) return false; if (!m_rdbuf.append_from(m_socket, s_rdflag)) return false;
if (m_rdbuf.ready() == false) if (m_rdbuf.ready() == false)
{ {
break; break;
...@@ -453,7 +508,7 @@ struct po_peer ...@@ -453,7 +508,7 @@ struct po_peer
} }
case read_message: case read_message:
{ {
if (!m_rdbuf.append_from(m_sockfd, s_rdflag)) return false; if (!m_rdbuf.append_from(m_socket, s_rdflag)) return false;
if (m_rdbuf.ready()) if (m_rdbuf.ready())
{ {
message msg; message msg;
...@@ -483,32 +538,26 @@ struct po_peer ...@@ -483,32 +538,26 @@ struct po_peer
}; };
struct po_doorman class po_doorman : public post_office_worker
{ {
typedef post_office_worker super;
// server socket // server socket
bool m_valid;
native_socket_t ssockfd;
actor_ptr published_actor; actor_ptr published_actor;
public:
explicit po_doorman(add_server_socket_msg& assm) explicit po_doorman(add_server_socket_msg& assm)
: m_valid(true) : super(assm.server_sockfd)
, ssockfd(assm.server_sockfd)
, published_actor(assm.published_actor) , published_actor(assm.published_actor)
{ {
} }
po_doorman(po_doorman&& other) po_doorman(po_doorman&& other)
: m_valid(true) : super(std::move(other))
, ssockfd(other.ssockfd)
, published_actor(std::move(other.published_actor)) , published_actor(std::move(other.published_actor))
{ {
other.m_valid = false;
}
~po_doorman()
{
if (m_valid) closesocket(ssockfd);
} }
// @return false if an error occured; otherwise true // @return false if an error occured; otherwise true
...@@ -517,7 +566,9 @@ struct po_doorman ...@@ -517,7 +566,9 @@ struct po_doorman
{ {
sockaddr addr; sockaddr addr;
socklen_t addrlen; socklen_t addrlen;
auto sfd = ::accept(ssockfd, &addr, &addrlen); memset(&addr, 0, sizeof(addr));
memset(&addrlen, 0, sizeof(addrlen));
auto sfd = ::accept(m_socket, &addr, &addrlen);
if (sfd < 0) if (sfd < 0)
{ {
switch (errno) switch (errno)
...@@ -537,15 +588,34 @@ struct po_doorman ...@@ -537,15 +588,34 @@ struct po_doorman
::send(sfd, &id, sizeof(std::uint32_t), 0); ::send(sfd, &id, sizeof(std::uint32_t), 0);
::send(sfd, &(pself.process_id), sizeof(std::uint32_t), 0); ::send(sfd, &(pself.process_id), sizeof(std::uint32_t), 0);
::send(sfd, pself.node_id.data(), pself.node_id.size(), 0); ::send(sfd, pself.node_id.data(), pself.node_id.size(), 0);
peers.push_back(po_peer(sfd, ssockfd)); peers.push_back(po_peer(sfd, m_socket));
DEBUG("socket accepted; published actor: " << id); DEBUG("socket accepted; published actor: " << id);
return true; return true;
} }
}; };
struct mailman_worker
{
boost::thread m_thread;
mailman_worker() : m_thread(mailman_loop)
{
}
~mailman_worker()
{
mailman_queue().push_back(mailman_job::kill_job());
m_thread.join();
}
};
void post_office_loop(int pipe_read_handle) void post_office_loop(int pipe_read_handle)
{ {
// starts and stops mailman
mailman_worker mworker;
// map of all published actors // map of all published actors
std::map<std::uint32_t, std::list<po_doorman> > doormen; std::map<std::uint32_t, std::list<po_doorman> > doormen;
// list of all connected peers // list of all connected peers
...@@ -563,8 +633,6 @@ void post_office_loop(int pipe_read_handle) ...@@ -563,8 +633,6 @@ void post_office_loop(int pipe_read_handle)
FD_SET(pipe_read_handle, &readset); FD_SET(pipe_read_handle, &readset);
// keeps track about what peer we are iterating at this time // keeps track about what peer we are iterating at this time
po_peer* selected_peer = nullptr; po_peer* selected_peer = nullptr;
buffer<pipe_msg_size, pipe_msg_size> pipe_msg_buf;
pipe_msg_buf.reset(pipe_msg_size);
// thread id of post_office // thread id of post_office
auto thread_id = boost::this_thread::get_id(); auto thread_id = boost::this_thread::get_id();
// if an actor calls its quit() handler in this thread, // if an actor calls its quit() handler in this thread,
...@@ -572,29 +640,14 @@ void post_office_loop(int pipe_read_handle) ...@@ -572,29 +640,14 @@ void post_office_loop(int pipe_read_handle)
std::vector<native_socket_t> released_socks; std::vector<native_socket_t> released_socks;
// functor that releases a socket descriptor // functor that releases a socket descriptor
// returns true if an element was removed from peers // returns true if an element was removed from peers
auto release_socket = [&](native_socket_t sockfd) -> bool auto release_socket = [&](native_socket_t sockfd)
{ {
auto i = peers.begin();
auto end = peers.end(); auto end = peers.end();
while (i != end) auto i = std::find_if(peers.begin(), end, [sockfd](po_peer& pp) -> bool
{ {
if (i->m_sockfd == sockfd) return pp.get_socket() == sockfd;
{ });
if (i->dec_ref_count() == 0) if (i != end && i->dec_ref_count() == 0) peers.erase(i);
{
DEBUG("socket closed; last proxy exited");
peers.erase(i);
return true;
}
// exit loop
return false;
}
else
{
++i;
}
}
return false;
}; };
// initialize proxy cache // initialize proxy cache
get_actor_proxy_cache().set_callback([&](actor_proxy_ptr& pptr) get_actor_proxy_cache().set_callback([&](actor_proxy_ptr& pptr)
...@@ -604,8 +657,9 @@ void post_office_loop(int pipe_read_handle) ...@@ -604,8 +657,9 @@ void post_office_loop(int pipe_read_handle)
{ {
throw std::logic_error("selected_peer == nullptr"); throw std::logic_error("selected_peer == nullptr");
} }
selected_peer->add_child(pptr);
selected_peer->inc_ref_count(); selected_peer->inc_ref_count();
auto msock = selected_peer->m_sockfd; auto msock = selected_peer->get_socket();
pptr->attach_functor([msock, thread_id, &released_socks](std::uint32_t) pptr->attach_functor([msock, thread_id, &released_socks](std::uint32_t)
{ {
if (boost::this_thread::get_id() == thread_id) if (boost::this_thread::get_id() == thread_id)
...@@ -630,14 +684,13 @@ void post_office_loop(int pipe_read_handle) ...@@ -630,14 +684,13 @@ void post_office_loop(int pipe_read_handle)
exit(3); exit(3);
} }
//std::cout << __LINE__ << std::endl; //std::cout << __LINE__ << std::endl;
bool recalculate_readset = false;
// iterate over all peers; lifetime scope of i, end // iterate over all peers; lifetime scope of i, end
{ {
auto i = peers.begin(); auto i = peers.begin();
auto end = peers.end(); auto end = peers.end();
while (i != end) while (i != end)
{ {
if (FD_ISSET(i->m_sockfd, &readset)) if (FD_ISSET(i->get_socket(), &readset))
{ {
selected_peer = &(*i); selected_peer = &(*i);
//DEBUG("read message from peer"); //DEBUG("read message from peer");
...@@ -651,7 +704,6 @@ void post_office_loop(int pipe_read_handle) ...@@ -651,7 +704,6 @@ void post_office_loop(int pipe_read_handle)
// peer detected an error; erase from list // peer detected an error; erase from list
DEBUG("connection to peer lost"); DEBUG("connection to peer lost");
i = peers.erase(i); i = peers.erase(i);
recalculate_readset = true;
} }
} }
else else
...@@ -670,7 +722,7 @@ void post_office_loop(int pipe_read_handle) ...@@ -670,7 +722,7 @@ void post_office_loop(int pipe_read_handle)
auto end = list.end(); auto end = list.end();
while (i != end) while (i != end)
{ {
if (FD_ISSET(i->ssockfd, &readset)) if (FD_ISSET(i->get_socket(), &readset))
{ {
DEBUG("accept new socket..."); DEBUG("accept new socket...");
if (i->read_and_continue(pself, peers)) if (i->read_and_continue(pself, peers))
...@@ -683,7 +735,6 @@ void post_office_loop(int pipe_read_handle) ...@@ -683,7 +735,6 @@ void post_office_loop(int pipe_read_handle)
DEBUG("failed; erased doorman"); DEBUG("failed; erased doorman");
i = list.erase(i); i = list.erase(i);
} }
recalculate_readset = true;
} }
else else
{ {
...@@ -694,147 +745,147 @@ void post_office_loop(int pipe_read_handle) ...@@ -694,147 +745,147 @@ void post_office_loop(int pipe_read_handle)
// read events from pipe // read events from pipe
if (FD_ISSET(pipe_read_handle, &readset)) if (FD_ISSET(pipe_read_handle, &readset))
{ {
//pipe_msg pmsg; pipe_msg pmsg;
//pipe_msg_buf.append_from_file_descriptor(pipe_read_handle, true); //memcpy(pmsg, pipe_msg_buf.data(), pipe_msg_buf.size());
//while (pipe_msg_buf.ready()) //pipe_msg_buf.clear();
//{ ::read(pipe_read_handle, &pmsg, pipe_msg_size);
pipe_msg pmsg; switch (pmsg[0])
//memcpy(pmsg, pipe_msg_buf.data(), pipe_msg_buf.size()); {
//pipe_msg_buf.clear(); case rd_queue_event:
::read(pipe_read_handle, &pmsg, pipe_msg_size);
switch (pmsg[0])
{ {
case rd_queue_event: DEBUG("rd_queue_event");
post_office_msg* pom = s_po_manager.m_queue.pop();
if (pom->is_add_peer_msg())
{ {
DEBUG("rd_queue_event"); auto& apm = pom->as_add_peer_msg();
post_office_msg* pom = s_po_manager.m_queue->pop(); actor_proxy_ptr pptr = apm.first_peer_actor;
if (pom->is_add_peer_msg()) po_peer pd(apm);
selected_peer = &pd;
if (pptr)
{ {
auto& apm = pom->as_add_peer_msg(); DEBUG("proxy added via post_office_msg");
actor_proxy_ptr pptr = apm.first_peer_actor; get_actor_proxy_cache().add(pptr);
po_peer pd(apm); }
selected_peer = &pd; selected_peer = nullptr;
if (pptr) peers.push_back(std::move(pd));
{ DEBUG("new peer (remote_actor)");
DEBUG("proxy added via post_office_msg"); }
get_actor_proxy_cache().add(pptr); else
} {
selected_peer = nullptr; auto& assm = pom->as_add_server_socket_msg();
peers.push_back(std::move(pd)); auto& pactor = assm.published_actor;
recalculate_readset = true; if (!pactor)
DEBUG("new peer (remote_actor)"); {
throw std::logic_error("nullptr published");
} }
else auto actor_id = pactor->id();
auto callback = [actor_id](std::uint32_t)
{ {
auto& assm = pom->as_add_server_socket_msg(); DEBUG("call post_office_unpublish() ...");
auto& pactor = assm.published_actor; post_office_unpublish(actor_id);
if (!pactor) };
{ if (pactor->attach_functor(std::move(callback)))
throw std::logic_error("nullptr published"); {
} auto& dm = doormen[actor_id];
auto actor_id = pactor->id(); dm.push_back(po_doorman(assm));
auto callback = [actor_id](std::uint32_t) DEBUG("new doorman");
{
DEBUG("call post_office_unpublish() ...");
post_office_unpublish(actor_id);
};
if (pactor->attach_functor(std::move(callback)))
{
auto& dm = doormen[actor_id];
dm.push_back(po_doorman(assm));
recalculate_readset = true;
DEBUG("new doorman");
}
// else: actor already exited!
} }
delete pom; // else: actor already exited!
break;
} }
case unpublish_actor_event: delete pom;
break;
}
case unpublish_actor_event:
{
DEBUG("unpublish_actor_event");
auto kvp = doormen.find(pmsg[1]);
if (kvp != doormen.end())
{ {
DEBUG("unpublish_actor_event"); for (po_doorman& dm : kvp->second)
auto kvp = doormen.find(pmsg[1]);
if (kvp != doormen.end())
{ {
for (po_doorman& dm : kvp->second) auto i = peers.begin();
auto end = peers.end();
while (i != end)
{ {
auto i = peers.begin(); if (i->parent_exited(dm.get_socket()) == 0)
auto end = peers.end();
while (i != end)
{ {
if (i->parent_exited(dm.ssockfd) == 0) DEBUG("socket closed; parent exited");
{ i = peers.erase(i);
DEBUG("socket closed; parent exited"); }
i = peers.erase(i); else
} {
else ++i;
{
++i;
}
} }
} }
doormen.erase(kvp);
recalculate_readset = true;
} }
break; doormen.erase(kvp);
} }
case dec_socket_ref_event: break;
}
case dec_socket_ref_event:
{
auto sockfd = static_cast<native_socket_t>(pmsg[1]);
release_socket(sockfd);
break;
}
case close_socket_event:
{
auto sockfd = static_cast<native_socket_t>(pmsg[1]);
auto i = peers.begin();
auto end = peers.end();
while (i != end)
{ {
auto sockfd = static_cast<native_socket_t>(pmsg[1]); if (i->get_socket() == sockfd)
if (release_socket(sockfd))
{ {
recalculate_readset = true; // exit loop
peers.erase(i);
i = end;
} }
break; else ++i;
} }
case shutdown_event: break;
{ }
// goodbye case shutdown_event:
DEBUG("case shutdown_event"); {
close(pipe_read_handle); // goodbye
return; return;
}
default: throw std::logic_error("unexpected event type");
} }
// next iteration? default:
//pipe_msg_buf.append_from_file_descriptor(pipe_read_handle, {
// true); std::ostringstream oss;
//} oss << "unexpected event type: " << pmsg[0];
throw std::logic_error(oss.str());
}
}
} }
if (released_socks.empty() == false) if (released_socks.empty() == false)
{ {
for (native_socket_t sockfd : released_socks) for (native_socket_t sockfd : released_socks)
{ {
if (release_socket(sockfd)) release_socket(sockfd);
{
recalculate_readset = true;
}
} }
} }
// recalculate readset if needed // recalculate readset if needed
if (recalculate_readset) //DEBUG("recalculate readset");
FD_ZERO(&readset);
FD_SET(pipe_read_handle, &readset);
maxfd = pipe_read_handle;
for (po_peer& pd : peers)
{ {
//DEBUG("recalculate readset"); auto fd = pd.get_socket();
FD_ZERO(&readset); if (fd > maxfd) maxfd = fd;
FD_SET(pipe_read_handle, &readset); FD_SET(fd, &readset);
maxfd = pipe_read_handle; }
for (po_peer& pd : peers) // iterate over key value pairs
for (auto& kvp : doormen)
{
// iterate over value (= list of doormen)
for (auto& dm : kvp.second)
{ {
auto fd = pd.m_sockfd; auto fd = dm.get_socket();
if (fd > maxfd) maxfd = fd; if (fd > maxfd) maxfd = fd;
FD_SET(fd, &readset); FD_SET(fd, &readset);
} }
// iterate over key value pairs
for (auto& kvp : doormen)
{
// iterate over value (= list of doormen)
for (auto& dm : kvp.second)
{
auto fd = dm.ssockfd;
if (fd > maxfd) maxfd = fd;
FD_SET(fd, &readset);
}
}
} }
} }
} }
...@@ -848,8 +899,7 @@ void post_office_add_peer(native_socket_t a0, ...@@ -848,8 +899,7 @@ void post_office_add_peer(native_socket_t a0,
const actor_proxy_ptr& a2, const actor_proxy_ptr& a2,
std::unique_ptr<attachable>&& a3) std::unique_ptr<attachable>&& a3)
{ {
DEBUG(__FUNCTION__); s_po_manager.m_queue.push_back(new post_office_msg(a0, a1, a2,
s_po_manager.m_queue->push_back(new post_office_msg(a0, a1, a2,
std::move(a3))); std::move(a3)));
pipe_msg msg = { rd_queue_event, 0 }; pipe_msg msg = { rd_queue_event, 0 };
write(s_po_manager.write_handle(), msg, pipe_msg_size); write(s_po_manager.write_handle(), msg, pipe_msg_size);
...@@ -858,8 +908,7 @@ void post_office_add_peer(native_socket_t a0, ...@@ -858,8 +908,7 @@ void post_office_add_peer(native_socket_t a0,
void post_office_publish(native_socket_t server_socket, void post_office_publish(native_socket_t server_socket,
const actor_ptr& published_actor) const actor_ptr& published_actor)
{ {
DEBUG(__FUNCTION__ << "(..., " << published_actor->id() << ")"); s_po_manager.m_queue.push_back(new post_office_msg(server_socket,
s_po_manager.m_queue->push_back(new post_office_msg(server_socket,
published_actor)); published_actor));
pipe_msg msg = { rd_queue_event, 0 }; pipe_msg msg = { rd_queue_event, 0 };
write(s_po_manager.write_handle(), msg, pipe_msg_size); write(s_po_manager.write_handle(), msg, pipe_msg_size);
...@@ -867,27 +916,14 @@ void post_office_publish(native_socket_t server_socket, ...@@ -867,27 +916,14 @@ void post_office_publish(native_socket_t server_socket,
void post_office_unpublish(std::uint32_t actor_id) void post_office_unpublish(std::uint32_t actor_id)
{ {
DEBUG(__FUNCTION__ << "(" << actor_id << ")");
pipe_msg msg = { unpublish_actor_event, actor_id }; pipe_msg msg = { unpublish_actor_event, actor_id };
write(s_po_manager.write_handle(), msg, pipe_msg_size); write(s_po_manager.write_handle(), msg, pipe_msg_size);
} }
void post_office_close_socket(native_socket_t sfd) void post_office_close_socket(native_socket_t sfd)
{ {
DEBUG(__FUNCTION__ << "(...)");
pipe_msg msg = { close_socket_event, static_cast<std::uint32_t>(sfd) }; pipe_msg msg = { close_socket_event, static_cast<std::uint32_t>(sfd) };
write(s_po_manager.write_handle(), msg, pipe_msg_size); write(s_po_manager.write_handle(), msg, pipe_msg_size);
} }
//void post_office_unpublish(const actor_ptr& published_actor)
//{
// pipe_msg msg = { unpublish_actor_event, published_actor->id() };
// write(s_po_manager.write_handle(), msg, pipe_msg_size);
//}
//void post_office_proxy_exited(const actor_proxy_ptr& proxy_ptr)
//{
// std::uint32_t
//}
} } // namespace cppa::detail } } // namespace cppa::detail
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