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
0cf245c8
Commit
0cf245c8
authored
Feb 13, 2012
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
maintenance
parent
a86ae7a4
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
122 additions
and
119 deletions
+122
-119
Makefile.am
Makefile.am
+1
-0
cppa.files
cppa.files
+1
-0
cppa/abstract_actor.hpp
cppa/abstract_actor.hpp
+26
-44
cppa/abstract_event_based_actor.hpp
cppa/abstract_event_based_actor.hpp
+5
-63
cppa/detail/disablable_delete.hpp
cppa/detail/disablable_delete.hpp
+57
-0
cppa/either.hpp
cppa/either.hpp
+3
-0
src/abstract_event_based_actor.cpp
src/abstract_event_based_actor.cpp
+5
-4
src/event_based_actor.cpp
src/event_based_actor.cpp
+9
-5
src/stacked_event_based_actor.cpp
src/stacked_event_based_actor.cpp
+10
-3
unit_testing/test__atom.cpp
unit_testing/test__atom.cpp
+3
-0
unit_testing/test__intrusive_ptr.cpp
unit_testing/test__intrusive_ptr.cpp
+2
-0
No files found.
Makefile.am
View file @
0cf245c8
...
...
@@ -106,6 +106,7 @@ nobase_library_include_HEADERS = \
cppa/detail/default_uniform_type_info_impl.hpp
\
cppa/detail/delegate.hpp
\
cppa/detail/demangle.hpp
\
cppa/detail/disablable_delete.hpp
\
cppa/detail/empty_tuple.hpp
\
cppa/detail/get_behavior.hpp
\
cppa/detail/group_manager.hpp
\
...
...
cppa.files
View file @
0cf245c8
...
...
@@ -260,3 +260,4 @@ benchmarks/theron_mixed_case.cpp
cppa/util/static_foreach.hpp
cppa/type_value_pair.hpp
examples/dining_philosophers.cpp
cppa/detail/disablable_delete.hpp
cppa/abstract_actor.hpp
View file @
0cf245c8
...
...
@@ -60,18 +60,16 @@ class abstract_actor : public Base
std
::
atomic
<
std
::
uint32_t
>
m_exit_reason
;
// guards access to m_exited, m_subscriptions and m_links
//std::mutex m_mtx;
detail
::
mutex
m_mtx
;
//
manages actor link
s
std
::
list
<
actor_ptr
>
m_links
;
//
links to other actor
s
std
::
vector
<
actor_ptr
>
m_links
;
// code that is executed on cleanup
std
::
vector
<
attachable_ptr
>
m_attachables
;
public:
class
queue_node_ptr
;
struct
queue_node
{
friend
class
abstract_actor
;
...
...
@@ -106,36 +104,6 @@ class abstract_actor : public Base
return
m_exit_reason
.
load
()
!=
exit_reason
::
not_exited
;
}
template
<
class
List
,
typename
Element
>
bool
unique_insert
(
List
&
lst
,
Element
const
&
e
)
{
auto
end
=
lst
.
end
();
auto
i
=
std
::
find
(
lst
.
begin
(),
end
,
e
);
if
(
i
==
end
)
{
lst
.
push_back
(
e
);
return
true
;
}
return
false
;
}
template
<
class
List
,
typename
Iterator
,
typename
Element
>
int
erase_all
(
List
&
lst
,
Iterator
begin
,
Iterator
end
,
Element
const
&
e
)
{
auto
i
=
std
::
find
(
begin
,
end
,
e
);
if
(
i
!=
end
)
{
return
1
+
erase_all
(
lst
,
lst
.
erase
(
i
),
end
,
e
);
}
return
0
;
}
template
<
class
List
,
typename
Element
>
int
erase_all
(
List
&
lst
,
Element
const
&
e
)
{
return
erase_all
(
lst
,
lst
.
begin
(),
lst
.
end
(),
e
);
}
protected:
template
<
typename
T
>
...
...
@@ -170,13 +138,10 @@ class abstract_actor : public Base
m_links
.
clear
();
m_attachables
.
clear
();
}
if
(
!
mlinks
.
empty
())
// send exit messages
for
(
actor_ptr
&
aptr
:
mlinks
)
{
// send exit messages
for
(
actor_ptr
&
aptr
:
mlinks
)
{
aptr
->
enqueue
(
this
,
make_tuple
(
atom
(
":Exit"
),
reason
));
}
aptr
->
enqueue
(
this
,
make_tuple
(
atom
(
":Exit"
),
reason
));
}
for
(
attachable_ptr
&
ptr
:
mattachables
)
{
...
...
@@ -189,11 +154,14 @@ class abstract_actor : public Base
if
(
other
&&
other
!=
this
)
{
guard_type
guard
(
m_mtx
);
// send exit message if already exited
if
(
exited
())
{
other
->
enqueue
(
this
,
make_tuple
(
atom
(
":Exit"
),
m_exit_reason
.
load
()));
}
// add link if not already linked to other
// (checked by establish_backlink)
else
if
(
other
->
establish_backlink
(
this
))
{
m_links
.
push_back
(
other
);
...
...
@@ -206,9 +174,13 @@ class abstract_actor : public Base
bool
unlink_from_impl
(
intrusive_ptr
<
actor
>&
other
)
{
guard_type
guard
(
m_mtx
);
// remove_backlink returns true if this actor is linked to other
if
(
other
&&
!
exited
()
&&
other
->
remove_backlink
(
this
))
{
return
erase_all
(
m_links
,
other
)
>
0
;
auto
i
=
std
::
find
(
m_links
.
begin
(),
m_links
.
end
(),
other
);
CPPA_REQUIRE
(
i
!=
m_links
.
end
());
m_links
.
erase
(
i
);
return
true
;
}
return
false
;
}
...
...
@@ -278,7 +250,12 @@ class abstract_actor : public Base
if
(
other
&&
other
!=
this
)
{
guard_type
guard
(
m_mtx
);
return
erase_all
(
m_links
,
other
)
>
0
;
auto
i
=
std
::
find
(
m_links
.
begin
(),
m_links
.
end
(),
other
);
if
(
i
!=
m_links
.
end
())
{
m_links
.
erase
(
i
);
return
true
;
}
}
return
false
;
}
...
...
@@ -292,7 +269,12 @@ class abstract_actor : public Base
reason
=
m_exit_reason
.
load
();
if
(
reason
==
exit_reason
::
not_exited
)
{
return
unique_insert
(
m_links
,
other
);
auto
i
=
std
::
find
(
m_links
.
begin
(),
m_links
.
end
(),
other
);
if
(
i
==
m_links
.
end
())
{
m_links
.
push_back
(
other
);
return
true
;
}
}
}
// send exit message without lock
...
...
cppa/abstract_event_based_actor.hpp
View file @
0cf245c8
...
...
@@ -39,6 +39,7 @@
#include "cppa/either.hpp"
#include "cppa/pattern.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/detail/disablable_delete.hpp"
#include "cppa/detail/abstract_scheduled_actor.hpp"
namespace
cppa
{
...
...
@@ -95,69 +96,10 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
abstract_event_based_actor
();
struct
stack_element
{
stack_element
()
=
delete
;
stack_element
(
stack_element
const
&
)
=
delete
;
stack_element
&
operator
=
(
stack_element
const
&
)
=
delete
;
either
<
invoke_rules
*
,
timed_invoke_rules
*>
m_ptr
;
bool
m_ownership
;
inline
stack_element
(
invoke_rules
*
ptr
,
bool
take_ownership
)
:
m_ptr
(
ptr
),
m_ownership
(
take_ownership
)
{
}
inline
stack_element
(
timed_invoke_rules
*
ptr
,
bool
take_ownership
)
:
m_ptr
(
ptr
),
m_ownership
(
take_ownership
)
{
}
inline
stack_element
(
stack_element
&&
other
)
:
m_ptr
(
other
.
m_ptr
),
m_ownership
(
other
.
m_ownership
)
{
other
.
m_ownership
=
false
;
}
inline
stack_element
&
operator
=
(
stack_element
&&
other
)
{
m_ptr
=
other
.
m_ptr
;
m_ownership
=
other
.
m_ownership
;
other
.
m_ownership
=
false
;
return
*
this
;
}
inline
~
stack_element
()
{
if
(
m_ownership
)
{
if
(
m_ptr
.
is_left
())
{
delete
m_ptr
.
left
();
}
else
{
delete
m_ptr
.
right
();
}
}
}
inline
bool
is_left
()
{
return
m_ptr
.
is_left
();
}
inline
bool
is_right
()
{
return
m_ptr
.
is_right
();
}
inline
invoke_rules
&
left
()
{
auto
ptr
=
m_ptr
.
left
();
CPPA_REQUIRE
(
ptr
!=
nullptr
);
return
*
(
ptr
);
}
inline
timed_invoke_rules
&
right
()
{
auto
ptr
=
m_ptr
.
right
();
CPPA_REQUIRE
(
ptr
!=
nullptr
);
return
*
(
ptr
);
}
};
// ownership flag + pointer
typedef
either
<
std
::
unique_ptr
<
invoke_rules
,
detail
::
disablable_delete
<
invoke_rules
>>
,
std
::
unique_ptr
<
timed_invoke_rules
,
detail
::
disablable_delete
<
timed_invoke_rules
>>>
stack_element
;
queue_node_buffer
m_buffer
;
std
::
vector
<
stack_element
>
m_loop_stack
;
...
...
cppa/detail/disablable_delete.hpp
0 → 100644
View file @
0cf245c8
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef DISABLABLE_DELETE_HPP
#define DISABLABLE_DELETE_HPP
namespace
cppa
{
namespace
detail
{
template
<
typename
T
>
class
disablable_delete
{
bool
m_enabled
;
public:
disablable_delete
()
:
m_enabled
(
true
)
{
}
inline
void
disable
()
{
m_enabled
=
false
;
}
inline
void
operator
()(
T
*
ptr
)
{
if
(
m_enabled
)
delete
ptr
;
}
};
}
}
// namespace cppa::detail
#endif // DISABLABLE_DELETE_HPP
cppa/either.hpp
View file @
0cf245c8
...
...
@@ -51,6 +51,9 @@ class either
public:
typedef
Left
left_type
;
typedef
Right
right_type
;
/**
* @brief Default constructor, creates a @p Left.
*/
...
...
src/abstract_event_based_actor.cpp
View file @
0cf245c8
...
...
@@ -72,9 +72,10 @@ void abstract_event_based_actor::handle_message(queue_node_ptr& node,
// request next timeout if needed
if
(
!
m_loop_stack
.
empty
())
{
if
(
m_loop_stack
.
back
().
is_right
())
auto
&
back
=
m_loop_stack
.
back
();
if
(
back
.
is_right
())
{
request_timeout
(
m_loop_stack
.
back
().
right
().
timeout
());
request_timeout
(
back
.
right
()
->
timeout
());
}
}
break
;
...
...
@@ -88,11 +89,11 @@ void abstract_event_based_actor::handle_message(queue_node_ptr& node)
auto
&
bhvr
=
m_loop_stack
.
back
();
if
(
bhvr
.
is_left
())
{
handle_message
(
node
,
bhvr
.
left
(
));
handle_message
(
node
,
*
(
bhvr
.
left
()
));
}
else
{
handle_message
(
node
,
bhvr
.
right
(
));
handle_message
(
node
,
*
(
bhvr
.
right
()
));
}
}
...
...
src/event_based_actor.cpp
View file @
0cf245c8
...
...
@@ -33,19 +33,19 @@
namespace
{
template
<
class
StackElement
,
class
Vec
,
class
What
>
void
push_to
(
Vec
&
vec
,
What
*
bhvr
,
bool
has_ownership
)
void
push_to
(
Vec
&
vec
,
What
&&
bhvr
)
{
// keep always the latest element in the stack to prevent subtle errors,
// e.g., the addresses of all variables in a lambda expression calling
// become() suddenly are invalid if we would pop the behavior!
if
(
vec
.
size
()
<
2
)
{
vec
.
push_back
(
StackElement
(
bhvr
,
has_ownership
));
vec
.
push_back
(
std
::
move
(
bhvr
));
}
else
{
vec
[
0
]
=
std
::
move
(
vec
[
1
]);
vec
[
1
]
=
StackElement
(
bhvr
,
has_ownership
);
vec
[
1
]
=
std
::
move
(
bhvr
);
}
}
...
...
@@ -73,13 +73,17 @@ void event_based_actor::do_become(behavior* bhvr)
void
event_based_actor
::
do_become
(
invoke_rules
*
bhvr
,
bool
has_ownership
)
{
reset_timeout
();
push_to
<
stack_element
>
(
m_loop_stack
,
bhvr
,
has_ownership
);
stack_element
::
left_type
ptr
(
bhvr
);
if
(
!
has_ownership
)
ptr
.
get_deleter
().
disable
();
push_to
<
stack_element
>
(
m_loop_stack
,
std
::
move
(
ptr
));
}
void
event_based_actor
::
do_become
(
timed_invoke_rules
*
bhvr
,
bool
has_ownership
)
{
request_timeout
(
bhvr
->
timeout
());
push_to
<
stack_element
>
(
m_loop_stack
,
bhvr
,
has_ownership
);
stack_element
::
right_type
ptr
(
bhvr
);
if
(
!
has_ownership
)
ptr
.
get_deleter
().
disable
();
push_to
<
stack_element
>
(
m_loop_stack
,
std
::
move
(
ptr
));
}
}
// namespace cppa
src/stacked_event_based_actor.cpp
View file @
0cf245c8
...
...
@@ -39,21 +39,28 @@ void stacked_event_based_actor::become_void()
void
stacked_event_based_actor
::
unbecome
()
{
if
(
!
m_loop_stack
.
empty
())
m_loop_stack
.
pop_back
();
if
(
!
m_loop_stack
.
empty
())
{
m_loop_stack
.
pop_back
();
}
}
void
stacked_event_based_actor
::
do_become
(
invoke_rules
*
behavior
,
bool
has_ownership
)
{
reset_timeout
();
m_loop_stack
.
push_back
(
stack_element
(
behavior
,
has_ownership
));
stack_element
::
left_type
ptr
(
behavior
);
if
(
!
has_ownership
)
ptr
.
get_deleter
().
disable
();
m_loop_stack
.
push_back
(
std
::
move
(
ptr
));
}
void
stacked_event_based_actor
::
do_become
(
timed_invoke_rules
*
behavior
,
bool
has_ownership
)
{
request_timeout
(
behavior
->
timeout
());
m_loop_stack
.
push_back
(
stack_element
(
behavior
,
has_ownership
));
stack_element
::
right_type
ptr
(
behavior
);
if
(
!
has_ownership
)
ptr
.
get_deleter
().
disable
();
m_loop_stack
.
push_back
(
std
::
move
(
ptr
));
}
}
// namespace cppa
unit_testing/test__atom.cpp
View file @
0cf245c8
...
...
@@ -30,9 +30,12 @@ size_t test__atom()
{
bool
matched_pattern
[
3
]
=
{
false
,
false
,
false
};
CPPA_TEST
(
test__atom
);
// check if there are leading bits that distinguish "zzz" and "000 "
CPPA_CHECK_NOT_EQUAL
(
atom
(
"zzz"
),
atom
(
"000 "
));
// 'illegal' characters are mapped to whitespaces
CPPA_CHECK_EQUAL
(
atom
(
" "
),
atom
(
"@!?"
));
CPPA_CHECK_NOT_EQUAL
(
atom
(
"abc"
),
atom
(
" abc"
));
// check to_string impl.
CPPA_CHECK_EQUAL
(
to_string
(
s_foo
),
"FooBar"
);
self
<<
make_tuple
(
atom
(
"foo"
),
static_cast
<
std
::
uint32_t
>
(
42
))
<<
make_tuple
(
atom
(
":Attach"
),
atom
(
":Baz"
),
"cstring"
)
...
...
unit_testing/test__intrusive_ptr.cpp
View file @
0cf245c8
...
...
@@ -48,6 +48,8 @@ class0_ptr get_test_ptr()
size_t
test__intrusive_ptr
()
{
// this test dosn't test thread-safety of intrusive_ptr
// however, it is thread safe since it uses atomic operations only
CPPA_TEST
(
test__intrusive_ptr
);
...
...
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