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
9afd06ce
Commit
9afd06ce
authored
Mar 06, 2015
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Simplify group module shutdown procedure
parent
a127cac1
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
51 additions
and
67 deletions
+51
-67
libcaf_core/src/group_manager.cpp
libcaf_core/src/group_manager.cpp
+51
-67
No files found.
libcaf_core/src/group_manager.cpp
View file @
9afd06ce
...
@@ -48,35 +48,28 @@ using upgrade_to_unique_guard = upgrade_to_unique_lock<detail::shared_spinlock>;
...
@@ -48,35 +48,28 @@ using upgrade_to_unique_guard = upgrade_to_unique_lock<detail::shared_spinlock>;
class
local_broker
;
class
local_broker
;
class
local_group_module
;
class
local_group_module
;
// simple handshake for one central component and X clients
void
await_all_locals_down
(
std
::
initializer_list
<
actor
>
xs
)
{
class
latch
{
CAF_LOGF_TRACE
(
""
);
public:
size_t
awaited_down_msgs
=
0
;
latch
(
int
value
)
:
m_value
(
value
)
{
scoped_actor
self
{
true
};
for
(
auto
&
x
:
xs
)
{
if
(
x
!=
invalid_actor
&&
!
x
.
is_remote
())
{
self
->
monitor
(
x
);
self
->
send_exit
(
x
,
exit_reason
::
user_shutdown
);
++
awaited_down_msgs
;
}
}
for
(
size_t
i
=
0
;
i
<
awaited_down_msgs
;
++
i
)
{
self
->
receive
(
[](
const
down_msg
&
)
{
// nop
// nop
},
after
(
std
::
chrono
::
seconds
(
1
))
>>
[
&
]
{
throw
std
::
logic_error
(
"at least one actor did not quit within 1s"
);
}
}
);
void
wait
()
{
std
::
unique_lock
<
std
::
mutex
>
guard
{
m_mtx
};
while
(
m_value
!=
0
)
{
m_cv
.
wait
(
guard
);
}
}
void
count_down
()
{
std
::
unique_lock
<
std
::
mutex
>
guard
;
--
m_value
;
m_cv
.
notify_one
();
}
~
latch
()
{
CAF_REQUIRE
(
m_value
==
0
);
}
}
}
private:
volatile
int
m_value
;
std
::
mutex
m_mtx
;
std
::
condition_variable
m_cv
;
};
class
local_group
:
public
abstract_group
{
class
local_group
:
public
abstract_group
{
public:
public:
...
@@ -132,8 +125,8 @@ class local_group : public abstract_group {
...
@@ -132,8 +125,8 @@ class local_group : public abstract_group {
void
stop
()
override
{
void
stop
()
override
{
CAF_LOG_TRACE
(
""
);
CAF_LOG_TRACE
(
""
);
a
non_send_exit
(
m_broker
,
exit_reason
::
user_shutdown
);
a
wait_all_locals_down
({
m_broker
}
);
m_
latch
.
wait
()
;
m_
broker
=
invalid_actor
;
}
}
const
actor
&
broker
()
const
{
const
actor
&
broker
()
const
{
...
@@ -148,40 +141,36 @@ class local_group : public abstract_group {
...
@@ -148,40 +141,36 @@ class local_group : public abstract_group {
detail
::
shared_spinlock
m_mtx
;
detail
::
shared_spinlock
m_mtx
;
std
::
set
<
actor_addr
>
m_subscribers
;
std
::
set
<
actor_addr
>
m_subscribers
;
actor
m_broker
;
actor
m_broker
;
latch
m_latch
;
};
};
using
local_group_ptr
=
intrusive_ptr
<
local_group
>
;
using
local_group_ptr
=
intrusive_ptr
<
local_group
>
;
class
local_broker
:
public
event_based_actor
{
class
local_broker
:
public
event_based_actor
{
public:
public:
local_broker
(
local_group_ptr
g
,
latch
*
hv
)
local_broker
(
local_group_ptr
g
)
:
m_group
(
std
::
move
(
g
))
{
:
m_group
(
std
::
move
(
g
)),
m_hv
(
hv
)
{
// nop
// nop
}
}
void
on_exit
()
{
void
on_exit
()
{
m_acquaintances
.
clear
();
m_acquaintances
.
clear
();
m_hv
->
count_down
();
m_group
.
reset
();
m_group
.
reset
();
}
}
behavior
make_behavior
()
override
{
behavior
make_behavior
()
override
{
return
{
return
{
on
(
atom
(
"JOIN"
),
arg_match
)
>>
[
=
](
const
actor
&
other
)
{
[
=
](
join_atom
,
const
actor
&
other
)
{
CAF_LOG_TRACE
(
CAF_TSARG
(
other
));
CAF_LOG_TRACE
(
CAF_TSARG
(
other
));
if
(
other
&&
m_acquaintances
.
insert
(
other
).
second
)
{
if
(
other
&&
m_acquaintances
.
insert
(
other
).
second
)
{
monitor
(
other
);
monitor
(
other
);
}
}
},
},
on
(
atom
(
"LEAVE"
),
arg_match
)
>>
[
=
](
const
actor
&
other
)
{
[
=
](
leave_atom
,
const
actor
&
other
)
{
CAF_LOG_TRACE
(
CAF_TSARG
(
other
));
CAF_LOG_TRACE
(
CAF_TSARG
(
other
));
if
(
other
&&
m_acquaintances
.
erase
(
other
)
>
0
)
{
if
(
other
&&
m_acquaintances
.
erase
(
other
)
>
0
)
{
demonitor
(
other
);
demonitor
(
other
);
}
}
},
},
on
(
atom
(
"_Forward"
),
arg_match
)
>>
[
=
](
const
message
&
what
)
{
[
=
](
forward_atom
,
const
message
&
what
)
{
CAF_LOG_TRACE
(
CAF_TSARG
(
what
));
CAF_LOG_TRACE
(
CAF_TSARG
(
what
));
// local forwarding
// local forwarding
m_group
->
send_all_subscribers
(
current_sender
(),
what
,
host
());
m_group
->
send_all_subscribers
(
current_sender
(),
what
,
host
());
...
@@ -224,10 +213,9 @@ class local_broker : public event_based_actor {
...
@@ -224,10 +213,9 @@ class local_broker : public event_based_actor {
local_group_ptr
m_group
;
local_group_ptr
m_group
;
std
::
set
<
actor
>
m_acquaintances
;
std
::
set
<
actor
>
m_acquaintances
;
latch
*
m_hv
;
};
};
// Send a
"JOIN"
message to the original group if a proxy
// Send a
join
message to the original group if a proxy
// has local subscriptions and a "LEAVE" message to the original group
// has local subscriptions and a "LEAVE" message to the original group
// if there's no subscription left.
// if there's no subscription left.
...
@@ -243,7 +231,7 @@ class local_group_proxy : public local_group {
...
@@ -243,7 +231,7 @@ class local_group_proxy : public local_group {
CAF_REQUIRE
(
m_broker
==
invalid_actor
);
CAF_REQUIRE
(
m_broker
==
invalid_actor
);
CAF_REQUIRE
(
remote_broker
!=
invalid_actor
);
CAF_REQUIRE
(
remote_broker
!=
invalid_actor
);
m_broker
=
std
::
move
(
remote_broker
);
m_broker
=
std
::
move
(
remote_broker
);
m_proxy_broker
=
spawn
<
proxy_broker
,
hidden
>
(
&
m_latch
,
this
);
m_proxy_broker
=
spawn
<
proxy_broker
,
hidden
>
(
this
);
}
}
attachable_ptr
subscribe
(
const
actor_addr
&
who
)
override
{
attachable_ptr
subscribe
(
const
actor_addr
&
who
)
override
{
...
@@ -252,7 +240,7 @@ class local_group_proxy : public local_group {
...
@@ -252,7 +240,7 @@ class local_group_proxy : public local_group {
if
(
res
.
first
)
{
if
(
res
.
first
)
{
if
(
res
.
second
==
1
)
{
if
(
res
.
second
==
1
)
{
// join the remote source
// join the remote source
anon_send
(
m_broker
,
atom
(
"JOIN"
)
,
m_proxy_broker
);
anon_send
(
m_broker
,
join_atom
::
value
,
m_proxy_broker
);
}
}
return
subscription
::
make
(
this
);
return
subscription
::
make
(
this
);
}
}
...
@@ -266,7 +254,7 @@ class local_group_proxy : public local_group {
...
@@ -266,7 +254,7 @@ class local_group_proxy : public local_group {
if
(
res
.
first
&&
res
.
second
==
0
)
{
if
(
res
.
first
&&
res
.
second
==
0
)
{
// leave the remote source,
// leave the remote source,
// because there's no more subscriber on this node
// because there's no more subscriber on this node
anon_send
(
m_broker
,
atom
(
"LEAVE"
)
,
m_proxy_broker
);
anon_send
(
m_broker
,
leave_atom
::
value
,
m_proxy_broker
);
}
}
}
}
...
@@ -274,13 +262,15 @@ class local_group_proxy : public local_group {
...
@@ -274,13 +262,15 @@ class local_group_proxy : public local_group {
execution_unit
*
eu
)
override
{
execution_unit
*
eu
)
override
{
// forward message to the broker
// forward message to the broker
m_broker
->
enqueue
(
sender
,
mid
,
m_broker
->
enqueue
(
sender
,
mid
,
make_message
(
atom
(
"_Forward"
),
std
::
move
(
msg
)),
eu
);
make_message
(
forward_atom
::
value
,
std
::
move
(
msg
)),
eu
);
}
}
void
stop
()
override
{
void
stop
()
override
{
CAF_LOG_TRACE
(
""
);
CAF_LOG_TRACE
(
""
);
anon_send_exit
(
m_proxy_broker
,
exit_reason
::
user_shutdown
);
await_all_locals_down
({
m_proxy_broker
,
m_broker
});
m_latch
.
wait
();
m_proxy_broker
=
invalid_actor
;
m_broker
=
invalid_actor
;
}
}
private:
private:
...
@@ -291,9 +281,7 @@ using local_group_proxy_ptr = intrusive_ptr<local_group_proxy>;
...
@@ -291,9 +281,7 @@ using local_group_proxy_ptr = intrusive_ptr<local_group_proxy>;
class
proxy_broker
:
public
event_based_actor
{
class
proxy_broker
:
public
event_based_actor
{
public:
public:
proxy_broker
(
latch
*
grp_latch
,
local_group_proxy_ptr
grp
)
proxy_broker
(
local_group_proxy_ptr
grp
)
:
m_group
(
std
::
move
(
grp
))
{
:
m_latch
(
grp_latch
),
m_group
(
std
::
move
(
grp
))
{
// nop
// nop
}
}
...
@@ -308,17 +296,16 @@ class proxy_broker : public event_based_actor {
...
@@ -308,17 +296,16 @@ class proxy_broker : public event_based_actor {
void
on_exit
()
{
void
on_exit
()
{
m_group
.
reset
();
m_group
.
reset
();
m_latch
->
count_down
();
}
}
private:
private:
latch
*
m_latch
;
local_group_proxy_ptr
m_group
;
local_group_proxy_ptr
m_group
;
};
};
class
local_group_module
:
public
abstract_group
::
module
{
class
local_group_module
:
public
abstract_group
::
module
{
public:
public:
using
super
=
abstract_group
::
module
;
using
super
=
abstract_group
::
module
;
local_group_module
()
local_group_module
()
:
super
(
"local"
),
m_actor_utype
(
uniform_typeid
<
actor
>
())
{
:
super
(
"local"
),
m_actor_utype
(
uniform_typeid
<
actor
>
())
{
// nop
// nop
...
@@ -329,18 +316,17 @@ class local_group_module : public abstract_group::module {
...
@@ -329,18 +316,17 @@ class local_group_module : public abstract_group::module {
auto
i
=
m_instances
.
find
(
identifier
);
auto
i
=
m_instances
.
find
(
identifier
);
if
(
i
!=
m_instances
.
end
())
{
if
(
i
!=
m_instances
.
end
())
{
return
{
i
->
second
};
return
{
i
->
second
};
}
else
{
}
auto
tmp
=
make_counted
<
local_group
>
(
true
,
this
,
identifier
);
auto
tmp
=
make_counted
<
local_group
>
(
true
,
this
,
identifier
);
{
// lifetime scope of uguard
upgrade_to_unique_guard
uguard
(
guard
);
upgrade_to_unique_guard
uguard
(
guard
);
auto
p
=
m_instances
.
insert
(
make_pair
(
identifier
,
tmp
));
auto
p
=
m_instances
.
insert
(
make_pair
(
identifier
,
tmp
));
auto
result
=
p
.
first
->
second
;
uguard
.
unlock
();
// someone might preempt us
// someone might preempt us
if
(
p
.
first
->
second
!=
tmp
)
{
if
(
result
!=
tmp
)
{
tmp
->
stop
();
tmp
->
stop
();
}
}
return
{
p
.
first
->
second
};
return
{
result
};
}
}
}
}
group
deserialize
(
deserializer
*
source
)
override
{
group
deserialize
(
deserializer
*
source
)
override
{
...
@@ -401,13 +387,11 @@ class local_group_module : public abstract_group::module {
...
@@ -401,13 +387,11 @@ class local_group_module : public abstract_group::module {
};
};
local_group
::
local_group
(
bool
do_spawn
,
local_group_module
*
mod
,
std
::
string
id
)
local_group
::
local_group
(
bool
do_spawn
,
local_group_module
*
mod
,
std
::
string
id
)
:
abstract_group
(
mod
,
std
::
move
(
id
)),
:
abstract_group
(
mod
,
std
::
move
(
id
))
{
m_latch
(
1
)
{
if
(
do_spawn
)
{
if
(
do_spawn
)
{
m_broker
=
spawn
<
local_broker
,
hidden
>
(
this
,
&
m_latch
);
m_broker
=
spawn
<
local_broker
,
hidden
>
(
this
);
}
}
// else: derived class spawns an actor and
// else: derived class spawns m_broker
// uses the latch for overriding stop()
}
}
local_group
::~
local_group
()
{
local_group
::~
local_group
()
{
...
@@ -420,7 +404,7 @@ void local_group::serialize(serializer* sink) {
...
@@ -420,7 +404,7 @@ void local_group::serialize(serializer* sink) {
static_cast
<
local_group_module
*>
(
m_module
)
->
serialize
(
this
,
sink
);
static_cast
<
local_group_module
*>
(
m_module
)
->
serialize
(
this
,
sink
);
}
}
std
::
atomic
<
size_t
>
m
_ad_hoc_id
;
std
::
atomic
<
size_t
>
s
_ad_hoc_id
;
}
// namespace <anonymous>
}
// namespace <anonymous>
...
@@ -447,7 +431,7 @@ group_manager::group_manager() {
...
@@ -447,7 +431,7 @@ group_manager::group_manager() {
group
group_manager
::
anonymous
()
{
group
group_manager
::
anonymous
()
{
std
::
string
id
=
"__#"
;
std
::
string
id
=
"__#"
;
id
+=
std
::
to_string
(
++
m
_ad_hoc_id
);
id
+=
std
::
to_string
(
++
s
_ad_hoc_id
);
return
get_module
(
"local"
)
->
get
(
id
);
return
get_module
(
"local"
)
->
get
(
id
);
}
}
...
...
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