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
e3a18cba
Commit
e3a18cba
authored
Jan 24, 2012
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
minor bugfix and documentation
parent
828669b0
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
459 additions
and
408 deletions
+459
-408
Makefile.am
Makefile.am
+1
-1
cppa.files
cppa.files
+2
-1
cppa/abstract_actor.hpp
cppa/abstract_actor.hpp
+6
-106
cppa/abstract_event_based_actor.hpp
cppa/abstract_event_based_actor.hpp
+8
-13
cppa/any_tuple.hpp
cppa/any_tuple.hpp
+0
-5
cppa/any_tuple_view.hpp
cppa/any_tuple_view.hpp
+9
-5
cppa/behavior.hpp
cppa/behavior.hpp
+5
-2
cppa/config.hpp
cppa/config.hpp
+12
-0
cppa/cppa.hpp
cppa/cppa.hpp
+10
-3
cppa/detail/abstract_scheduled_actor.hpp
cppa/detail/abstract_scheduled_actor.hpp
+2
-4
cppa/detail/converted_thread_context.hpp
cppa/detail/converted_thread_context.hpp
+2
-3
cppa/detail/group_manager.hpp
cppa/detail/group_manager.hpp
+2
-0
cppa/detail/implicit_conversions.hpp
cppa/detail/implicit_conversions.hpp
+2
-3
cppa/detail/yielding_actor.hpp
cppa/detail/yielding_actor.hpp
+2
-2
cppa/either.hpp
cppa/either.hpp
+128
-160
cppa/group.hpp
cppa/group.hpp
+9
-0
cppa/option.hpp
cppa/option.hpp
+155
-46
cppa/tuple_view.hpp
cppa/tuple_view.hpp
+12
-10
gen_server/Makefile
gen_server/Makefile
+2
-2
gen_server/sequential_send.cpp
gen_server/sequential_send.cpp
+3
-2
src/abstract_event_based_actor.cpp
src/abstract_event_based_actor.cpp
+4
-4
src/abstract_scheduled_actor.cpp
src/abstract_scheduled_actor.cpp
+11
-0
src/event_based_actor.cpp
src/event_based_actor.cpp
+24
-5
src/group.cpp
src/group.cpp
+15
-10
src/group_manager.cpp
src/group_manager.cpp
+27
-15
src/scheduler.cpp
src/scheduler.cpp
+2
-2
src/stacked_event_based_actor.cpp
src/stacked_event_based_actor.cpp
+4
-4
No files found.
Makefile.am
View file @
e3a18cba
...
...
@@ -88,6 +88,7 @@ nobase_library_include_HEADERS = \
cppa/cow_ptr.hpp
\
cppa/cppa.hpp
\
cppa/deserializer.hpp
\
cppa/either.hpp
\
cppa/event_based_actor.hpp
\
cppa/event_based_actor_base.hpp
\
cppa/abstract_event_based_actor.hpp
\
...
...
@@ -179,7 +180,6 @@ nobase_library_include_HEADERS = \
cppa/util/disable_if.hpp
\
cppa/util/disjunction.hpp
\
cppa/util/duration.hpp
\
cppa/util/either.hpp
\
cppa/util/element_at.hpp
\
cppa/util/enable_if.hpp
\
cppa/util/fiber.hpp
\
...
...
cppa.files
View file @
e3a18cba
...
...
@@ -215,7 +215,7 @@ examples/hello_world_example.cpp
examples/math_actor_example.cpp
cppa/detail/yielding_actor.hpp
src/yielding_actor.cpp
cppa/
util/
either.hpp
cppa/either.hpp
cppa/abstract_event_based_actor.hpp
src/abstract_event_based_actor.cpp
cppa/event_based_actor.hpp
...
...
@@ -261,3 +261,4 @@ benchmarks/theron_actor_creation.cpp
benchmarks/theron_mixed_case.cpp
cppa/util/static_foreach.hpp
cppa/type_value_pair.hpp
examples/dining_hakkers.cpp
cppa/abstract_actor.hpp
View file @
e3a18cba
...
...
@@ -71,113 +71,32 @@ class abstract_actor : public Base
public:
class
queue_node_ptr
;
struct
queue_node_deallocator
;
struct
queue_node
{
friend
class
abstract_actor
;
friend
class
queue_node_ptr
;
friend
struct
queue_node_deallocator
;
queue_node
*
next
;
std
::
atomic
<
queue_node
*>*
owner
;
actor_ptr
sender
;
any_tuple
msg
;
private:
// you have to be a friend to create or destroy a node
inline
~
queue_node
()
{
}
queue_node
()
:
next
(
nullptr
),
owner
(
nullptr
)
{
}
queue_node
()
:
next
(
nullptr
)
{
}
queue_node
(
actor
*
from
,
any_tuple
&&
content
)
:
next
(
nullptr
),
owner
(
nullptr
),
sender
(
from
),
msg
(
std
::
move
(
content
))
:
next
(
nullptr
),
sender
(
from
),
msg
(
std
::
move
(
content
))
{
}
queue_node
(
actor
*
from
,
any_tuple
const
&
content
)
:
next
(
nullptr
),
owner
(
nullptr
),
sender
(
from
),
msg
(
content
)
{
}
};
struct
queue_node_deallocator
{
inline
void
operator
()(
queue_node
*
ptr
)
:
next
(
nullptr
),
sender
(
from
),
msg
(
content
)
{
if
(
ptr
)
{
if
(
ptr
->
owner
!=
nullptr
)
{
ptr
->
sender
.
reset
();
ptr
->
msg
=
any_tuple
();
auto
owner
=
ptr
->
owner
;
ptr
->
next
=
owner
->
load
();
for
(;;)
{
if
(
owner
->
compare_exchange_weak
(
ptr
->
next
,
ptr
))
return
;
}
}
else
{
delete
ptr
;
}
}
}
};
class
queue_node_ptr
{
queue_node
*
m_ptr
;
queue_node_deallocator
d
;
queue_node_ptr
(
queue_node_ptr
const
&
)
=
delete
;
queue_node_ptr
&
operator
=
(
queue_node_ptr
const
&
)
=
delete
;
public:
inline
queue_node_ptr
(
queue_node
*
ptr
=
nullptr
)
:
m_ptr
(
ptr
)
{
}
inline
queue_node_ptr
(
queue_node_ptr
&&
other
)
:
m_ptr
(
other
.
m_ptr
)
{
other
.
m_ptr
=
nullptr
;
}
inline
~
queue_node_ptr
()
{
d
(
m_ptr
);
}
inline
queue_node
*
operator
->
()
{
return
m_ptr
;
}
inline
queue_node
*
release
()
{
auto
result
=
m_ptr
;
m_ptr
=
nullptr
;
return
result
;
}
inline
void
reset
(
queue_node
*
ptr
=
nullptr
)
{
d
(
m_ptr
);
m_ptr
=
ptr
;
}
inline
queue_node_ptr
&
operator
=
(
queue_node_ptr
&&
other
)
{
reset
(
other
.
release
());
return
*
this
;
}
inline
operator
bool
()
const
{
return
m_ptr
!=
nullptr
;
}
};
typedef
std
::
unique_ptr
<
queue_node
>
queue_node_ptr
;
protected:
queue_node
m_prefetched_nodes
[
10
];
std
::
atomic
<
queue_node
*>
m_prefetched
;
util
::
single_reader_queue
<
queue_node
,
queue_node_deallocator
>
m_mailbox
;
util
::
single_reader_queue
<
queue_node
>
m_mailbox
;
private:
...
...
@@ -220,20 +139,8 @@ class abstract_actor : public Base
protected:
template
<
typename
T
>
queue_node
*
fetch_node
(
actor
*
sender
,
T
&&
msg
)
inline
queue_node
*
fetch_node
(
actor
*
sender
,
T
&&
msg
)
{
queue_node
*
result
=
m_prefetched
.
load
();
while
(
result
)
{
queue_node
*
next
=
result
->
next
;
if
(
m_prefetched
.
compare_exchange_weak
(
result
,
next
))
{
result
->
next
=
nullptr
;
result
->
sender
.
reset
(
sender
);
result
->
msg
=
std
::
forward
<
T
>
(
msg
);
return
result
;
}
}
return
new
queue_node
(
sender
,
std
::
forward
<
T
>
(
msg
));
}
...
...
@@ -241,13 +148,6 @@ class abstract_actor : public Base
abstract_actor
(
Args
&&
...
args
)
:
Base
(
std
::
forward
<
Args
>
(
args
)...)
,
m_exit_reason
(
exit_reason
::
not_exited
)
{
for
(
int
i
=
0
;
i
<
9
;
++
i
)
{
m_prefetched_nodes
[
i
].
next
=
&
(
m_prefetched_nodes
[
i
+
1
]);
m_prefetched_nodes
[
i
].
owner
=
&
m_prefetched
;
}
m_prefetched_nodes
[
9
].
owner
=
&
m_prefetched
;
m_prefetched
.
store
(
m_prefetched_nodes
);
}
void
cleanup
(
std
::
uint32_t
reason
)
...
...
cppa/abstract_event_based_actor.hpp
View file @
e3a18cba
...
...
@@ -35,9 +35,10 @@
#include <memory>
#include <vector>
#include "cppa/config.hpp"
#include "cppa/either.hpp"
#include "cppa/pattern.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/util/either.hpp"
#include "cppa/detail/abstract_scheduled_actor.hpp"
namespace
cppa
{
...
...
@@ -101,7 +102,7 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
stack_element
(
stack_element
const
&
)
=
delete
;
stack_element
&
operator
=
(
stack_element
const
&
)
=
delete
;
util
::
either
<
invoke_rules
*
,
timed_invoke_rules
*>
m_ptr
;
either
<
invoke_rules
*
,
timed_invoke_rules
*>
m_ptr
;
bool
m_ownership
;
inline
stack_element
(
invoke_rules
*
ptr
,
bool
take_ownership
)
...
...
@@ -142,30 +143,24 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
}
}
}
inline
bool
is_left
()
{
return
m_ptr
.
is_left
();
}
inline
bool
is_right
()
{
return
m_ptr
.
is_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
();
if
(
ptr
==
nullptr
)
throw
std
::
runtime_error
(
"nullptr"
);
CPPA_REQUIRE
(
ptr
!=
nullptr
);
return
*
(
ptr
);
}
inline
timed_invoke_rules
&
right
()
{
auto
ptr
=
m_ptr
.
right
();
if
(
ptr
==
nullptr
)
throw
std
::
runtime_error
(
"nullptr"
);
CPPA_REQUIRE
(
ptr
!=
nullptr
);
return
*
(
ptr
);
}
};
queue_node_buffer
m_buffer
;
std
::
stack
<
stack_element
,
std
::
vector
<
stack_element
>
>
m_loop_stack
;
std
::
vector
<
stack_element
>
m_loop_stack
;
// provoke compiler errors for usage of receive() and related functions
...
...
cppa/any_tuple.hpp
View file @
e3a18cba
...
...
@@ -52,14 +52,11 @@ class any_tuple
/**
* @brief Creates an empty tuple.
* @post <tt>empty() == true</tt>
*/
any_tuple
();
/**
* @brief Creates a tuple from @p t.
* @param t A typed tuple representation.
* @post <tt>empty() == false</tt>
*/
template
<
typename
...
Args
>
any_tuple
(
tuple
<
Args
...
>
const
&
t
)
:
m_vals
(
t
.
vals
())
{
}
...
...
@@ -78,13 +75,11 @@ class any_tuple
/**
* @brief Move assignment.
* @returns <tt>*this</tt>.
*/
any_tuple
&
operator
=
(
any_tuple
&&
);
/**
* @brief Copy assignment.
* @returns <tt>*this</tt>.
*/
any_tuple
&
operator
=
(
any_tuple
const
&
)
=
default
;
...
...
cppa/any_tuple_view.hpp
View file @
e3a18cba
...
...
@@ -52,7 +52,7 @@ namespace cppa {
class
any_tuple_view
{
typedef
std
::
vector
<
std
::
pair
<
uniform_type_info
const
*
,
void
const
*>
>
typedef
std
::
vector
<
std
::
pair
<
uniform_type_info
const
*
,
void
*>
>
vector_type
;
vector_type
m_values
;
...
...
@@ -86,6 +86,7 @@ class any_tuple_view
}
}
/*
template<typename... T>
explicit any_tuple_view(tuple<T...> const& tup)
{
...
...
@@ -94,6 +95,7 @@ class any_tuple_view
m_values.push_back(std::make_pair(tup.type_at(i), tup.at(i)));
}
}
*/
template
<
typename
...
T
>
any_tuple_view
(
tuple_view
<
T
...
>
const
&
tup
)
...
...
@@ -113,16 +115,16 @@ class any_tuple_view
}
template
<
typename
T
>
any_tuple_view
(
std
::
set
<
T
>
const
&
vec
)
{
from_list
(
vec
);
}
any_tuple_view
(
std
::
set
<
T
>&
vec
)
{
from_list
(
vec
);
}
template
<
typename
T
>
any_tuple_view
(
std
::
list
<
T
>
const
&
vec
)
{
from_list
(
vec
);
}
any_tuple_view
(
std
::
list
<
T
>&
vec
)
{
from_list
(
vec
);
}
template
<
typename
T
>
any_tuple_view
(
std
::
vector
<
T
>
const
&
vec
)
{
from_list
(
vec
);
}
any_tuple_view
(
std
::
vector
<
T
>&
vec
)
{
from_list
(
vec
);
}
template
<
typename
T
>
any_tuple_view
(
T
const
&
val
,
any_tuple_view
(
T
&
val
,
typename
util
::
enable_if
<
util
::
is_primitive
<
T
>
>::
type
*
=
0
)
{
auto
&
arr
=
detail
::
static_types_array
<
T
>::
arr
;
...
...
@@ -135,6 +137,8 @@ class any_tuple_view
inline
void
const
*
at
(
size_t
p
)
const
{
return
m_values
[
p
].
second
;
}
void
*
mutable_at
(
size_t
p
)
{
return
m_values
[
p
].
second
;
}
inline
uniform_type_info
const
*
type_at
(
size_t
p
)
const
{
return
m_values
[
p
].
first
;
...
...
cppa/behavior.hpp
View file @
e3a18cba
...
...
@@ -31,12 +31,15 @@
#ifndef BEHAVIOR_HPP
#define BEHAVIOR_HPP
#include "cppa/
util/
either.hpp"
#include "cppa/either.hpp"
#include "cppa/invoke_rules.hpp"
namespace
cppa
{
typedef
util
::
either
<
invoke_rules
,
timed_invoke_rules
>
behavior
;
/**
* @brief
*/
typedef
either
<
invoke_rules
,
timed_invoke_rules
>
behavior
;
}
// namespace cppa
...
...
cppa/config.hpp
View file @
e3a18cba
...
...
@@ -66,4 +66,16 @@
# error Plattform and/or compiler not supportet
#endif
#ifdef CPPA_DEBUG
#include <cstdlib>
#define CPPA_REQUIRE__(stmt, file, line) \
printf("%s:%u: requirement failed '%s'\n", file, line, stmt); abort()
#define CPPA_REQUIRE(stmt) \
if ((stmt) == false) { \
CPPA_REQUIRE__(#stmt, __FILE__, __LINE__); \
}((void) 0)
#else // CPPA_DEBUG
#define CPPA_REQUIRE(unused) ((void) 0)
#endif // CPPA_DEBUG
#endif // CPPA_CONFIG_HPP
cppa/cppa.hpp
View file @
e3a18cba
...
...
@@ -524,12 +524,19 @@ void send(intrusive_ptr<C>&& whom, Arg0 const& arg0, Args const&... args)
if
(
tmp
)
tmp
->
enqueue
(
self
,
make_tuple
(
arg0
,
args
...));
}
// matches "send(this, ...)" in event-based actors
template
<
typename
Arg0
,
typename
...
Args
>
void
send
(
local_actor
*
whom
,
Arg0
const
&
arg0
,
Args
const
&
...
args
)
{
whom
->
enqueue
(
whom
,
make_tuple
(
arg0
,
args
...));
}
// matches send(self, ...);
template
<
typename
Arg0
,
typename
...
Args
>
void
send
(
self_type
const
&
,
Arg0
const
&
arg0
,
Args
const
&
...
args
)
inline
void
send
(
self_type
const
&
,
Arg0
const
&
arg0
,
Args
const
&
...
args
)
{
local_actor
*
s
=
self
;
s
->
enqueue
(
s
,
make_tuple
(
arg0
,
args
...));
send
(
static_cast
<
local_actor
*>
(
self
),
arg0
,
args
...);
}
template
<
class
C
>
...
...
cppa/detail/abstract_scheduled_actor.hpp
View file @
e3a18cba
...
...
@@ -45,9 +45,7 @@ namespace cppa { namespace detail {
class
task_scheduler
;
/**
* @brief A spawned, scheduled Actor.
*/
// A spawned, scheduled Actor.
class
abstract_scheduled_actor
:
public
abstract_actor
<
local_actor
>
{
...
...
@@ -65,7 +63,7 @@ class abstract_scheduled_actor : public abstract_actor<local_actor>
typedef
abstract_actor
super
;
typedef
super
::
queue_node
queue_node
;
typedef
util
::
singly_linked_list
<
queue_node
,
super
::
queue_node_deallocator
>
typedef
util
::
singly_linked_list
<
queue_node
>
queue_node_buffer
;
enum
dq_result
...
...
cppa/detail/converted_thread_context.hpp
View file @
e3a18cba
...
...
@@ -43,12 +43,11 @@
#include <cstdint>
#include "cppa/atom.hpp"
#include "cppa/either.hpp"
#include "cppa/pattern.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/abstract_actor.hpp"
#include "cppa/util/either.hpp"
#include "cppa/util/singly_linked_list.hpp"
namespace
cppa
{
namespace
detail
{
...
...
@@ -87,7 +86,7 @@ class converted_thread_context : public abstract_actor<local_actor>
private:
typedef
util
::
singly_linked_list
<
queue_node
,
super
::
queue_node_deallocator
>
typedef
util
::
singly_linked_list
<
queue_node
>
queue_node_buffer
;
enum
throw_on_exit_result
...
...
cppa/detail/group_manager.hpp
View file @
e3a18cba
...
...
@@ -49,6 +49,8 @@ class group_manager
intrusive_ptr
<
group
>
get
(
std
::
string
const
&
module_name
,
std
::
string
const
&
group_identifier
);
intrusive_ptr
<
group
>
anonymous
();
void
add_module
(
group
::
module
*
);
private:
...
...
cppa/detail/implicit_conversions.hpp
View file @
e3a18cba
...
...
@@ -67,9 +67,8 @@ struct implicit_conversions
subtype3
;
typedef
typename
util
::
replace_type
<
subtype3
,
actor_ptr
,
std
::
is_same
<
actor
*
,
T
>
,
std
::
is_same
<
local_actor
*
,
T
>
,
std
::
is_same
<
self_type
,
T
>
,
std
::
is_convertible
<
T
,
actor
*>
,
std
::
is_convertible
<
T
,
local_actor
*>
,
std
::
is_same
<
self_type
,
T
>>::
type
type
;
...
...
cppa/detail/yielding_actor.hpp
View file @
e3a18cba
...
...
@@ -37,13 +37,13 @@
#include <stack>
#include "cppa/either.hpp"
#include "cppa/pattern.hpp"
#include "cppa/detail/delegate.hpp"
#include "cppa/detail/abstract_scheduled_actor.hpp"
#include "cppa/detail/yield_interface.hpp"
#include "cppa/detail/abstract_scheduled_actor.hpp"
#include "cppa/util/either.hpp"
#include "cppa/util/singly_linked_list.hpp"
namespace
cppa
{
namespace
detail
{
...
...
cppa/either.hpp
View file @
e3a18cba
...
...
@@ -32,283 +32,251 @@
#define EITHER_HPP
#include <new>
#include <
stdexcept
>
#include <
utility
>
#include <type_traits>
#include "cppa/config.hpp"
namespace
cppa
{
namespace
util
{
namespace
cppa
{
/**
* @brief Represents either a @p Left or a @p Right.
*/
template
<
class
Left
,
class
Right
>
class
either
{
static_assert
(
std
::
is_same
<
Left
,
Right
>::
value
==
false
,
"Left == Right"
);
union
{
Left
m_left
;
Right
m_right
;
};
bool
m_is_left
;
void
check_flag
(
bool
flag
,
char
const
*
side
)
const
{
if
(
m_is_left
!=
flag
)
{
std
::
string
err
=
"not a "
;
err
+=
side
;
throw
std
::
runtime_error
(
err
);
}
}
void
destroy
()
{
if
(
m_is_left
)
{
m_left
.
~
Left
();
}
else
{
m_right
.
~
Right
();
}
}
template
<
typename
L
>
void
cr_left
(
L
&&
value
)
{
new
(
&
m_left
)
Left
(
std
::
forward
<
L
>
(
value
));
}
template
<
typename
R
>
void
cr_right
(
R
&&
value
)
{
new
(
&
m_right
)
Right
(
std
::
forward
<
R
>
(
value
));
}
static_assert
(
std
::
is_convertible
<
Left
,
Right
>::
value
==
false
&&
std
::
is_convertible
<
Right
,
Left
>::
value
==
false
,
"Left is not allowed to be convertible to Right"
);
public:
// default constructor creates a left
either
()
:
m_is_left
(
true
)
{
new
(
&
m_left
)
Left
();
}
either
(
Left
const
&
value
)
:
m_is_left
(
true
)
{
cr_left
(
value
);
}
either
(
Left
&&
value
)
:
m_is_left
(
true
)
{
cr_left
(
std
::
move
(
value
));
}
either
(
Right
const
&
value
)
:
m_is_left
(
false
)
{
cr_right
(
value
);
}
either
(
Right
&&
value
)
:
m_is_left
(
false
)
{
cr_right
(
std
::
move
(
value
));
}
/**
* @brief Default constructor, creates a @p Left.
*/
either
()
:
m_is_left
(
true
)
{
new
(
&
m_left
)
Left
();
}
/**
* @brief Creates a @p Left from @p value.
*/
either
(
Left
const
&
value
)
:
m_is_left
(
true
)
{
cr_left
(
value
);
}
/**
* @brief Creates a @p Left from @p value.
*/
either
(
Left
&&
value
)
:
m_is_left
(
true
)
{
cr_left
(
std
::
move
(
value
));
}
/**
* @brief Creates a @p Right from @p value.
*/
either
(
Right
const
&
value
)
:
m_is_left
(
false
)
{
cr_right
(
value
);
}
/**
* @brief Creates a @p Right from @p value.
*/
either
(
Right
&&
value
)
:
m_is_left
(
false
)
{
cr_right
(
std
::
move
(
value
));
}
/**
* @brief Copy constructor.
*/
either
(
either
const
&
other
)
:
m_is_left
(
other
.
m_is_left
)
{
if
(
other
.
m_is_left
)
{
cr_left
(
other
.
m_left
);
}
else
{
cr_right
(
other
.
m_right
);
}
if
(
other
.
m_is_left
)
cr_left
(
other
.
m_left
);
else
cr_right
(
other
.
m_right
);
}
/**
* @brief Move constructor.
*/
either
(
either
&&
other
)
:
m_is_left
(
other
.
m_is_left
)
{
if
(
other
.
m_is_left
)
{
cr_left
(
std
::
move
(
other
.
m_left
));
}
else
{
cr_right
(
std
::
move
(
other
.
m_right
));
}
if
(
other
.
m_is_left
)
cr_left
(
std
::
move
(
other
.
m_left
));
else
cr_right
(
std
::
move
(
other
.
m_right
));
}
~
either
()
{
destroy
();
}
~
either
()
{
destroy
();
}
/**
* @brief Copy assignment.
*/
either
&
operator
=
(
either
const
&
other
)
{
if
(
m_is_left
==
other
.
m_is_left
)
{
if
(
m_is_left
)
{
m_left
=
other
.
m_left
;
}
else
{
m_right
=
other
.
m_right
;
}
if
(
m_is_left
)
m_left
=
other
.
m_left
;
else
m_right
=
other
.
m_right
;
}
else
{
destroy
();
m_is_left
=
other
.
m_is_left
;
if
(
other
.
m_is_left
)
{
cr_left
(
other
.
m_left
);
}
else
{
cr_right
(
other
.
m_right
);
}
if
(
other
.
m_is_left
)
cr_left
(
other
.
m_left
);
else
cr_right
(
other
.
m_right
);
}
return
*
this
;
}
/**
* @brief Move assignment.
*/
either
&
operator
=
(
either
&&
other
)
{
if
(
m_is_left
==
other
.
m_is_left
)
{
if
(
m_is_left
)
{
m_left
=
std
::
move
(
other
.
m_left
);
}
else
{
m_right
=
std
::
move
(
other
.
m_right
);
}
if
(
m_is_left
)
m_left
=
std
::
move
(
other
.
m_left
);
else
m_right
=
std
::
move
(
other
.
m_right
);
}
else
{
destroy
();
m_is_left
=
other
.
m_is_left
;
if
(
other
.
m_is_left
)
{
cr_left
(
std
::
move
(
other
.
m_left
));
}
else
{
cr_right
(
std
::
move
(
other
.
m_right
));
}
if
(
other
.
m_is_left
)
cr_left
(
std
::
move
(
other
.
m_left
));
else
cr_right
(
std
::
move
(
other
.
m_right
));
}
return
*
this
;
}
inline
bool
is_left
()
const
{
return
m_is_left
;
}
/**
* @brief Returns @p true if this is a @p Left; otherwise @p false.
*/
inline
bool
is_left
()
const
{
return
m_is_left
;
}
inline
bool
is_right
()
const
{
return
!
m_is_left
;
}
/**
* @brief Returns @p true if this is a @p Left; otherwise @p false.
*/
inline
bool
is_right
()
const
{
return
!
m_is_left
;
}
Left
&
left
()
/**
* @brief Returns this @p either as a @p Left.
*/
inline
Left
&
left
()
{
//check_flag(true, "left"
);
CPPA_REQUIRE
(
m_is_left
);
return
m_left
;
}
Left
const
&
left
()
const
/**
* @brief Returns this @p either as a @p Left.
*/
inline
Left
const
&
left
()
const
{
//check_flag(true, "left"
);
CPPA_REQUIRE
(
m_is_left
);
return
m_left
;
}
Right
&
right
()
/**
* @brief Returns this @p either as a @p Right.
*/
inline
Right
&
right
()
{
//check_flag(false, "right"
);
CPPA_REQUIRE
(
!
m_is_left
);
return
m_right
;
}
Right
const
&
right
()
const
/**
* @brief Returns this @p either as a @p Right.
*/
inline
Right
const
&
right
()
const
{
//check_flag(false, "right"
);
CPPA_REQUIRE
(
!
m_is_left
);
return
m_right
;
}
private:
bool
m_is_left
;
union
{
Left
m_left
;
Right
m_right
;
};
void
destroy
()
{
if
(
m_is_left
)
m_left
.
~
Left
();
else
m_right
.
~
Right
();
}
template
<
typename
L
>
void
cr_left
(
L
&&
value
)
{
new
(
&
m_left
)
Left
(
std
::
forward
<
L
>
(
value
));
}
template
<
typename
R
>
void
cr_right
(
R
&&
value
)
{
new
(
&
m_right
)
Right
(
std
::
forward
<
R
>
(
value
));
}
};
template
<
typename
Left
,
typename
Right
>
bool
operator
==
(
const
either
<
Left
,
Right
>&
lhs
,
const
either
<
Left
,
Right
>&
rhs
)
bool
operator
==
(
either
<
Left
,
Right
>
const
&
lhs
,
either
<
Left
,
Right
>
const
&
rhs
)
{
if
(
lhs
.
is_left
()
==
rhs
.
is_left
())
{
if
(
lhs
.
is_left
())
{
return
lhs
.
left
()
==
rhs
.
left
();
}
else
{
return
lhs
.
right
()
==
rhs
.
right
();
}
if
(
lhs
.
is_left
())
return
lhs
.
left
()
==
rhs
.
left
();
else
return
lhs
.
right
()
==
rhs
.
right
();
}
return
false
;
}
template
<
typename
Left
,
typename
Right
>
bool
operator
==
(
const
either
<
Left
,
Right
>
&
lhs
,
Left
const
&
rhs
)
bool
operator
==
(
either
<
Left
,
Right
>
const
&
lhs
,
Left
const
&
rhs
)
{
return
lhs
.
is_left
()
&&
lhs
.
left
()
==
rhs
;
}
template
<
typename
Left
,
typename
Right
>
bool
operator
==
(
Left
const
&
lhs
,
const
either
<
Left
,
Right
>
&
rhs
)
bool
operator
==
(
Left
const
&
lhs
,
either
<
Left
,
Right
>
const
&
rhs
)
{
return
rhs
==
lhs
;
}
template
<
typename
Left
,
typename
Right
>
bool
operator
==
(
const
either
<
Left
,
Right
>
&
lhs
,
Right
const
&
rhs
)
bool
operator
==
(
either
<
Left
,
Right
>
const
&
lhs
,
Right
const
&
rhs
)
{
return
lhs
.
is_right
()
&&
lhs
.
right
()
==
rhs
;
}
template
<
typename
Left
,
typename
Right
>
bool
operator
==
(
Right
const
&
lhs
,
const
either
<
Left
,
Right
>
&
rhs
)
bool
operator
==
(
Right
const
&
lhs
,
either
<
Left
,
Right
>
const
&
rhs
)
{
return
rhs
==
lhs
;
}
template
<
typename
Left
,
typename
Right
>
bool
operator
!=
(
const
either
<
Left
,
Right
>&
lhs
,
const
either
<
Left
,
Right
>&
rhs
)
bool
operator
!=
(
either
<
Left
,
Right
>
const
&
lhs
,
either
<
Left
,
Right
>
const
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
template
<
typename
Left
,
typename
Right
>
bool
operator
!=
(
const
either
<
Left
,
Right
>
&
lhs
,
Left
const
&
rhs
)
bool
operator
!=
(
either
<
Left
,
Right
>
const
&
lhs
,
Left
const
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
template
<
typename
Left
,
typename
Right
>
bool
operator
!=
(
Left
const
&
lhs
,
const
either
<
Left
,
Right
>
&
rhs
)
bool
operator
!=
(
Left
const
&
lhs
,
either
<
Left
,
Right
>
const
&
rhs
)
{
return
!
(
rhs
==
lhs
);
}
template
<
typename
Left
,
typename
Right
>
bool
operator
!=
(
const
either
<
Left
,
Right
>
&
lhs
,
Right
const
&
rhs
)
bool
operator
!=
(
either
<
Left
,
Right
>
const
&
lhs
,
Right
const
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
template
<
typename
Left
,
typename
Right
>
bool
operator
!=
(
Right
const
&
lhs
,
const
either
<
Left
,
Right
>
&
rhs
)
bool
operator
!=
(
Right
const
&
lhs
,
either
<
Left
,
Right
>
const
&
rhs
)
{
return
!
(
rhs
==
lhs
);
}
}
}
// namespace cppa::util
}
// namespace cppa
#endif // EITHER_HPP
cppa/group.hpp
View file @
e3a18cba
...
...
@@ -151,6 +151,15 @@ class group : public channel
static
intrusive_ptr
<
group
>
get
(
std
::
string
const
&
module_name
,
std
::
string
const
&
group_identifier
);
/**
* @brief Returns an anonymous group.
*
* Each calls to this member function returns a new instances
* of an anonymous group. Anonymous groups can be used whenever
* a set of actors wants to communicate over an exclusive channel.
*/
static
intrusive_ptr
<
group
>
anonymous
();
/**
* @brief Add a new group module to the libcppa group management.
* @threadsafe
...
...
cppa/option.hpp
View file @
e3a18cba
...
...
@@ -31,60 +31,67 @@
#ifndef OPTION_HPP
#define OPTION_HPP
#include <new>
#include <utility>
#include "cppa/config.hpp"
namespace
cppa
{
/**
* @brief Represents an optional value of @p T.
*/
template
<
typename
T
>
class
option
{
union
{
T
m_value
;
};
bool
m_valid
;
void
destroy
()
{
if
(
m_valid
)
m_value
.
~
T
();
}
template
<
typename
V
>
void
cr
(
V
&&
value
)
{
m_valid
=
true
;
new
(
&
m_value
)
T
(
std
::
forward
<
V
>
(
value
));
}
public:
/**
* @brief Typdef for @p T.
*/
typedef
T
value_type
;
/**
* @brief Default constructor.
* @post <tt>valid() == false</tt>
*/
option
()
:
m_valid
(
false
)
{
}
template
<
typename
V
>
option
(
V
&&
value
)
{
cr
(
std
::
forward
<
V
>
(
value
));
}
/**
* @brief Creates an @p option from @p value.
* @post <tt>valid() == true</tt>
*/
option
(
T
&&
value
)
{
cr
(
std
::
move
(
value
));
}
/**
* @brief Creates an @p option from @p value.
* @post <tt>valid() == true</tt>
*/
option
(
T
const
&
value
)
{
cr
(
value
);
}
/**
* @brief Copy constructor.
*/
option
(
option
const
&
other
)
{
if
(
other
.
m_valid
)
cr
(
other
.
m_value
);
else
m_valid
=
false
;
}
/**
* @brief Move constructor.
*/
option
(
option
&&
other
)
{
if
(
other
.
m_valid
)
cr
(
std
::
move
(
other
.
m_value
));
else
m_valid
=
false
;
}
~
option
()
{
destroy
();
}
~
option
()
{
destroy
();
}
/**
* @brief Copy assignment.
*/
option
&
operator
=
(
option
const
&
other
)
{
if
(
m_valid
)
...
...
@@ -99,16 +106,16 @@ class option
m_valid
=
false
;
}
}
else
else
if
(
other
.
m_valid
)
{
if
(
other
.
m_valid
)
{
cr
(
other
.
m_value
);
}
cr
(
other
.
m_value
);
}
return
*
this
;
}
/**
* @brief Move assignment.
*/
option
&
operator
=
(
option
&&
other
)
{
if
(
m_valid
)
...
...
@@ -123,16 +130,16 @@ class option
m_valid
=
false
;
}
}
else
else
if
(
other
.
m_valid
)
{
if
(
other
.
m_valid
)
{
cr
(
std
::
move
(
other
.
m_value
));
}
cr
(
std
::
move
(
other
.
m_value
));
}
return
*
this
;
}
/**
* @brief Copy assignment.
*/
option
&
operator
=
(
T
const
&
value
)
{
if
(
m_valid
)
m_value
=
value
;
...
...
@@ -140,6 +147,9 @@ class option
return
*
this
;
}
/**
* @brief Move assignment.
*/
option
&
operator
=
(
T
&
value
)
{
if
(
m_valid
)
m_value
=
std
::
move
(
value
);
...
...
@@ -147,33 +157,132 @@ class option
return
*
this
;
}
/**
* @brief Returns @p true if this @p option has a valid value;
* otherwise @p false.
*/
inline
bool
valid
()
const
{
return
m_valid
;
}
/**
* @copydoc valid()
*/
inline
explicit
operator
bool
()
const
{
return
m_valid
;
}
/**
* @brief Returns @p false if this @p option has a valid value;
* otherwise @p true.
*/
inline
bool
operator
!
()
const
{
return
!
m_valid
;
}
inline
T
&
operator
*
()
{
return
m_value
;
}
inline
T
const
&
operator
*
()
const
{
return
m_value
;
}
/**
* @brief Returns the value.
*/
inline
T
&
operator
*
()
{
CPPA_REQUIRE
(
valid
());
return
m_value
;
}
/**
* @brief Returns the value.
*/
inline
T
const
&
operator
*
()
const
{
CPPA_REQUIRE
(
valid
());
return
m_value
;
}
inline
T
&
get
()
{
return
m_value
;
}
/**
* @brief Returns the value.
*/
inline
T
&
get
()
{
CPPA_REQUIRE
(
valid
());
return
m_value
;
}
inline
T
const
&
get
()
const
{
return
m_value
;
}
/**
* @brief Returns the value.
*/
inline
T
const
&
get
()
const
{
CPPA_REQUIRE
(
valid
());
return
m_value
;
}
inline
T
&
get_or_else
(
T
const
&
val
)
/**
* @brief Returns the value of this @p option if it's valid
* or @p default_value.
*/
inline
T
&
get_or_else
(
T
const
&
default_value
)
{
if
(
!
m_valid
)
cr
(
val
);
if
(
!
m_valid
)
cr
(
default_value
);
return
m_value
;
}
inline
T
&
get_or_else
(
T
&&
val
)
/**
* @copydoc get_or_else(T const&)
*/
inline
T
&
get_or_else
(
T
&&
default_value
)
{
if
(
!
m_valid
)
cr
(
std
::
move
(
val
));
if
(
!
m_valid
)
cr
(
std
::
move
(
default_value
));
return
m_value
;
}
public:
bool
m_valid
;
union
{
T
m_value
;
};
void
destroy
()
{
if
(
m_valid
)
m_value
.
~
T
();
}
template
<
typename
V
>
void
cr
(
V
&&
value
)
{
m_valid
=
true
;
new
(
&
m_value
)
T
(
std
::
forward
<
V
>
(
value
));
}
};
template
<
typename
T
>
bool
operator
==
(
option
<
T
>
const
&
lhs
,
option
<
T
>
const
&
rhs
)
{
if
((
lhs
)
&&
(
rhs
))
return
*
lhs
==
*
rhs
;
return
false
;
}
template
<
typename
T
>
bool
operator
==
(
option
<
T
>
const
&
lhs
,
T
const
&
rhs
)
{
if
(
lhs
)
return
*
lhs
==
rhs
;
return
false
;
}
template
<
typename
T
>
bool
operator
==
(
T
const
&
lhs
,
option
<
T
>
const
&
rhs
)
{
return
rhs
==
lhs
;
}
template
<
typename
T
>
bool
operator
!=
(
option
<
T
>
const
&
lhs
,
option
<
T
>
const
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
template
<
typename
T
>
bool
operator
!=
(
option
<
T
>
const
&
lhs
,
T
const
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
template
<
typename
T
>
bool
operator
!=
(
T
const
&
lhs
,
option
<
T
>
const
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
}
// namespace cppa
#endif // OPTION_HPP
cppa/tuple_view.hpp
View file @
e3a18cba
...
...
@@ -60,7 +60,7 @@ class tuple_view
template
<
size_t
N
,
typename
...
Types
>
friend
typename
util
::
at
<
N
,
Types
...
>::
type
&
get_ref
(
tuple_view
<
Types
...
>&
);
void
const
*
m_data
[
sizeof
...(
ElementTypes
)];
void
*
m_data
[
sizeof
...(
ElementTypes
)];
tuple_view
()
{
}
...
...
@@ -70,7 +70,7 @@ class tuple_view
typedef
util
::
type_list
<
ElementTypes
...
>
types
;
static
tuple_view
from
(
std
::
vector
<
std
::
pair
<
uniform_type_info
const
*
,
void
const
*>
>
const
&
vec
)
static
tuple_view
from
(
std
::
vector
<
std
::
pair
<
uniform_type_info
const
*
,
void
*>
>
const
&
vec
)
{
tuple_view
result
;
size_t
j
=
0
;
...
...
@@ -81,7 +81,7 @@ class tuple_view
return
std
::
move
(
result
);
}
static
tuple_view
from
(
std
::
vector
<
std
::
pair
<
uniform_type_info
const
*
,
void
const
*>
>
const
&
vec
,
static
tuple_view
from
(
std
::
vector
<
std
::
pair
<
uniform_type_info
const
*
,
void
*>
>
const
&
vec
,
util
::
fixed_vector
<
size_t
,
sizeof
...(
ElementTypes
)
>
const
&
mv
)
{
tuple_view
result
;
...
...
@@ -110,6 +110,8 @@ class tuple_view
inline
void
const
*
at
(
size_t
p
)
const
{
return
m_data
[
p
];
}
inline
void
*
mutable_at
(
size_t
p
)
{
return
m_data
[
p
];
}
};
template
<
size_t
N
,
typename
...
Types
>
...
...
@@ -120,13 +122,13 @@ const typename util::at<N, Types...>::type& get(tuple_view<Types...> const& t)
return
*
reinterpret_cast
<
result_t
const
*>
(
t
.
at
(
N
));
}
//
template<size_t N, typename... Types>
//
typename util::at<N, Types...>::type& get_ref(tuple_view<Types...>& t)
//
{
//
static_assert(N < sizeof...(Types), "N >= t.size()");
//
typedef typename util::at<N, Types...>::type result_t;
// return *reinterpret_cast<result_t*>(t.m_vals->
mutable_at(N));
//
}
template
<
size_t
N
,
typename
...
Types
>
typename
util
::
at
<
N
,
Types
...
>::
type
&
get_ref
(
tuple_view
<
Types
...
>&
t
)
{
static_assert
(
N
<
sizeof
...(
Types
),
"N >= t.size()"
);
typedef
typename
util
::
at
<
N
,
Types
...
>::
type
result_t
;
return
*
reinterpret_cast
<
result_t
*>
(
t
.
mutable_at
(
N
));
}
template
<
typename
TypeList
>
struct
tuple_view_from_type_list
;
...
...
gen_server/Makefile
View file @
e3a18cba
#CXX = /opt/local/bin/g++-mp-4.6
CXX
=
/
usr/bin/g++
-4.6
CXXFLAGS
=
-std
=
c++0x
-pedantic
-Wall
-Wextra
-I
/opt/local/include/
-I
../
-fpermissive
-O2
CXX
=
/
opt/local/bin/g++-mp
-4.6
CXXFLAGS
=
-std
=
c++0x
-pedantic
-Wall
-Wextra
-I
/opt/local/include/
-I
../
-fpermissive
LIBS
=
-L
../.libs/
-lcppa
-L
/opt/local/lib
-L
/usr/lib
-lboost_thread-mt
all
:
...
...
gen_server/sequential_send.cpp
View file @
e3a18cba
...
...
@@ -31,10 +31,10 @@ long the_test(int msg_count)
auto
msg
=
make_tuple
(
atom
(
"AddCount"
),
val
);
for
(
int
i
=
0
;
i
<
msg_count
;
++
i
)
{
send_tuple
(
counter
,
msg
)
;
counter
<<
msg
;
//send(counter, atom("AddCount"), val);
}
send
(
counter
,
atom
(
"Get"
),
self
()
);
send
(
counter
,
atom
(
"Get"
),
self
);
long
result
=
0
;
receive
(
...
...
@@ -64,3 +64,4 @@ int main()
await_all_others_done
();
return
0
;
}
src/abstract_event_based_actor.cpp
View file @
e3a18cba
...
...
@@ -72,9 +72,9 @@ 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
.
top
().
is_right
())
if
(
m_loop_stack
.
back
().
is_right
())
{
request_timeout
(
m_loop_stack
.
top
().
right
().
timeout
());
request_timeout
(
m_loop_stack
.
back
().
right
().
timeout
());
}
}
break
;
...
...
@@ -85,7 +85,7 @@ void abstract_event_based_actor::handle_message(queue_node_ptr& node,
void
abstract_event_based_actor
::
handle_message
(
queue_node_ptr
&
node
)
{
auto
&
bhvr
=
m_loop_stack
.
top
();
auto
&
bhvr
=
m_loop_stack
.
back
();
if
(
bhvr
.
is_left
())
{
handle_message
(
node
,
bhvr
.
left
());
...
...
@@ -102,7 +102,7 @@ void abstract_event_based_actor::resume(util::fiber*, resume_callback* callback)
auto
done_cb
=
[
&
]()
{
m_state
.
store
(
abstract_scheduled_actor
::
done
);
while
(
!
m_loop_stack
.
empty
())
m_loop_stack
.
pop
();
while
(
!
m_loop_stack
.
empty
())
m_loop_stack
.
pop
_back
();
on_exit
();
callback
->
exec_done
();
};
...
...
src/abstract_scheduled_actor.cpp
View file @
e3a18cba
...
...
@@ -29,12 +29,17 @@
#include "cppa/cppa.hpp"
#include "cppa/to_string.hpp"
#include "cppa/exception.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/task_scheduler.hpp"
#include "cppa/detail/yield_interface.hpp"
#include "cppa/detail/abstract_scheduled_actor.hpp"
using
std
::
cout
;
using
std
::
endl
;
#include <iostream>
namespace
cppa
{
namespace
detail
{
namespace
{
...
...
@@ -202,6 +207,12 @@ auto abstract_scheduled_actor::dq(queue_node_ptr& node,
}
else
{
std
::
string
err_msg
=
"unhandled message in actor "
;
err_msg
+=
std
::
to_string
(
id
());
err_msg
+=
": "
;
err_msg
+=
to_string
(
node
->
msg
);
err_msg
+=
"
\n
"
;
cout
<<
err_msg
;
buffer
.
push_back
(
node
.
release
());
return
dq_indeterminate
;
}
...
...
src/event_based_actor.cpp
View file @
e3a18cba
...
...
@@ -30,11 +30,32 @@
#include "cppa/event_based_actor.hpp"
namespace
{
template
<
class
StackElement
,
class
Vec
,
class
What
>
void
push_to
(
Vec
&
vec
,
What
*
bhvr
,
bool
has_ownership
)
{
// 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
));
}
else
{
vec
[
0
]
=
std
::
move
(
vec
[
1
]);
vec
[
1
]
=
StackElement
(
bhvr
,
has_ownership
);
}
}
}
// namespace <anonymous>
namespace
cppa
{
void
event_based_actor
::
become_void
()
{
while
(
!
m_loop_stack
.
empty
())
m_loop_stack
.
pop
();
m_loop_stack
.
clear
();
}
void
event_based_actor
::
do_become
(
behavior
*
bhvr
)
...
...
@@ -51,16 +72,14 @@ void event_based_actor::do_become(behavior* bhvr)
void
event_based_actor
::
do_become
(
invoke_rules
*
bhvr
,
bool
has_ownership
)
{
become_void
();
reset_timeout
();
m_loop_stack
.
push
(
stack_element
(
bhvr
,
has_ownership
)
);
push_to
<
stack_element
>
(
m_loop_stack
,
bhvr
,
has_ownership
);
}
void
event_based_actor
::
do_become
(
timed_invoke_rules
*
bhvr
,
bool
has_ownership
)
{
become_void
();
request_timeout
(
bhvr
->
timeout
());
m_loop_stack
.
push
(
stack_element
(
bhvr
,
has_ownership
)
);
push_to
<
stack_element
>
(
m_loop_stack
,
bhvr
,
has_ownership
);
}
}
// namespace cppa
src/group.cpp
View file @
e3a18cba
...
...
@@ -38,19 +38,24 @@
namespace
cppa
{
intrusive_ptr
<
group
>
group
::
get
(
const
std
::
string
&
arg0
,
const
std
::
string
&
arg1
)
intrusive_ptr
<
group
>
group
::
get
(
std
::
string
const
&
arg0
,
std
::
string
const
&
arg1
)
{
return
detail
::
singleton_manager
::
get_group_manager
()
->
get
(
arg0
,
arg1
);
}
intrusive_ptr
<
group
>
group
::
anonymous
()
{
return
detail
::
singleton_manager
::
get_group_manager
()
->
anonymous
();
}
void
group
::
add_module
(
group
::
module
*
ptr
)
{
detail
::
singleton_manager
::
get_group_manager
()
->
add_module
(
ptr
);
}
group
::
unsubscriber
::
unsubscriber
(
c
onst
channel_ptr
&
s
,
const
intrusive_ptr
<
group
>
&
g
)
group
::
unsubscriber
::
unsubscriber
(
c
hannel_ptr
const
&
s
,
intrusive_ptr
<
group
>
const
&
g
)
:
m_self
(
s
),
m_group
(
g
)
{
}
...
...
@@ -65,7 +70,7 @@ void group::unsubscriber::actor_exited(std::uint32_t)
// unsubscription is done in destructor
}
bool
group
::
unsubscriber
::
matches
(
const
attachable
::
token
&
what
)
bool
group
::
unsubscriber
::
matches
(
attachable
::
token
const
&
what
)
{
if
(
what
.
subtype
==
typeid
(
group
::
unsubscriber
))
{
...
...
@@ -74,7 +79,7 @@ bool group::unsubscriber::matches(const attachable::token& what)
return
false
;
}
group
::
module
::
module
(
const
std
::
string
&
name
)
:
m_name
(
name
)
group
::
module
::
module
(
std
::
string
const
&
name
)
:
m_name
(
name
)
{
}
...
...
@@ -82,7 +87,7 @@ group::module::module(std::string&& name) : m_name(std::move(name))
{
}
const
std
::
string
&
group
::
module
::
name
()
std
::
string
const
&
group
::
module
::
name
()
{
return
m_name
;
}
...
...
@@ -92,17 +97,17 @@ group::group(std::string&& id, std::string&& mod_name)
{
}
group
::
group
(
const
std
::
string
&
id
,
const
std
::
string
&
mod_name
)
group
::
group
(
std
::
string
const
&
id
,
std
::
string
const
&
mod_name
)
:
m_identifier
(
id
),
m_module_name
(
mod_name
)
{
}
const
std
::
string
&
group
::
identifier
()
const
std
::
string
const
&
group
::
identifier
()
const
{
return
m_identifier
;
}
const
std
::
string
&
group
::
module_name
()
const
std
::
string
const
&
group
::
module_name
()
const
{
return
m_module_name
;
}
...
...
src/group_manager.cpp
View file @
e3a18cba
...
...
@@ -47,22 +47,16 @@ typedef util::upgrade_lock_guard<util::shared_spinlock> upgrade_guard;
class
local_group_module
;
class
local_group
:
public
group
class
group_impl
:
public
group
{
friend
class
local_group_module
;
util
::
shared_spinlock
m_shared_mtx
;
std
::
set
<
channel_ptr
>
m_subscribers
;
// allow access to local_group_module only
local_group
(
std
::
string
&&
gname
)
:
group
(
std
::
move
(
gname
),
"local"
)
{
}
protected:
local_group
(
const
std
::
string
&
gname
)
:
group
(
gname
,
"local"
)
{
}
template
<
typename
F
,
typename
S
>
group_impl
(
F
&&
f
,
S
&&
s
)
:
group
(
std
::
forward
<
F
>
(
f
),
std
::
forward
<
S
>
(
s
))
{
}
public:
...
...
@@ -71,6 +65,8 @@ class local_group : public group
shared_guard
guard
(
m_shared_mtx
);
for
(
auto
i
=
m_subscribers
.
begin
();
i
!=
m_subscribers
.
end
();
++
i
)
{
// this cast is safe because we don't affect the "value"
// of *i, thus, the set remains in a consistent state
const_cast
<
channel_ptr
&>
(
*
i
)
->
enqueue
(
sender
,
msg
);
}
}
...
...
@@ -81,7 +77,7 @@ class local_group : public group
enqueue
(
sender
,
tmp
);
}
virtual
group
::
subscription
subscribe
(
const
channel_ptr
&
who
)
group
::
subscription
subscribe
(
const
channel_ptr
&
who
)
/*override*/
{
group
::
subscription
result
;
exclusive_guard
guard
(
m_shared_mtx
);
...
...
@@ -92,11 +88,24 @@ class local_group : public group
return
result
;
}
v
irtual
void
unsubscribe
(
const
channel_ptr
&
who
)
v
oid
unsubscribe
(
const
channel_ptr
&
who
)
/*override*/
{
exclusive_guard
guard
(
m_shared_mtx
);
m_subscribers
.
erase
(
who
);
}
};
struct
anonymous_group
:
group_impl
{
anonymous_group
()
:
group_impl
(
"anonymous"
,
"anonymous"
)
{
}
};
class
local_group
:
public
group_impl
{
friend
class
local_group_module
;
local_group
(
std
::
string
const
&
gname
)
:
group_impl
(
gname
,
"local"
)
{
}
};
...
...
@@ -110,9 +119,7 @@ class local_group_module : public group::module
public:
local_group_module
()
:
super
(
"local"
)
{
}
local_group_module
()
:
super
(
"local"
)
{
}
group_ptr
get
(
const
std
::
string
&
group_name
)
{
...
...
@@ -147,6 +154,11 @@ group_manager::group_manager()
m_mmap
.
insert
(
std
::
make_pair
(
std
::
string
(
"local"
),
std
::
move
(
ptr
)));
}
intrusive_ptr
<
group
>
group_manager
::
anonymous
()
{
return
new
anonymous_group
;
}
intrusive_ptr
<
group
>
group_manager
::
get
(
const
std
::
string
&
module_name
,
const
std
::
string
&
group_identifier
)
{
...
...
src/scheduler.cpp
View file @
e3a18cba
...
...
@@ -149,7 +149,7 @@ void scheduler_helper::time_emitter(scheduler_helper::ptr_type m_self)
if
(
*
whom
)
{
any_tuple
msg
=
*
(
reinterpret_cast
<
any_tuple
const
*>
(
ptr
->
msg
.
at
(
2
)));
ptr
->
msg
.
at
(
2
)));
(
*
whom
)
->
enqueue
(
ptr
->
sender
.
get
(),
std
::
move
(
msg
));
}
messages
.
erase
(
it
);
...
...
@@ -159,7 +159,7 @@ void scheduler_helper::time_emitter(scheduler_helper::ptr_type m_self)
// wait for next message or next timeout
if
(
it
!=
messages
.
end
())
{
msg_ptr
=
queue
.
try_pop
(
it
->
first
);
msg_ptr
.
reset
(
queue
.
try_pop
(
it
->
first
)
);
}
}
}
...
...
src/stacked_event_based_actor.cpp
View file @
e3a18cba
...
...
@@ -34,26 +34,26 @@ namespace cppa {
void
stacked_event_based_actor
::
become_void
()
{
while
(
!
m_loop_stack
.
empty
())
m_loop_stack
.
pop
();
m_loop_stack
.
clear
();
}
void
stacked_event_based_actor
::
unbecome
()
{
if
(
!
m_loop_stack
.
empty
())
m_loop_stack
.
pop
();
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
(
stack_element
(
behavior
,
has_ownership
));
m_loop_stack
.
push
_back
(
stack_element
(
behavior
,
has_ownership
));
}
void
stacked_event_based_actor
::
do_become
(
timed_invoke_rules
*
behavior
,
bool
has_ownership
)
{
request_timeout
(
behavior
->
timeout
());
m_loop_stack
.
push
(
stack_element
(
behavior
,
has_ownership
));
m_loop_stack
.
push
_back
(
stack_element
(
behavior
,
has_ownership
));
}
}
// namespace cppa
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