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
767ab3f4
Commit
767ab3f4
authored
May 14, 2011
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
shared spinlock, some implementation work
parent
1d3cce57
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
573 additions
and
307 deletions
+573
-307
cppa.creator.user
cppa.creator.user
+1
-1
cppa.files
cppa.files
+4
-0
cppa/actor.hpp
cppa/actor.hpp
+2
-0
cppa/detail/abstract_tuple.hpp
cppa/detail/abstract_tuple.hpp
+1
-1
cppa/intrusive_ptr.hpp
cppa/intrusive_ptr.hpp
+119
-131
cppa/message.hpp
cppa/message.hpp
+47
-34
cppa/on.hpp
cppa/on.hpp
+111
-110
cppa/ref_counted.hpp
cppa/ref_counted.hpp
+1
-1
cppa/scheduler.hpp
cppa/scheduler.hpp
+7
-0
cppa/tuple.hpp
cppa/tuple.hpp
+21
-4
cppa/untyped_tuple.hpp
cppa/untyped_tuple.hpp
+18
-16
cppa/util/replace_type.hpp
cppa/util/replace_type.hpp
+1
-1
cppa/util/shared_lock_guard.hpp
cppa/util/shared_lock_guard.hpp
+28
-0
cppa/util/shared_spinlock.hpp
cppa/util/shared_spinlock.hpp
+30
-0
libcppa.Makefile
libcppa.Makefile
+7
-0
src/actor.cpp
src/actor.cpp
+32
-2
src/message.cpp
src/message.cpp
+23
-0
src/shared_spinlock.cpp
src/shared_spinlock.cpp
+78
-0
src/uniform_type_info.cpp
src/uniform_type_info.cpp
+2
-1
unit_testing/test__serialization.cpp
unit_testing/test__serialization.cpp
+40
-5
No files found.
cppa.creator.user
View file @
767ab3f4
...
...
@@ -135,7 +135,7 @@
</data>
<data>
<variable>
ProjectExplorer.Project.Updater.EnvironmentId
</variable>
<value
type=
"QString"
>
{
23902c37-f07e-47cd-bb19-c366b9f708db
}
</value>
<value
type=
"QString"
>
{
07fcd197-092d-45a0-8500-3be614e6ae31
}
</value>
</data>
<data>
<variable>
ProjectExplorer.Project.Updater.FileVersion
</variable>
...
...
cppa.files
View file @
767ab3f4
...
...
@@ -143,3 +143,7 @@ src/binary_deserializer.cpp
src/actor.cpp
cppa/announce.hpp
src/abstract_type_list.cpp
src/message.cpp
cppa/util/shared_spinlock.hpp
src/shared_spinlock.cpp
cppa/util/shared_lock_guard.hpp
cppa/actor.hpp
View file @
767ab3f4
...
...
@@ -22,6 +22,8 @@ class actor : public channel
public:
~
actor
();
virtual
void
join
(
group_ptr
&
what
)
=
0
;
virtual
void
leave
(
const
group_ptr
&
what
)
=
0
;
virtual
void
link
(
intrusive_ptr
<
actor
>&
other
)
=
0
;
...
...
cppa/detail/abstract_tuple.hpp
View file @
767ab3f4
...
...
@@ -18,9 +18,9 @@ struct abstract_tuple : ref_counted
virtual
std
::
size_t
size
()
const
=
0
;
virtual
abstract_tuple
*
copy
()
const
=
0
;
virtual
const
void
*
at
(
std
::
size_t
pos
)
const
=
0
;
virtual
const
uniform_type_info
*
utype_at
(
std
::
size_t
pos
)
const
=
0
;
virtual
const
util
::
abstract_type_list
&
types
()
const
=
0
;
virtual
bool
equal_to
(
const
abstract_tuple
&
other
)
const
=
0
;
virtual
const
uniform_type_info
*
utype_at
(
std
::
size_t
pos
)
const
=
0
;
};
...
...
cppa/intrusive_ptr.hpp
View file @
767ab3f4
...
...
@@ -136,18 +136,6 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>,
return
compare
(
other
.
get
());
}
/*
inline bool equal_to(const T* ptr) const
{
return get() == ptr;
}
inline bool equal_to(const intrusive_ptr& other) const
{
return get() == other.get();
}
*/
};
template
<
typename
X
,
typename
Y
>
...
...
cppa/message.hpp
View file @
767ab3f4
...
...
@@ -14,54 +14,67 @@ namespace cppa {
class
message
{
public:
struct
content
:
ref_counted
{
const
actor_ptr
sender
;
const
channel_ptr
receiver
;
const
untyped_tuple
data
;
content
(
const
actor_ptr
&
s
,
const
channel_ptr
&
r
,
inline
content
(
const
actor_ptr
&
s
,
const
channel_ptr
&
r
,
const
untyped_tuple
&
ut
)
:
ref_counted
(),
sender
(
s
),
receiver
(
r
),
data
(
ut
)
{
}
};
private:
intrusive_ptr
<
content
>
m_content
;
public:
template
<
typename
...
Args
>
message
(
const
actor_ptr
&
from
,
const
channel_ptr
&
to
,
const
Args
&
...
args
)
:
m_content
(
new
content
(
from
,
to
,
tuple
<
Args
...
>
(
args
...)))
{
}
:
m_content
(
new
content
(
from
,
to
,
tuple
<
Args
...
>
(
args
...)))
{
}
message
(
const
actor_ptr
&
from
,
const
channel_ptr
&
to
,
const
untyped_tuple
&
ut
);
message
(
const
actor_ptr
&
from
,
const
channel_ptr
&
to
,
const
untyped_tuple
&
ut
)
:
m_content
(
new
content
(
from
,
to
,
ut
))
{
}
message
();
// message(const actor_ptr& from, const channel_ptr& to, untyped_tuple&& ut)
// : m_content(new content(from, to, std::move(ut))) { }
message
&
operator
=
(
const
message
&
)
=
default
;
message
()
:
m_content
(
new
content
(
0
,
0
,
tuple
<
int
>
(
0
)))
{
}
message
&
operator
=
(
message
&&
)
=
default
;
const
actor_ptr
&
sender
()
const
message
(
const
message
&
)
=
default
;
message
(
message
&&
)
=
default
;
inline
const
actor_ptr
&
sender
()
const
{
return
m_content
->
sender
;
}
const
channel_ptr
&
receiver
()
const
inline
const
channel_ptr
&
receiver
()
const
{
return
m_content
->
receiver
;
}
const
untyped_tuple
&
data
()
const
inline
const
untyped_tuple
&
data
()
const
{
return
m_content
->
data
;
}
};
bool
operator
==
(
const
message
&
lhs
,
const
message
&
rhs
);
inline
bool
operator
!=
(
const
message
&
lhs
,
const
message
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
}
// namespace cppa
#endif // MESSAGE_HPP
cppa/on.hpp
View file @
767ab3f4
...
...
@@ -12,6 +12,7 @@
namespace
cppa
{
namespace
detail
{
// irb_helper is not thread safe
struct
irb_helper
:
ref_counted_impl
<
std
::
size_t
>
{
virtual
~
irb_helper
()
{
}
...
...
cppa/ref_counted.hpp
View file @
767ab3f4
...
...
@@ -12,7 +12,7 @@ namespace cppa {
* @brief (Thread safe) base class for reference counted objects
* with an atomic reference count.
*/
typedef
detail
::
ref_counted_impl
<
std
::
atomic
<
std
::
size_t
>
>
ref_counted
;
typedef
detail
::
ref_counted_impl
<
std
::
atomic
<
std
::
size_t
>
>
ref_counted
;
}
// namespace cppa
...
...
cppa/scheduler.hpp
View file @
767ab3f4
...
...
@@ -9,6 +9,9 @@ namespace cppa {
class
context
;
class
actor_behavior
;
/**
* @brief
*/
class
scheduler
{
...
...
@@ -44,6 +47,10 @@ class scheduler
};
/**
* @brief Gets the actual used scheduler implementation.
* @return The active scheduler or @c nullptr.
*/
scheduler
*
get_scheduler
();
}
// namespace cppa::detail
...
...
cppa/tuple.hpp
View file @
767ab3f4
...
...
@@ -22,22 +22,39 @@
namespace
cppa
{
namespace
detail
{
template
<
typename
T
>
struct
is_char_array
/**
* @brief <tt>is_array_of<T,U>::value == true</tt> if and only
* if T is an array of U.
*/
template
<
typename
T
,
typename
U
>
struct
is_array_of
{
typedef
typename
std
::
remove_all_extents
<
T
>::
type
step1_type
;
typedef
typename
std
::
remove_cv
<
step1_type
>::
type
step2_type
;
static
const
bool
value
=
std
::
is_array
<
T
>::
value
&&
std
::
is_same
<
step2_type
,
char
>::
value
;
&&
std
::
is_same
<
step2_type
,
U
>::
value
;
};
template
<
typename
T
>
struct
chars_to_string
{
typedef
typename
util
::
replace_type
<
T
,
std
::
string
,
std
::
is_same
<
T
,
const
char
*>
,
std
::
is_same
<
T
,
char
*>
,
is_char_array
<
T
>>::
type
is_array_of
<
T
,
char
>>::
type
subtype1
;
typedef
typename
util
::
replace_type
<
subtype1
,
std
::
u16string
,
std
::
is_same
<
subtype1
,
const
char16_t
*>
,
std
::
is_same
<
subtype1
,
char16_t
*>
,
is_array_of
<
subtype1
,
char16_t
>>::
type
subtype2
;
typedef
typename
util
::
replace_type
<
subtype2
,
std
::
u32string
,
std
::
is_same
<
subtype2
,
const
char32_t
*>
,
std
::
is_same
<
subtype2
,
char32_t
*>
,
is_array_of
<
subtype2
,
char32_t
>>::
type
type
;
};
...
...
cppa/untyped_tuple.hpp
View file @
767ab3f4
...
...
@@ -26,7 +26,9 @@ class untyped_tuple
std
::
size_t
size
()
const
{
return
m_vals
->
size
();
}
const
void
*
at
(
std
::
size_t
p
)
const
{
return
m_vals
->
at
(
p
);
}
void
*
mutable_at
(
size_t
p
)
{
return
m_vals
->
mutable_at
(
p
);
}
const
void
*
at
(
size_t
p
)
const
{
return
m_vals
->
at
(
p
);
}
const
uniform_type_info
*
utype_at
(
std
::
size_t
p
)
const
{
return
m_vals
->
utype_at
(
p
);
}
...
...
cppa/util/replace_type.hpp
View file @
767ab3f4
...
...
@@ -26,7 +26,7 @@ namespace cppa { namespace util {
template
<
typename
What
,
typename
With
,
typename
...
IfStmt
>
struct
replace_type
{
static
const
bool
do_replace
=
disjunction
<
IfStmt
...
>::
value
;
static
const
expr
bool
do_replace
=
disjunction
<
IfStmt
...
>::
value
;
typedef
typename
detail
::
replace_type
<
do_replace
,
What
,
With
>::
type
type
;
};
...
...
cppa/util/shared_lock_guard.hpp
0 → 100644
View file @
767ab3f4
#ifndef SHARED_LOCK_GUARD_HPP
#define SHARED_LOCK_GUARD_HPP
namespace
cppa
{
namespace
util
{
template
<
typename
SharedLockable
>
class
shared_lock_guard
{
SharedLockable
&
m_lockable
;
public:
shared_lock_guard
(
SharedLockable
&
lockable
)
:
m_lockable
(
lockable
)
{
m_lockable
.
lock_shared
();
}
~
shared_lock_guard
()
{
m_lockable
.
unlock_shared
();
}
};
}
}
// namespace cppa::util
#endif // SHARED_LOCK_GUARD_HPP
cppa/util/shared_spinlock.hpp
0 → 100644
View file @
767ab3f4
#ifndef SHARED_SPINLOCK_HPP
#define SHARED_SPINLOCK_HPP
#include <atomic>
#include <cstddef>
namespace
cppa
{
namespace
util
{
class
shared_spinlock
{
std
::
atomic
<
long
>
m_flag
;
public:
shared_spinlock
();
void
lock
();
void
unlock
();
bool
try_lock
();
void
lock_shared
();
void
unlock_shared
();
bool
try_lock_shared
();
};
}
}
// namespace cppa::util
#endif // SHARED_SPINLOCK_HPP
libcppa.Makefile
View file @
767ab3f4
...
...
@@ -59,8 +59,13 @@ HEADERS = cppa/actor.hpp \
cppa/util/is_comparable.hpp \
cppa/util/is_copyable.hpp \
cppa/util/is_one_of.hpp \
cppa/util/is_primitive.hpp \
cppa/util/pt_token.hpp \
cppa/util/remove_const_reference.hpp \
cppa/util/replace_type.hpp \
cppa/util/reverse_type_list.hpp \
cppa/util/rm_ref.hpp \
cppa/util/shared_spinlock.hpp \
cppa/util/single_reader_queue.hpp \
cppa/util/type_at.hpp \
cppa/util/type_list.hpp \
...
...
@@ -80,11 +85,13 @@ SOURCES = src/abstract_type_list.cpp \
src/demangle.cpp \
src/deserializer.cpp \
src/group.cpp \
src/message.cpp \
src/mock_scheduler.cpp \
src/object.cpp \
src/primitive_variant.cpp \
src/scheduler.cpp \
src/serializer.cpp \
src/shared_spinlock.cpp \
src/to_uniform_name.cpp \
src/uniform_type_info.cpp \
src/untyped_tuple.cpp
...
...
src/actor.cpp
View file @
767ab3f4
#include "cppa/config.hpp"
#include <map>
#include <mutex>
#include <atomic>
#include "cppa/actor.hpp"
#include "cppa/util/shared_spinlock.hpp"
#include "cppa/util/shared_lock_guard.hpp"
namespace
{
std
::
atomic
<
std
::
uint32_t
>
s_ids
(
1
);
std
::
map
<
std
::
uint32_t
,
cppa
::
actor
*>
s_instances
;
cppa
::
util
::
shared_spinlock
s_instances_mtx
;
}
// namespace <anonmyous>
namespace
cppa
{
actor
::
actor
()
:
m_id
(
0
)
actor
::
actor
()
:
m_id
(
s_ids
.
fetch_add
(
1
))
{
std
::
lock_guard
<
util
::
shared_spinlock
>
guard
(
s_instances_mtx
);
s_instances
.
insert
(
std
::
make_pair
(
m_id
,
this
));
}
actor
::~
actor
()
{
std
::
lock_guard
<
util
::
shared_spinlock
>
guard
(
s_instances_mtx
);
s_instances
.
erase
(
m_id
);
}
intrusive_ptr
<
actor
>
actor
::
by_id
(
std
::
uint32_t
)
intrusive_ptr
<
actor
>
actor
::
by_id
(
std
::
uint32_t
actor_id
)
{
util
::
shared_lock_guard
<
util
::
shared_spinlock
>
guard
(
s_instances_mtx
);
auto
i
=
s_instances
.
find
(
actor_id
);
if
(
i
!=
s_instances
.
end
())
{
return
i
->
second
;
}
return
nullptr
;
}
...
...
src/message.cpp
0 → 100644
View file @
767ab3f4
#include "cppa/message.hpp"
namespace
cppa
{
message
::
message
(
const
actor_ptr
&
from
,
const
channel_ptr
&
to
,
const
untyped_tuple
&
ut
)
:
m_content
(
new
content
(
from
,
to
,
ut
))
{
}
message
::
message
()
:
m_content
(
new
content
(
0
,
0
,
tuple
<
int
>
(
0
)))
{
}
bool
operator
==
(
const
message
&
lhs
,
const
message
&
rhs
)
{
return
lhs
.
sender
()
==
rhs
.
sender
()
&&
lhs
.
receiver
()
==
rhs
.
receiver
()
&&
lhs
.
data
().
vals
()
->
equal_to
(
*
(
rhs
.
data
().
vals
()));
}
}
// namespace cppa
src/shared_spinlock.cpp
0 → 100644
View file @
767ab3f4
#include "cppa/config.hpp"
#include <limits>
#include <thread>
#include "cppa/util/shared_spinlock.hpp"
namespace
{
constexpr
long
min_long
=
std
::
numeric_limits
<
long
>::
min
();
}
// namespace <anonymous>
namespace
cppa
{
namespace
util
{
shared_spinlock
::
shared_spinlock
()
:
m_flag
(
0
)
{
}
void
shared_spinlock
::
lock
()
{
long
v
=
m_flag
.
load
();
for
(;;)
{
if
(
v
!=
0
)
{
//std::this_thread::yield();
v
=
m_flag
.
load
();
}
else
if
(
m_flag
.
compare_exchange_weak
(
v
,
min_long
))
{
return
;
}
// else: next iteration
}
}
void
shared_spinlock
::
unlock
()
{
m_flag
.
store
(
0
);
}
bool
shared_spinlock
::
try_lock
()
{
long
v
=
m_flag
.
load
();
return
(
v
==
0
)
?
m_flag
.
compare_exchange_weak
(
v
,
min_long
)
:
false
;
}
void
shared_spinlock
::
lock_shared
()
{
long
v
=
m_flag
.
load
();
for
(;;)
{
if
(
v
<
0
)
{
//std::this_thread::yield();
v
=
m_flag
.
load
();
}
else
if
(
m_flag
.
compare_exchange_weak
(
v
,
v
+
1
))
{
return
;
}
// else: next iteration
}
}
void
shared_spinlock
::
unlock_shared
()
{
m_flag
.
fetch_sub
(
1
);
}
bool
shared_spinlock
::
try_lock_shared
()
{
long
v
=
m_flag
.
load
();
return
(
v
>=
0
)
?
m_flag
.
compare_exchange_weak
(
v
,
v
+
1
)
:
false
;
}
}
}
// namespace cppa::util
src/uniform_type_info.cpp
View file @
767ab3f4
...
...
@@ -101,7 +101,8 @@ class actor_ptr_type_info_impl : public util::uniform_type_info_base<actor_ptr>
void
serialize
(
const
void
*
ptr
,
serializer
*
sink
)
const
{
sink
->
begin_object
(
name
());
sink
->
write_value
((
*
reinterpret_cast
<
const
actor_ptr
*>
(
ptr
))
->
id
());
auto
id
=
(
*
reinterpret_cast
<
const
actor_ptr
*>
(
ptr
))
->
id
();
sink
->
write_value
(
id
);
sink
->
end_object
();
}
...
...
unit_testing/test__serialization.cpp
View file @
767ab3f4
...
...
@@ -23,6 +23,7 @@
#include "cppa/match.hpp"
#include "cppa/tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/announce.hpp"
#include "cppa/serializer.hpp"
#include "cppa/ref_counted.hpp"
...
...
@@ -37,10 +38,11 @@
#include "cppa/util/pt_token.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/is_iterable.hpp"
#include "cppa/util/if_else_type.hpp"
#include "cppa/util/wrapped_type.hpp"
#include "cppa/util/is_primitive.hpp"
#include "cppa/util/
is_iterabl
e.hpp"
#include "cppa/util/
uniform_type_info_bas
e.hpp"
#include "cppa/detail/type_to_ptype.hpp"
#include "cppa/detail/ptype_to_type.hpp"
...
...
@@ -370,21 +372,54 @@ class string_deserializer : public deserializer
};
class
message_uti
:
public
util
::
uniform_type_info_base
<
message
>
{
public:
virtual
void
serialize
(
const
void
*
instance
,
serializer
*
sink
)
const
{
const
message
&
msg
=
*
reinterpret_cast
<
const
message
*>
(
instance
);
const
untyped_tuple
&
data
=
msg
.
data
();
sink
->
begin_object
(
"cppa::message"
);
sink
->
begin_sequence
(
data
.
size
());
for
(
size_t
i
=
0
;
i
<
data
.
size
();
++
i
)
{
const
uniform_type_info
*
ut
=
data
.
utype_at
(
i
);
ut
->
serialize
(
data
.
at
(
i
),
sink
);
}
sink
->
end_sequence
();
sink
->
end_object
();
}
virtual
void
deserialize
(
void
*
instance
,
deserializer
*
source
)
const
{
}
};
template
<
typename
T
>
std
::
string
to_string
(
const
T
&
what
)
{
std
::
string
tname
=
detail
::
to_uniform_name
(
typeid
(
T
));
auto
mobj
=
uniform_typeid
<
T
>
();
if
(
!
mobj
)
throw
std
::
logic_error
(
tname
+
" not found"
);
auto
utype
=
uniform_typeid
<
T
>
();
if
(
!
utype
)
{
throw
std
::
logic_error
(
detail
::
to_uniform_name
(
typeid
(
T
))
+
" not found"
);
}
std
::
ostringstream
osstr
;
string_serializer
strs
(
osstr
);
mobj
->
serialize
(
&
what
,
&
strs
);
utype
->
serialize
(
&
what
,
&
strs
);
return
osstr
.
str
();
}
std
::
size_t
test__serialization
()
{
CPPA_TEST
(
test__serialization
);
announce
(
typeid
(
message
),
new
message_uti
);
//message msg(0, 0, 42, std::string("Hello World"), 23.32);
//cout << to_string(msg) << endl;
CPPA_CHECK_EQUAL
((
is_iterable
<
int
>::
value
),
false
);
// std::string is primitive and thus not identified by is_iterable
...
...
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