Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
d7088d90
Commit
d7088d90
authored
Jun 14, 2011
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixed select() bug and static initialization/deinitialization
parent
7023a997
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
298 additions
and
254 deletions
+298
-254
cppa/detail/mailman.hpp
cppa/detail/mailman.hpp
+2
-0
src/mailman.cpp
src/mailman.cpp
+18
-12
src/post_office.cpp
src/post_office.cpp
+278
-242
No files found.
cppa/detail/mailman.hpp
View file @
d7088d90
...
@@ -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
...
...
src/mailman.cpp
View file @
d7088d90
#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
src/post_office.cpp
View file @
d7088d90
...
@@ -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_pe
er
class
post_office_work
er
{
{
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_s
ockfd
(
from
.
sockfd
)
,
m_s
tate
(
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_s
ockfd
(
other
.
m_sockfd
)
,
m_s
tate
(
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_sock
fd
,
s_rdflag
))
return
false
;
if
(
!
m_rdbuf
.
append_from
(
m_sock
et
,
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_sock
fd
,
mailman_queue
().
push_back
(
new
mailman_job
(
m_sock
et
,
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_sock
fd
,
s_rdflag
))
return
false
;
if
(
!
m_rdbuf
.
append_from
(
m_sock
et
,
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_sock
fd
,
s_rdflag
))
return
false
;
if
(
!
m_rdbuf
.
append_from
(
m_sock
et
,
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment