Commit 767ab3f4 authored by neverlord's avatar neverlord

shared spinlock, some implementation work

parent 1d3cce57
...@@ -135,7 +135,7 @@ ...@@ -135,7 +135,7 @@
</data> </data>
<data> <data>
<variable>ProjectExplorer.Project.Updater.EnvironmentId</variable> <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>
<data> <data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable> <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
......
...@@ -143,3 +143,7 @@ src/binary_deserializer.cpp ...@@ -143,3 +143,7 @@ src/binary_deserializer.cpp
src/actor.cpp src/actor.cpp
cppa/announce.hpp cppa/announce.hpp
src/abstract_type_list.cpp src/abstract_type_list.cpp
src/message.cpp
cppa/util/shared_spinlock.hpp
src/shared_spinlock.cpp
cppa/util/shared_lock_guard.hpp
...@@ -22,6 +22,8 @@ class actor : public channel ...@@ -22,6 +22,8 @@ class actor : public channel
public: public:
~actor();
virtual void join(group_ptr& what) = 0; virtual void join(group_ptr& what) = 0;
virtual void leave(const group_ptr& what) = 0; virtual void leave(const group_ptr& what) = 0;
virtual void link(intrusive_ptr<actor>& other) = 0; virtual void link(intrusive_ptr<actor>& other) = 0;
......
...@@ -18,9 +18,9 @@ struct abstract_tuple : ref_counted ...@@ -18,9 +18,9 @@ struct abstract_tuple : ref_counted
virtual std::size_t size() const = 0; virtual std::size_t size() const = 0;
virtual abstract_tuple* copy() const = 0; virtual abstract_tuple* copy() const = 0;
virtual const void* at(std::size_t pos) 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 const util::abstract_type_list& types() const = 0;
virtual bool equal_to(const abstract_tuple& other) 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;
}; };
......
...@@ -12,154 +12,142 @@ namespace cppa { ...@@ -12,154 +12,142 @@ namespace cppa {
template<typename T> template<typename T>
class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>, class intrusive_ptr : util::comparable<intrusive_ptr<T>, T*>,
util::comparable<intrusive_ptr<T>> util::comparable<intrusive_ptr<T>>
{ {
T* m_ptr; T* m_ptr;
inline void set_ptr(T* raw_ptr) inline void set_ptr(T* raw_ptr)
{ {
m_ptr = raw_ptr; m_ptr = raw_ptr;
if (raw_ptr) raw_ptr->ref(); if (raw_ptr) raw_ptr->ref();
} }
public: public:
intrusive_ptr() : m_ptr(0) { } intrusive_ptr() : m_ptr(0) { }
intrusive_ptr(T* raw_ptr) { set_ptr(raw_ptr); } intrusive_ptr(T* raw_ptr) { set_ptr(raw_ptr); }
intrusive_ptr(const intrusive_ptr& other) intrusive_ptr(const intrusive_ptr& other)
{ {
set_ptr(other.m_ptr); set_ptr(other.m_ptr);
} }
intrusive_ptr(intrusive_ptr&& other) : m_ptr(0) intrusive_ptr(intrusive_ptr&& other) : m_ptr(0)
{ {
swap(other); swap(other);
} }
template<typename Y> template<typename Y>
intrusive_ptr(const intrusive_ptr<Y>& other) intrusive_ptr(const intrusive_ptr<Y>& other)
{ {
static_assert(std::is_convertible<Y*, T*>::value, static_assert(std::is_convertible<Y*, T*>::value,
"Y* is not assignable to T*"); "Y* is not assignable to T*");
set_ptr(const_cast<Y*>(other.get())); set_ptr(const_cast<Y*>(other.get()));
} }
template<typename Y> template<typename Y>
intrusive_ptr(intrusive_ptr<Y>&& other) : m_ptr(0) intrusive_ptr(intrusive_ptr<Y>&& other) : m_ptr(0)
{ {
swap(other); swap(other);
} }
~intrusive_ptr() ~intrusive_ptr()
{ {
if (m_ptr && !m_ptr->deref()) if (m_ptr && !m_ptr->deref())
{ {
delete m_ptr; delete m_ptr;
} }
} }
T* get() { return m_ptr; } T* get() { return m_ptr; }
const T* get() const { return m_ptr; } const T* get() const { return m_ptr; }
void swap(intrusive_ptr& other) void swap(intrusive_ptr& other)
{ {
std::swap(m_ptr, other.m_ptr); std::swap(m_ptr, other.m_ptr);
} }
void reset(T* new_value = nullptr) void reset(T* new_value = nullptr)
{ {
if (m_ptr && !m_ptr->deref()) delete m_ptr; if (m_ptr && !m_ptr->deref()) delete m_ptr;
set_ptr(new_value); set_ptr(new_value);
} }
template<typename Y> template<typename Y>
void reset(Y* new_value) void reset(Y* new_value)
{ {
static_assert(std::is_convertible<Y*, T*>::value, static_assert(std::is_convertible<Y*, T*>::value,
"Y* is not assignable to T*"); "Y* is not assignable to T*");
reset(static_cast<T*>(new_value)); reset(static_cast<T*>(new_value));
} }
intrusive_ptr& operator=(const intrusive_ptr& other) intrusive_ptr& operator=(const intrusive_ptr& other)
{ {
intrusive_ptr tmp(other); intrusive_ptr tmp(other);
swap(tmp); swap(tmp);
return *this; return *this;
} }
intrusive_ptr& operator=(intrusive_ptr&& other) intrusive_ptr& operator=(intrusive_ptr&& other)
{ {
reset(); reset();
swap(other); swap(other);
return *this; return *this;
} }
template<typename Y> template<typename Y>
intrusive_ptr& operator=(const intrusive_ptr<Y>& other) intrusive_ptr& operator=(const intrusive_ptr<Y>& other)
{ {
intrusive_ptr tmp(other); intrusive_ptr tmp(other);
swap(tmp); swap(tmp);
return *this; return *this;
} }
template<typename Y> template<typename Y>
intrusive_ptr& operator=(intrusive_ptr<Y>&& other) intrusive_ptr& operator=(intrusive_ptr<Y>&& other)
{ {
static_assert(std::is_convertible<Y*, T*>::value, static_assert(std::is_convertible<Y*, T*>::value,
"Y* is not assignable to T*"); "Y* is not assignable to T*");
m_ptr = other.m_ptr; m_ptr = other.m_ptr;
other.m_ptr = nullptr; other.m_ptr = nullptr;
return *this; return *this;
} }
T* operator->() { return m_ptr; } T* operator->() { return m_ptr; }
T& operator*() { return *m_ptr; } T& operator*() { return *m_ptr; }
const T* operator->() const { return m_ptr; } const T* operator->() const { return m_ptr; }
const T& operator*() const { return *m_ptr; } const T& operator*() const { return *m_ptr; }
inline explicit operator bool() const { return m_ptr != nullptr; } inline explicit operator bool() const { return m_ptr != nullptr; }
inline ptrdiff_t compare(const T* ptr) const inline ptrdiff_t compare(const T* ptr) const
{ {
return static_cast<ptrdiff_t>(get() - ptr); return static_cast<ptrdiff_t>(get() - ptr);
} }
inline ptrdiff_t compare(const intrusive_ptr& other) const inline ptrdiff_t compare(const intrusive_ptr& other) const
{ {
return compare(other.get()); 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> template<typename X, typename Y>
bool operator==(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs) bool operator==(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs)
{ {
return lhs.get() == rhs.get(); return lhs.get() == rhs.get();
} }
template<typename X, typename Y> template<typename X, typename Y>
bool operator!=(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs) bool operator!=(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs)
{ {
return lhs.get() != rhs.get(); return lhs.get() != rhs.get();
} }
} // namespace cppa } // namespace cppa
......
...@@ -14,54 +14,67 @@ namespace cppa { ...@@ -14,54 +14,67 @@ namespace cppa {
class message class message
{ {
struct content : ref_counted
{
const actor_ptr sender;
const channel_ptr receiver;
const untyped_tuple data;
inline content(const actor_ptr& s,
const channel_ptr& r,
const untyped_tuple& ut)
: ref_counted(), sender(s), receiver(r), data(ut)
{
}
};
intrusive_ptr<content> m_content;
public: public:
struct content : ref_counted template<typename... Args>
{ message(const actor_ptr& from, const channel_ptr& to, const Args&... args)
const actor_ptr sender; : m_content(new content(from, to, tuple<Args...>(args...)))
const channel_ptr receiver; {
const untyped_tuple data; }
content(const actor_ptr& s, const channel_ptr& r,
const untyped_tuple& ut)
: ref_counted(), sender(s), receiver(r), data(ut)
{
}
};
private: message(const actor_ptr& from,
const channel_ptr& to,
const untyped_tuple& ut);
intrusive_ptr<content> m_content; message();
public: message& operator=(const message&) = default;
template<typename... Args> message& operator=(message&&) = default;
message(const actor_ptr& from, const channel_ptr& to, const 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 message&) = default;
: m_content(new content(from, to, ut)) { }
// message(const actor_ptr& from, const channel_ptr& to, untyped_tuple&& ut) message(message&&) = default;
// : m_content(new content(from, to, std::move(ut))) { }
message() : m_content(new content(0, 0, tuple<int>(0))) { } inline const actor_ptr& sender() const
{
return m_content->sender;
}
const actor_ptr& sender() const inline const channel_ptr& receiver() const
{ {
return m_content->sender; return m_content->receiver;
} }
const channel_ptr& receiver() const
{
return m_content->receiver;
}
const untyped_tuple& data() const inline const untyped_tuple& data() const
{ {
return m_content->data; 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 } // namespace cppa
#endif // MESSAGE_HPP #endif // MESSAGE_HPP
...@@ -12,127 +12,128 @@ ...@@ -12,127 +12,128 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
// irb_helper is not thread safe
struct irb_helper : ref_counted_impl<std::size_t> struct irb_helper : ref_counted_impl<std::size_t>
{ {
virtual ~irb_helper() { } virtual ~irb_helper() { }
virtual bool value_cmp(const untyped_tuple&, virtual bool value_cmp(const untyped_tuple&,
std::vector<std::size_t>&) const = 0; std::vector<std::size_t>&) const = 0;
}; };
template<typename... Types> template<typename... Types>
struct invoke_rule_builder struct invoke_rule_builder
{ {
typedef util::type_list<Types...> types_list; typedef util::type_list<Types...> types_list;
typedef typename util::filter_type_list<any_type, types_list>::type typedef typename util::filter_type_list<any_type, types_list>::type
filtered_types; filtered_types;
intrusive_ptr<irb_helper> m_helper; intrusive_ptr<irb_helper> m_helper;
public: public:
invoke_rule_builder() { } invoke_rule_builder() { }
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
invoke_rule_builder(const Arg0& arg0, const Args&... args) invoke_rule_builder(const Arg0& arg0, const Args&... args)
{ {
typedef util::type_list<Arg0, Args...> arg_types; typedef util::type_list<Arg0, Args...> arg_types;
static_assert(arg_types::type_list_size static_assert(arg_types::type_list_size
<= filtered_types::type_list_size, <= filtered_types::type_list_size,
"too much arguments"); "too much arguments");
class helper_impl : public irb_helper class helper_impl : public irb_helper
{ {
tuple<Arg0, Args...> m_values; tuple<Arg0, Args...> m_values;
public: public:
helper_impl(const Arg0& arg0, const Args&... args) helper_impl(const Arg0& arg0, const Args&... args)
: m_values(arg0, args...) : m_values(arg0, args...)
{ {
} }
virtual bool value_cmp(const untyped_tuple& t, virtual bool value_cmp(const untyped_tuple& t,
std::vector<std::size_t>& v) const std::vector<std::size_t>& v) const
{ {
return match<Types...>(t, m_values, v); return match<Types...>(t, m_values, v);
} }
}; };
m_helper = new helper_impl(arg0, args...); m_helper = new helper_impl(arg0, args...);
static_assert(util::eval_first_n<arg_types::type_list_size, static_assert(util::eval_first_n<arg_types::type_list_size,
filtered_types, filtered_types,
arg_types, arg_types,
util::is_comparable>::value, util::is_comparable>::value,
"wrong argument types (not comparable)"); "wrong argument types (not comparable)");
} }
typedef typename tuple_view_type_from_type_list<filtered_types>::type typedef typename tuple_view_type_from_type_list<filtered_types>::type
tuple_view_type; tuple_view_type;
template<typename F> template<typename F>
invoke_rules operator>>(F f) invoke_rules operator>>(F f)
{ {
auto sub_inv = [f](const tuple_view_type& tv) auto sub_inv = [f](const tuple_view_type& tv)
{ {
invoke(f, tv); invoke(f, tv);
}; };
if (!m_helper) if (!m_helper)
{ {
auto inv = [f](const untyped_tuple& t) -> bool auto inv = [f](const untyped_tuple& t) -> bool
{ {
std::vector<std::size_t> mappings; std::vector<std::size_t> mappings;
if (match<Types...>(t, mappings)) if (match<Types...>(t, mappings))
{ {
tuple_view_type tv(t.vals(), std::move(mappings)); tuple_view_type tv(t.vals(), std::move(mappings));
invoke(f, tv); invoke(f, tv);
return true; return true;
} }
return false; return false;
}; };
auto gt = [sub_inv](const untyped_tuple& t) -> detail::intermediate* auto gt = [sub_inv](const untyped_tuple& t) -> detail::intermediate*
{ {
std::vector<std::size_t> mappings; std::vector<std::size_t> mappings;
if (match<Types...>(t, mappings)) if (match<Types...>(t, mappings))
{ {
tuple_view_type tv(t.vals(), std::move(mappings)); tuple_view_type tv(t.vals(), std::move(mappings));
return new detail::intermediate_impl<decltype(sub_inv), tuple_view_type>(sub_inv, tv); return new detail::intermediate_impl<decltype(sub_inv), tuple_view_type>(sub_inv, tv);
} }
return 0; return 0;
}; };
return invoke_rules(new detail::invokable_impl<decltype(inv), decltype(gt)>(std::move(inv), std::move(gt))); return invoke_rules(new detail::invokable_impl<decltype(inv), decltype(gt)>(std::move(inv), std::move(gt)));
} }
else else
{ {
auto inv = [f, m_helper](const untyped_tuple& t) -> bool auto inv = [f, m_helper](const untyped_tuple& t) -> bool
{ {
std::vector<std::size_t> mappings; std::vector<std::size_t> mappings;
if (m_helper->value_cmp(t, mappings)) if (m_helper->value_cmp(t, mappings))
{ {
tuple_view_type tv(t.vals(), std::move(mappings)); tuple_view_type tv(t.vals(), std::move(mappings));
invoke(f, tv); invoke(f, tv);
return true; return true;
} }
return false; return false;
}; };
auto gt = [sub_inv, m_helper](const untyped_tuple& t) -> detail::intermediate* auto gt = [sub_inv, m_helper](const untyped_tuple& t) -> detail::intermediate*
{ {
std::vector<std::size_t> mappings; std::vector<std::size_t> mappings;
if (m_helper->value_cmp(t, mappings)) if (m_helper->value_cmp(t, mappings))
{ {
tuple_view_type tv(t.vals(), std::move(mappings)); tuple_view_type tv(t.vals(), std::move(mappings));
return new detail::intermediate_impl<decltype(sub_inv), tuple_view_type>(sub_inv, tv); return new detail::intermediate_impl<decltype(sub_inv), tuple_view_type>(sub_inv, tv);
} }
return 0; return 0;
}; };
return invoke_rules(new detail::invokable_impl<decltype(inv), decltype(gt)>(std::move(inv), std::move(gt))); return invoke_rules(new detail::invokable_impl<decltype(inv), decltype(gt)>(std::move(inv), std::move(gt)));
} }
} }
}; };
...@@ -143,13 +144,13 @@ namespace cppa { ...@@ -143,13 +144,13 @@ namespace cppa {
template<typename... Types> template<typename... Types>
inline detail::invoke_rule_builder<Types...> on() inline detail::invoke_rule_builder<Types...> on()
{ {
return detail::invoke_rule_builder<Types...>(); return detail::invoke_rule_builder<Types...>();
} }
template<typename... Types, typename Arg0, typename... Args> template<typename... Types, typename Arg0, typename... Args>
inline detail::invoke_rule_builder<Types...> on(const Arg0& arg0, const Args&... args) inline detail::invoke_rule_builder<Types...> on(const Arg0& arg0, const Args&... args)
{ {
return detail::invoke_rule_builder<Types...>(arg0, args...); return detail::invoke_rule_builder<Types...>(arg0, args...);
} }
} // namespace cppa } // namespace cppa
......
...@@ -12,7 +12,7 @@ namespace cppa { ...@@ -12,7 +12,7 @@ namespace cppa {
* @brief (Thread safe) base class for reference counted objects * @brief (Thread safe) base class for reference counted objects
* with an atomic reference count. * 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 } // namespace cppa
......
...@@ -9,6 +9,9 @@ namespace cppa { ...@@ -9,6 +9,9 @@ namespace cppa {
class context; class context;
class actor_behavior; class actor_behavior;
/**
* @brief
*/
class scheduler class scheduler
{ {
...@@ -44,6 +47,10 @@ 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(); scheduler* get_scheduler();
} // namespace cppa::detail } // namespace cppa::detail
......
...@@ -22,22 +22,39 @@ ...@@ -22,22 +22,39 @@
namespace cppa { namespace detail { 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_all_extents<T>::type step1_type;
typedef typename std::remove_cv<step1_type>::type step2_type; typedef typename std::remove_cv<step1_type>::type step2_type;
static const bool value = std::is_array<T>::value 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> template<typename T>
struct chars_to_string struct chars_to_string
{ {
typedef typename util::replace_type<T, std::string, typedef typename util::replace_type<T, std::string,
std::is_same<T, const char*>, std::is_same<T, const char*>,
std::is_same<T, 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; type;
}; };
......
...@@ -10,32 +10,34 @@ namespace cppa { ...@@ -10,32 +10,34 @@ namespace cppa {
class untyped_tuple class untyped_tuple
{ {
cow_ptr<detail::abstract_tuple> m_vals; cow_ptr<detail::abstract_tuple> m_vals;
public: public:
untyped_tuple(); untyped_tuple();
template<typename Tuple> template<typename Tuple>
untyped_tuple(const Tuple& t) : m_vals(t.vals()) { } untyped_tuple(const Tuple& t) : m_vals(t.vals()) { }
inline untyped_tuple(const cow_ptr<detail::abstract_tuple>& vals) inline untyped_tuple(const cow_ptr<detail::abstract_tuple>& vals)
: m_vals(vals) : m_vals(vals)
{ {
} }
std::size_t size() const { return m_vals->size(); } 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 uniform_type_info* utype_at(std::size_t p) const { return m_vals->utype_at(p); } const void* at(size_t p) const { return m_vals->at(p); }
const util::abstract_type_list& types() const { return m_vals->types(); } const uniform_type_info* utype_at(std::size_t p) const { return m_vals->utype_at(p); }
const cow_ptr<detail::abstract_tuple>& vals() const const util::abstract_type_list& types() const { return m_vals->types(); }
{
return m_vals; const cow_ptr<detail::abstract_tuple>& vals() const
} {
return m_vals;
}
}; };
......
...@@ -26,7 +26,7 @@ namespace cppa { namespace util { ...@@ -26,7 +26,7 @@ namespace cppa { namespace util {
template<typename What, typename With, typename... IfStmt> template<typename What, typename With, typename... IfStmt>
struct replace_type struct replace_type
{ {
static const bool do_replace = disjunction<IfStmt...>::value; static constexpr bool do_replace = disjunction<IfStmt...>::value;
typedef typename detail::replace_type<do_replace, What, With>::type typedef typename detail::replace_type<do_replace, What, With>::type
type; type;
}; };
......
#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
#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
...@@ -59,8 +59,13 @@ HEADERS = cppa/actor.hpp \ ...@@ -59,8 +59,13 @@ HEADERS = cppa/actor.hpp \
cppa/util/is_comparable.hpp \ cppa/util/is_comparable.hpp \
cppa/util/is_copyable.hpp \ cppa/util/is_copyable.hpp \
cppa/util/is_one_of.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/remove_const_reference.hpp \
cppa/util/replace_type.hpp \
cppa/util/reverse_type_list.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/single_reader_queue.hpp \
cppa/util/type_at.hpp \ cppa/util/type_at.hpp \
cppa/util/type_list.hpp \ cppa/util/type_list.hpp \
...@@ -80,11 +85,13 @@ SOURCES = src/abstract_type_list.cpp \ ...@@ -80,11 +85,13 @@ SOURCES = src/abstract_type_list.cpp \
src/demangle.cpp \ src/demangle.cpp \
src/deserializer.cpp \ src/deserializer.cpp \
src/group.cpp \ src/group.cpp \
src/message.cpp \
src/mock_scheduler.cpp \ src/mock_scheduler.cpp \
src/object.cpp \ src/object.cpp \
src/primitive_variant.cpp \ src/primitive_variant.cpp \
src/scheduler.cpp \ src/scheduler.cpp \
src/serializer.cpp \ src/serializer.cpp \
src/shared_spinlock.cpp \
src/to_uniform_name.cpp \ src/to_uniform_name.cpp \
src/uniform_type_info.cpp \ src/uniform_type_info.cpp \
src/untyped_tuple.cpp src/untyped_tuple.cpp
......
#include "cppa/config.hpp"
#include <map>
#include <mutex>
#include <atomic>
#include "cppa/actor.hpp" #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 { 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; return nullptr;
} }
......
#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
#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
...@@ -101,7 +101,8 @@ class actor_ptr_type_info_impl : public util::uniform_type_info_base<actor_ptr> ...@@ -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 void serialize(const void* ptr, serializer* sink) const
{ {
sink->begin_object(name()); 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(); sink->end_object();
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "cppa/match.hpp" #include "cppa/match.hpp"
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
#include "cppa/serializer.hpp" #include "cppa/serializer.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
...@@ -37,10 +38,11 @@ ...@@ -37,10 +38,11 @@
#include "cppa/util/pt_token.hpp" #include "cppa/util/pt_token.hpp"
#include "cppa/util/enable_if.hpp" #include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp" #include "cppa/util/disable_if.hpp"
#include "cppa/util/is_iterable.hpp"
#include "cppa/util/if_else_type.hpp" #include "cppa/util/if_else_type.hpp"
#include "cppa/util/wrapped_type.hpp" #include "cppa/util/wrapped_type.hpp"
#include "cppa/util/is_primitive.hpp" #include "cppa/util/is_primitive.hpp"
#include "cppa/util/is_iterable.hpp" #include "cppa/util/uniform_type_info_base.hpp"
#include "cppa/detail/type_to_ptype.hpp" #include "cppa/detail/type_to_ptype.hpp"
#include "cppa/detail/ptype_to_type.hpp" #include "cppa/detail/ptype_to_type.hpp"
...@@ -370,21 +372,54 @@ class string_deserializer : public deserializer ...@@ -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> template<typename T>
std::string to_string(const T& what) std::string to_string(const T& what)
{ {
std::string tname = detail::to_uniform_name(typeid(T)); auto utype = uniform_typeid<T>();
auto mobj = uniform_typeid<T>(); if (!utype)
if (!mobj) throw std::logic_error(tname + " not found"); {
throw std::logic_error( detail::to_uniform_name(typeid(T))
+ " not found");
}
std::ostringstream osstr; std::ostringstream osstr;
string_serializer strs(osstr); string_serializer strs(osstr);
mobj->serialize(&what, &strs); utype->serialize(&what, &strs);
return osstr.str(); return osstr.str();
} }
std::size_t test__serialization() std::size_t test__serialization()
{ {
CPPA_TEST(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); CPPA_CHECK_EQUAL((is_iterable<int>::value), false);
// std::string is primitive and thus not identified by is_iterable // std::string is primitive and thus not identified by is_iterable
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment