Commit 1d3cce57 authored by neverlord's avatar neverlord

type system

parent d0c322ae
......@@ -64,8 +64,6 @@ src/deserializer.cpp
cppa/util/eval_type_list.hpp
cppa/util/is_legal_tuple_type.hpp
cppa/util/replace_type.hpp
cppa/util/source.hpp
cppa/util/sink.hpp
src/untyped_tuple.cpp
cppa/util/abstract_type_list.hpp
cppa/detail/serialize_tuple.hpp
......@@ -143,3 +141,5 @@ src/binary_serializer.cpp
cppa/binary_deserializer.hpp
src/binary_deserializer.cpp
src/actor.cpp
cppa/announce.hpp
src/abstract_type_list.cpp
......@@ -8,9 +8,9 @@ class actor_behavior
public:
virtual void act() = 0;
virtual void on_exit();
virtual ~actor_behavior();
virtual void on_exit();
virtual void act() = 0;
};
......
#ifndef ANNOUNCE_HPP
#define ANNOUNCE_HPP
#include <typeinfo>
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/uniform_type_info_base.hpp"
#include "cppa/detail/default_uniform_type_info_impl.hpp"
namespace cppa {
template<class C, class Parent, typename... Args>
std::pair<C Parent::*, util::uniform_type_info_base<C>*>
compound_member(C Parent::*c_ptr, const Args&... args)
{
return { c_ptr, new detail::default_uniform_type_info_impl<C>(args...) };
}
/**
* @brief Add a new type mapping to the libCPPA internal type system.
* @return <code>true</code> if @p uniform_type was added as known
* instance (mapped to @p plain_type); otherwise @c false
* is returned and @p uniform_type was deleted.
*/
bool announce(const std::type_info& tinfo, uniform_type_info* utype);
template<typename T, typename... Args>
inline bool announce(const Args&... args)
{
return announce(typeid(T),
new detail::default_uniform_type_info_impl<T>(args...));
}
} // namespace cppa
#endif // ANNOUNCE_HPP
......@@ -5,7 +5,8 @@ namespace cppa {
struct any_type
{
inline operator any_type*() { return 0; }
constexpr any_type() { }
inline operator any_type*() { return 0; }
};
inline bool operator==(const any_type&, const any_type&) { return true; }
......@@ -25,9 +26,9 @@ template<typename T>
inline bool operator!=(const any_type&, const T&) { return false; }
#ifdef __GNUC__
static any_type any_val __attribute__ ((unused));
static constexpr any_type any_val __attribute__ ((unused));
#else
static any_type any_val;
static constexpr any_type any_val;
#endif
} // namespace cppa
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 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 CPPA_HPP
#define CPPA_HPP
......@@ -17,88 +45,88 @@ namespace cppa {
template<typename F>
actor_ptr spawn(scheduling_hint hint, F fun)
{
struct fun_behavior : actor_behavior
{
F m_fun;
fun_behavior(const F& fun_arg) : m_fun(fun_arg) { }
virtual void act()
{
m_fun();
}
};
return get_scheduler()->spawn(new fun_behavior(fun), hint);
struct fun_behavior : actor_behavior
{
F m_fun;
fun_behavior(const F& fun_arg) : m_fun(fun_arg) { }
virtual void act()
{
m_fun();
}
};
return get_scheduler()->spawn(new fun_behavior(fun), hint);
}
template<typename F, typename Arg0, typename... Args>
actor_ptr spawn(scheduling_hint hint, F fun, const Arg0& arg0, const Args&... args)
{
auto arg_tuple = make_tuple(arg0, args...);
return spawn(hint, [=]() { invoke(fun, arg_tuple); });
auto arg_tuple = make_tuple(arg0, args...);
return spawn(hint, [=]() { invoke(fun, arg_tuple); });
}
template<typename F, typename... Args>
inline actor_ptr spawn(F fun, const Args&... args)
{
return spawn(scheduled, fun, args...);
return spawn(scheduled, fun, args...);
}
inline actor_ptr spawn(scheduling_hint hint, actor_behavior* ab)
{
return get_scheduler()->spawn(ab, hint);
return get_scheduler()->spawn(ab, hint);
}
inline actor_ptr spawn(actor_behavior* ab)
{
return get_scheduler()->spawn(ab, scheduled);
return get_scheduler()->spawn(ab, scheduled);
}
inline const message& receive()
{
return self()->mailbox().dequeue();
return self()->mailbox().dequeue();
}
inline void receive(invoke_rules& rules)
{
self()->mailbox().dequeue(rules);
self()->mailbox().dequeue(rules);
}
inline void receive(invoke_rules&& rules)
{
self()->mailbox().dequeue(rules);
self()->mailbox().dequeue(rules);
}
inline bool try_receive(message& msg)
{
return self()->mailbox().try_dequeue(msg);
return self()->mailbox().try_dequeue(msg);
}
inline bool try_receive(invoke_rules& rules)
{
return self()->mailbox().try_dequeue(rules);
return self()->mailbox().try_dequeue(rules);
}
inline const message& last_received()
{
return self()->mailbox().last_dequeued();
return self()->mailbox().last_dequeued();
}
template<typename Arg0, typename... Args>
void send(channel_ptr whom, const Arg0& arg0, const Args&... args)
{
if (whom) whom->enqueue(message(self(), whom, arg0, args...));
if (whom) whom->enqueue(message(self(), whom, arg0, args...));
}
template<typename Arg0, typename... Args>
void reply(const Arg0& arg0, const Args&... args)
{
context* sptr = self();
actor_ptr whom = sptr->mailbox().last_dequeued().sender();
if (whom) whom->enqueue(message(sptr, whom, arg0, args...));
context* sptr = self();
actor_ptr whom = sptr->mailbox().last_dequeued().sender();
if (whom) whom->enqueue(message(sptr, whom, arg0, args...));
}
inline void await_all_actors_done()
{
get_scheduler()->await_all_done();
get_scheduler()->await_others_done();
}
} // namespace cppa
......
......@@ -9,6 +9,8 @@
namespace cppa {
class object;
class deserializer
{
......@@ -42,6 +44,8 @@ class deserializer
};
deserializer& operator>>(deserializer& d, object& what);
} // namespace cppa
#endif // DESERIALIZER_HPP
......@@ -15,36 +15,36 @@ namespace cppa { namespace detail {
class converted_thread_context : public context
{
// mailbox implementation
detail::blocking_message_queue m_mailbox;
// mailbox implementation
detail::blocking_message_queue m_mailbox;
// guards access to m_exited, m_subscriptions and m_links
std::mutex m_mtx;
// guards access to m_exited, m_subscriptions and m_links
std::mutex m_mtx;
// true if the associated thread has finished execution
bool m_exited;
// true if the associated thread has finished execution
bool m_exited;
// manages group subscriptions
std::map<group_ptr, intrusive_ptr<group::subscription>> m_subscriptions;
// manages group subscriptions
std::map<group_ptr, intrusive_ptr<group::subscription>> m_subscriptions;
// manages actor links
std::set<actor_ptr> m_links;
// manages actor links
std::set<actor_ptr> m_links;
public:
message_queue& mailbox /*[[override]]*/ ();
message_queue& mailbox /*[[override]]*/ ();
void join /*[[override]]*/ (group_ptr& what);
void join /*[[override]]*/ (group_ptr& what);
void leave /*[[override]]*/ (const group_ptr& what);
void leave /*[[override]]*/ (const group_ptr& what);
void link /*[[override]]*/ (intrusive_ptr<actor>& other);
void link /*[[override]]*/ (intrusive_ptr<actor>& other);
void unlink /*[[override]]*/ (intrusive_ptr<actor>& other);
void unlink /*[[override]]*/ (intrusive_ptr<actor>& other);
bool remove_backlink /*[[override]]*/ (const intrusive_ptr<actor>& to);
bool remove_backlink /*[[override]]*/ (const intrusive_ptr<actor>& to);
bool establish_backlink /*[[override]]*/ (const intrusive_ptr<actor>& to);
bool establish_backlink /*[[override]]*/ (const intrusive_ptr<actor>& to);
};
......
......@@ -14,99 +14,99 @@ template<typename... Types> struct matcher;
template<typename Head, typename... Tail>
struct matcher<Head, Tail...>
{
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0)
{
auto head_uti = uniform_typeid<Head>();
if (begin != end)
{
if (*(*begin) == *head_uti)
{
if (res)
{
res->push_back(pos);
}
++begin;
++pos;
return matcher<Tail...>::match(begin, end, res, pos);
}
}
return false;
}
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0)
{
auto head_uti = uniform_typeid<Head>();
if (begin != end)
{
if (*begin == *head_uti)
{
if (res)
{
res->push_back(pos);
}
++begin;
++pos;
return matcher<Tail...>::match(begin, end, res, pos);
}
}
return false;
}
};
template<typename... Tail>
struct matcher<any_type, Tail...>
{
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0)
{
if (begin != end)
{
++begin;
++pos;
return matcher<Tail...>::match(begin, end, res, pos);
}
return false;
}
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0)
{
if (begin != end)
{
++begin;
++pos;
return matcher<Tail...>::match(begin, end, res, pos);
}
return false;
}
};
template<typename Next, typename... Tail>
struct matcher<any_type*, Next, Tail...>
{
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0)
{
bool result = false;
while (!result)
{
util::abstract_type_list::const_iterator begin_cpy = begin;
result = matcher<Next, Tail...>::match(begin_cpy,end,nullptr,pos);
if (!result)
{
++begin;
++pos;
if (begin == end) return false;
}
else if (res)
{
// one more iteration to store mappings
begin_cpy = begin;
(void) matcher<Next, Tail...>::match(begin_cpy, end, res, pos);
}
}
return result;
}
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0)
{
bool result = false;
while (!result)
{
util::abstract_type_list::const_iterator begin_cpy = begin;
result = matcher<Next, Tail...>::match(begin_cpy,end,nullptr,pos);
if (!result)
{
++begin;
++pos;
if (begin == end) return false;
}
else if (res)
{
// one more iteration to store mappings
begin_cpy = begin;
(void) matcher<Next, Tail...>::match(begin_cpy, end, res, pos);
}
}
return result;
}
};
template<>
struct matcher<any_type*>
{
static bool match(util::abstract_type_list::const_iterator&,
util::abstract_type_list::const_iterator&,
std::vector<std::size_t>* = nullptr,
std::size_t = 0)
{
return true;
}
static bool match(util::abstract_type_list::const_iterator&,
util::abstract_type_list::const_iterator&,
std::vector<std::size_t>* = nullptr,
std::size_t = 0)
{
return true;
}
};
template<>
struct matcher<>
{
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* = nullptr,
std::size_t = 0)
{
return begin == end;
}
static bool match(util::abstract_type_list::const_iterator& begin,
util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* = nullptr,
std::size_t = 0)
{
return begin == end;
}
};
} } // namespace cppa::detail
......
......@@ -10,8 +10,10 @@ class mock_scheduler : public scheduler
public:
actor_ptr spawn(actor_behavior* behavior, scheduling_hint hint);
void await_all_done();
void await_others_done();
void register_converted_context(context*);
void unregister_converted_context(context*);
actor_ptr spawn(actor_behavior*, scheduling_hint);
};
......
#ifndef PRIMITIVE_MEMBER_HPP
#define PRIMITIVE_MEMBER_HPP
#include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/primitive_type.hpp"
#include "cppa/primitive_variant.hpp"
#include "cppa/detail/type_to_ptype.hpp"
......
......@@ -116,7 +116,7 @@ struct object_caster
} // namespace detail
template<typename T>
T& get(object& obj)
T& get_ref(object& obj)
{
static_assert(util::disjunction<std::is_pointer<T>,
std::is_reference<T>>::value == false,
......@@ -128,7 +128,7 @@ template<typename T>
const T& get(const object& obj)
{
static_assert(util::disjunction<std::is_pointer<T>,
std::is_reference<T>>::value,
std::is_reference<T>>::value == false,
"T is a reference a pointer type.");
return detail::object_caster<T>::_(obj);
}
......
......@@ -2,30 +2,45 @@
#define SCHEDULER_HPP
#include "cppa/actor.hpp"
#include "cppa/context.hpp"
#include "cppa/actor_behavior.hpp"
#include "cppa/scheduling_hint.hpp"
namespace cppa {
class context;
class actor_behavior;
class scheduler
{
public:
virtual ~scheduler();
/**
* @brief Spawn a new actor that executes <code>behavior->act()</code>
* with the scheduling policy @p hint if possible.
*/
virtual actor_ptr spawn(actor_behavior* behavior,
scheduling_hint hint) = 0;
/**
* @brief Wait until all (other) actors finished execution.
*/
virtual void await_all_done() = 0;
virtual ~scheduler();
/**
* @brief Spawns a new actor that executes <code>behavior->act()</code>
* with the scheduling policy @p hint if possible.
*/
virtual actor_ptr spawn(actor_behavior* behavior,
scheduling_hint hint) = 0;
/**
* @brief Informs the scheduler about a converted context
* (a thread that acts as actor).
*/
virtual void register_converted_context(context* what) = 0;
/**
* @brief Informs the scheduler that the convertex context @p what
* finished execution.
*/
virtual void unregister_converted_context(context* what) = 0;
/**
* @brief Wait until all other actors finished execution.
* @warning This function causes a deadlock if it's called from
* more than one actor.
*/
virtual void await_others_done() = 0;
};
......
......@@ -4,6 +4,9 @@
#include <string>
#include <cstddef> // size_t
#include "cppa/uniform_type_info.hpp"
#include "cppa/detail/to_uniform_name.hpp"
namespace cppa {
// forward declaration
......@@ -36,6 +39,19 @@ class serializer
};
template<typename T>
serializer& operator<<(serializer& s, const T& what)
{
auto mtype = uniform_typeid<T>();
if (mtype == nullptr)
{
throw std::logic_error( "no uniform type info found for "
+ cppa::detail::to_uniform_name(typeid(T)));
}
mtype->serialize(&what, &s);
return s;
}
} // namespace cppa
#endif // SERIALIZER_HPP
......@@ -9,8 +9,6 @@
#include <type_traits>
#include "cppa/object.hpp"
#include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/util/comparable.hpp"
#include "cppa/util/disjunction.hpp"
......@@ -21,6 +19,8 @@
namespace cppa {
class serializer;
class deserializer;
class uniform_type_info;
const uniform_type_info* uniform_typeid(const std::type_info&);
......@@ -68,7 +68,7 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
public:
// enable copy constructor
// enable copy constructor (only)
identifier(const identifier&) = default;
// needed by cppa::detail::comparable<identifier>
......@@ -136,29 +136,6 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
return id().compare(other.id());
}
/**
* @brief Add a new type mapping to the libCPPA internal type system.
* @return <code>true</code> if @p uniform_type was added as known
* instance (mapped to @p plain_type); otherwise @c false
* is returned and @p uniform_type was deleted.
*/
// static bool announce(const std::type_info& plain_type,
// uniform_type_info* uniform_type);
/**
* auto concept value_type<typename T>
* {
* T();
* T(const T&);
* bool operator==(const T&, const T&);
* }
*/
// template<typename T,
// class SerializeFun, class DeserializeFun,
// class ToStringFun, class FromStringFun>
// static bool announce(const SerializeFun& sf, const DeserializeFun& df,
// const ToStringFun& ts, const FromStringFun& fs);
/**
* @brief Creates an object of this type.
*/
......
......@@ -26,8 +26,6 @@
#include "cppa/util/reverse_type_list.hpp"
#include "cppa/util/single_reader_queue.hpp"
#include "cppa/util/singly_linked_list.hpp"
#include "cppa/util/sink.hpp"
#include "cppa/util/source.hpp"
#include "cppa/util/type_at.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/type_list_apply.hpp"
......
......@@ -13,44 +13,44 @@ namespace cppa { namespace detail {
template<typename HeadA, typename TailA, typename HeadB, typename TailB>
struct amb_helper : util::conjunction<util::is_one_of<HeadA, HeadB, any_type>,
amb_helper<typename TailA::head_type,
typename TailA::tail_type,
typename TailB::head_type,
typename TailB::tail_type>>
amb_helper<typename TailA::head_type,
typename TailA::tail_type,
typename TailB::head_type,
typename TailB::tail_type>>
{
static_assert( !std::is_same<HeadB, any_type>::value
&& !std::is_same<HeadB, any_type*>::value,
"any_type in right hand type list");
static_assert( std::is_same<HeadB, any_type>::value == false
&& std::is_same<HeadB, any_type*>::value == false,
"any_type in right hand type list");
};
template<>
struct amb_helper<util::void_type, util::type_list<>,
util::void_type, util::type_list<>> : std::true_type
util::void_type, util::type_list<>> : std::true_type
{
};
template<typename TailA>
struct amb_helper<any_type*, TailA, util::void_type, util::type_list<>>
: amb_helper<typename TailA::head_type,
typename TailA::tail_type,
util::void_type,
util::type_list<>>
: amb_helper<typename TailA::head_type,
typename TailA::tail_type,
util::void_type,
util::type_list<>>
{
};
template<typename TailA, typename HeadB, typename TailB>
struct amb_helper<any_type*, TailA, HeadB, TailB>
: util::disjunction<amb_helper<typename TailA::head_type,
typename TailA::tail_type,
HeadB,
TailB>,
amb_helper<any_type*,
TailA,
typename TailB::head_type,
typename TailB::tail_type>>
: util::disjunction<amb_helper<typename TailA::head_type,
typename TailA::tail_type,
HeadB,
TailB>,
amb_helper<any_type*,
TailA,
typename TailB::head_type,
typename TailB::tail_type>>
{
static_assert(!std::is_same<HeadB, any_type>::value,
"any_type in right hand type list");
static_assert(std::is_same<HeadB, any_type>::value == false,
"any_type in right hand type list");
};
} } // namespace cppa::detail
......@@ -59,9 +59,9 @@ namespace cppa { namespace util {
template<typename ListA, typename ListB>
struct a_matches_b : detail::amb_helper<typename ListA::head_type,
typename ListA::tail_type,
typename ListB::head_type,
typename ListB::tail_type>
typename ListA::tail_type,
typename ListB::head_type,
typename ListB::tail_type>
{
};
......
......@@ -2,86 +2,76 @@
#define ABSTRACT_TYPE_LIST_HPP
#include <iterator>
#include "cppa/uniform_type_info.hpp"
namespace cppa { class serializer; }
// forward declaration
namespace cppa { class uniform_type_info; }
namespace cppa { namespace util {
struct abstract_type_list
{
class const_iterator : public std::iterator<std::bidirectional_iterator_tag,
const uniform_type_info*>
{
class const_iterator : public std::iterator<std::bidirectional_iterator_tag,
const uniform_type_info*>
{
const uniform_type_info* const* p;
const uniform_type_info* const* p;
public:
public:
inline const_iterator(const uniform_type_info* const* x = nullptr) : p(x) { }
inline const_iterator(const uniform_type_info* const* x = 0) : p(x) { }
const_iterator(const_iterator&&) = default;
const_iterator(const const_iterator&) = default;
const_iterator(const const_iterator&) = default;
const_iterator& operator=(const_iterator&&) = default;
const_iterator& operator=(const const_iterator&) = default;
const_iterator& operator=(const const_iterator&) = default;
inline bool operator==(const const_iterator& other) const
{
return p == other.p;
}
inline bool operator==(const const_iterator& other) const
{
return p == other.p;
}
inline bool operator!=(const const_iterator& other) const
{
return p != other.p;
}
inline bool operator!=(const const_iterator& other) const
{
return p != other.p;
}
inline const uniform_type_info* operator*()
{
return *p;
}
inline const uniform_type_info& operator*() const
{
return *(*p);
}
inline const uniform_type_info* const* operator->()
{
return p;
}
inline const uniform_type_info* operator->() const
{
return *p;
}
inline const_iterator& operator++()
{
++p;
return *this;
}
inline const_iterator& operator++()
{
++p;
return *this;
}
inline const_iterator operator++(int)
{
const_iterator tmp(*this);
operator++();
return tmp;
}
const_iterator operator++(int);
inline const_iterator& operator--()
{
--p;
return *this;
}
inline const_iterator& operator--()
{
--p;
return *this;
}
inline const_iterator operator--(int)
{
const_iterator tmp(*this);
operator--();
return tmp;
}
const_iterator operator--(int);
};
};
virtual abstract_type_list* copy() const = 0;
virtual ~abstract_type_list();
virtual const_iterator begin() const = 0;
virtual abstract_type_list* copy() const = 0;
virtual const_iterator end() const = 0;
virtual const_iterator begin() const = 0;
virtual const uniform_type_info* at(std::size_t pos) const = 0;
virtual const_iterator end() const = 0;
virtual const uniform_type_info* at(std::size_t pos) const = 0;
};
......
......@@ -13,89 +13,88 @@ template<std::size_t N, template<typename...> class Tuple, typename... Types>
const typename util::type_at<N, util::type_list<Types...>>::type&
do_get(const Tuple<Types...>& t)
{
return ::cppa::get<N, Types...>(t);
return ::cppa::get<N, Types...>(t);
}
template<std::size_t N, typename LhsTuple, typename RhsTuple>
struct cmp_helper
{
inline static bool cmp(const LhsTuple& lhs, const RhsTuple& rhs)
{
return do_get<N>(lhs) == do_get<N>(rhs)
&& cmp_helper<N-1, LhsTuple, RhsTuple>::cmp(lhs, rhs);
}
inline static bool cmp(const LhsTuple& lhs, const RhsTuple& rhs)
{
return do_get<N>(lhs) == do_get<N>(rhs)
&& cmp_helper<N-1, LhsTuple, RhsTuple>::cmp(lhs, rhs);
}
};
template<typename LhsTuple, typename RhsTuple>
struct cmp_helper<0, LhsTuple, RhsTuple>
{
inline static bool cmp(const LhsTuple& lhs, const RhsTuple& rhs)
{
return do_get<0>(lhs) == do_get<0>(rhs);
}
inline static bool cmp(const LhsTuple& lhs, const RhsTuple& rhs)
{
return do_get<0>(lhs) == do_get<0>(rhs);
}
};
template<bool ALessB, std::size_t A, std::size_t B>
struct min_impl
{
static const std::size_t value = A;
static const std::size_t value = A;
};
template<std::size_t A, std::size_t B>
struct min_impl<false, A, B>
{
static const std::size_t value = B;
static const std::size_t value = B;
};
template<std::size_t A, std::size_t B>
struct min_
{
static const std::size_t value = min_impl<(A < B), A, B>::value;
static const std::size_t value = min_impl<(A < B), A, B>::value;
};
} } // namespace cppa::detail
namespace cppa { namespace util {
template<template<typename...> class LhsTuple, typename... LhsTypes,
template<typename...> class RhsTuple, typename... RhsTypes>
template<typename...> class RhsTuple, typename... RhsTypes>
bool compare_tuples(const LhsTuple<LhsTypes...>& lhs,
const RhsTuple<RhsTypes...>& rhs)
const RhsTuple<RhsTypes...>& rhs)
{
static_assert( LhsTuple<LhsTypes...>::type_list_size
== RhsTuple<RhsTypes...>::type_list_size,
"could not compare tuples of different size");
static_assert(util::eval_type_lists<util::type_list<LhsTypes...>,
util::type_list<RhsTypes...>,
util::is_comparable>::value,
"types of lhs are not comparable to the types of rhs");
return detail::cmp_helper<(LhsTuple<LhsTypes...>::type_list_size - 1),
LhsTuple<LhsTypes...>,
RhsTuple<RhsTypes...>>::cmp(lhs, rhs);
static_assert( LhsTuple<LhsTypes...>::type_list_size
== RhsTuple<RhsTypes...>::type_list_size,
"could not compare tuples of different size");
static_assert(util::eval_type_lists<util::type_list<LhsTypes...>,
util::type_list<RhsTypes...>,
util::is_comparable>::value,
"types of lhs are not comparable to the types of rhs");
return detail::cmp_helper<(LhsTuple<LhsTypes...>::type_list_size - 1),
LhsTuple<LhsTypes...>,
RhsTuple<RhsTypes...>>::cmp(lhs, rhs);
}
template<template<typename...> class LhsTuple, typename... LhsTypes,
template<typename...> class RhsTuple, typename... RhsTypes>
template<typename...> class RhsTuple, typename... RhsTypes>
bool compare_first_elements(const LhsTuple<LhsTypes...>& lhs,
const RhsTuple<RhsTypes...>& rhs)
const RhsTuple<RhsTypes...>& rhs)
{
typedef util::type_list<LhsTypes...> lhs_types;
typedef util::type_list<RhsTypes...> rhs_types;
static_assert(util::eval_first_n<detail::min_<lhs_types::type_list_size,
rhs_types::type_list_size>
::value,
lhs_types,
rhs_types,
util::is_comparable>::value,
"types of lhs are not comparable to the types of rhs");
return detail::cmp_helper<(detail::min_<lhs_types::type_list_size,
rhs_types::type_list_size>
::value - 1),
LhsTuple<LhsTypes...>,
RhsTuple<RhsTypes...>>::cmp(lhs, rhs);
typedef util::type_list<LhsTypes...> lhs_types;
typedef util::type_list<RhsTypes...> rhs_types;
static_assert(util::eval_first_n<detail::min_<lhs_types::type_list_size,
rhs_types::type_list_size>
::value,
lhs_types,
rhs_types,
util::is_comparable>::value,
"types of lhs are not comparable to the types of rhs");
return detail::cmp_helper<(detail::min_<lhs_types::type_list_size,
rhs_types::type_list_size>
::value - 1),
LhsTuple<LhsTypes...>,
RhsTuple<RhsTypes...>>::cmp(lhs, rhs);
}
} } // namespace cppa::util
......
......@@ -11,7 +11,7 @@ struct concat_type_lists;
template<typename... ListATypes, typename... ListBTypes>
struct concat_type_lists<util::type_list<ListATypes...>, util::type_list<ListBTypes...>>
{
typedef util::type_list<ListATypes..., ListBTypes...> type;
typedef util::type_list<ListATypes..., ListBTypes...> type;
};
} } // namespace cppa::util
......
......@@ -10,7 +10,7 @@ struct conjunction;
template<typename Head, typename... Tail>
struct conjunction<Head, Tail...>
: std::integral_constant<bool, Head::value && conjunction<Tail...>::value>
: std::integral_constant<bool, Head::value && conjunction<Tail...>::value>
{
};
......
......@@ -12,21 +12,21 @@ struct detach_;
template<bool HasCpyMemFun>
struct detach_<true, HasCpyMemFun>
{
template<typename T>
inline static T* cpy(const T* what)
{
return new T(*what);
}
template<typename T>
inline static T* cpy(const T* what)
{
return new T(*what);
}
};
template<>
struct detach_<false, true>
{
template<typename T>
inline static T* cpy(const T* what)
{
return what->copy();
}
template<typename T>
inline static T* cpy(const T* what)
{
return what->copy();
}
};
} } // namespace cppa::detail
......@@ -36,8 +36,8 @@ namespace cppa { namespace util {
template<typename T>
inline T* detach(const T* what)
{
return detail::detach_<is_copyable<T>::value,
has_copy_member_fun<T>::value>::cpy(what);
return detail::detach_<is_copyable<T>::value,
has_copy_member_fun<T>::value>::cpy(what);
}
} } // namespace cppa::util
......
......@@ -10,7 +10,7 @@ struct disjunction;
template<typename Head, typename... Tail>
struct disjunction<Head, Tail...>
: std::integral_constant<bool, Head::value || disjunction<Tail...>::value>
: std::integral_constant<bool, Head::value || disjunction<Tail...>::value>
{
};
......
......@@ -10,21 +10,21 @@
namespace cppa { namespace util {
template <std::size_t N,
class ListA, class ListB,
template <typename, typename> class What>
class ListA, class ListB,
template <typename, typename> class What>
struct eval_first_n;
template <std::size_t N, typename... TypesA, typename... TypesB,
template <typename, typename> class What>
template <typename, typename> class What>
struct eval_first_n<N, type_list<TypesA...>, type_list<TypesB...>, What>
{
typedef type_list<TypesA...> first_list;
typedef type_list<TypesB...> second_list;
typedef type_list<TypesA...> first_list;
typedef type_list<TypesB...> second_list;
typedef typename first_n<N, first_list>::type slist_a;
typedef typename first_n<N, second_list>::type slist_b;
typedef typename first_n<N, first_list>::type slist_a;
typedef typename first_n<N, second_list>::type slist_b;
static const bool value = eval_type_lists<slist_a, slist_b, What>::value;
static const bool value = eval_type_lists<slist_a, slist_b, What>::value;
};
} } // namespace cppa::util
......
......@@ -12,18 +12,18 @@ namespace cppa { namespace util {
template <class List, template <typename> class What>
struct eval_type_list
{
typedef typename List::head_type head_type;
typedef typename List::tail_type tail_type;
typedef typename List::head_type head_type;
typedef typename List::tail_type tail_type;
static const bool value =
What<head_type>::value
&& eval_type_list<tail_type, What>::value;
static const bool value =
What<head_type>::value
&& eval_type_list<tail_type, What>::value;
};
template <template <typename> class What>
struct eval_type_list<type_list<>, What>
{
static const bool value = true;
static const bool value = true;
};
} } // namespace cppa::util
......
......@@ -11,28 +11,28 @@ namespace cppa { namespace util {
* @brief Apply @p What to each element of @p List.
*/
template <class ListA, class ListB,
template <typename, typename> class What>
template <typename, typename> class What>
struct eval_type_lists
{
typedef typename ListA::head_type head_type_a;
typedef typename ListA::tail_type tail_type_a;
typedef typename ListA::head_type head_type_a;
typedef typename ListA::tail_type tail_type_a;
typedef typename ListB::head_type head_type_b;
typedef typename ListB::tail_type tail_type_b;
typedef typename ListB::head_type head_type_b;
typedef typename ListB::tail_type tail_type_b;
static const bool value =
!std::is_same<head_type_a, void_type>::value
&& !std::is_same<head_type_b, void_type>::value
&& What<head_type_a, head_type_b>::value
&& eval_type_lists<tail_type_a, tail_type_b, What>::value;
static const bool value =
!std::is_same<head_type_a, void_type>::value
&& !std::is_same<head_type_b, void_type>::value
&& What<head_type_a, head_type_b>::value
&& eval_type_lists<tail_type_a, tail_type_b, What>::value;
};
template <template <typename, typename> class What>
struct eval_type_lists<type_list<>, type_list<>, What>
{
static const bool value = true;
static const bool value = true;
};
} } // namespace cppa::util
......
......@@ -11,25 +11,25 @@ struct filter_type_list;
template<typename Needle, typename... Tail>
struct filter_type_list<Needle, util::type_list<Needle, Tail...>>
{
typedef typename filter_type_list<Needle, util::type_list<Tail...>>::type type;
typedef typename filter_type_list<Needle, util::type_list<Tail...>>::type type;
};
template<typename Needle, typename... Tail>
struct filter_type_list<Needle, util::type_list<Needle*, Tail...>>
{
typedef typename filter_type_list<Needle, util::type_list<Tail...>>::type type;
typedef typename filter_type_list<Needle, util::type_list<Tail...>>::type type;
};
template<typename Needle, typename Head, typename... Tail>
struct filter_type_list<Needle, util::type_list<Head, Tail...>>
{
typedef typename concat_type_lists<util::type_list<Head>, typename filter_type_list<Needle, util::type_list<Tail...>>::type>::type type;
typedef typename concat_type_lists<util::type_list<Head>, typename filter_type_list<Needle, util::type_list<Tail...>>::type>::type type;
};
template<typename Needle>
struct filter_type_list<Needle, util::type_list<>>
{
typedef util::type_list<> type;
typedef util::type_list<> type;
};
} } // namespace cppa::util
......
......@@ -13,35 +13,35 @@ namespace cppa { namespace detail {
template<bool Stmt, typename IfType, typename ElseType>
struct if_t
{
typedef ElseType type;
typedef ElseType type;
};
template<typename IfType, typename ElseType>
struct if_t<true, IfType, ElseType>
{
typedef IfType type;
typedef IfType type;
};
template<std::size_t N, typename List>
struct n_
{
typedef typename util::type_at<N - 1, List>::type head_type;
typedef typename util::type_at<N - 1, List>::type head_type;
typedef typename if_t<std::is_same<util::void_type, head_type>::value,
util::type_list<>,
util::type_list<head_type>>::type
head_list;
typedef typename if_t<std::is_same<util::void_type, head_type>::value,
util::type_list<>,
util::type_list<head_type>>::type
head_list;
typedef typename n_<N - 1, List>::type tail_list;
typedef typename n_<N - 1, List>::type tail_list;
typedef typename util::concat_type_lists<tail_list, head_list>::type type;
typedef typename util::concat_type_lists<tail_list, head_list>::type type;
};
template<typename List>
struct n_<0, List>
{
typedef util::type_list<> type;
typedef util::type_list<> type;
};
} } // namespace cppa::detail
......@@ -54,7 +54,7 @@ struct first_n;
template<std::size_t N, typename... ListTypes>
struct first_n<N, util::type_list<ListTypes...>>
{
typedef typename detail::n_<N, util::type_list<ListTypes...>>::type type;
typedef typename detail::n_<N, util::type_list<ListTypes...>>::type type;
};
} } // namespace cppa::util
......
......@@ -9,20 +9,20 @@ template<typename T>
class has_copy_member_fun
{
template<typename A>
static bool hc_help_fun(const A* arg0, decltype(arg0->copy()) = 0)
{
return true;
}
template<typename A>
static bool hc_help_fun(const A* arg0, decltype(arg0->copy()) = 0)
{
return true;
}
template<typename A>
static void hc_help_fun(const A*, void* = 0) { }
template<typename A>
static void hc_help_fun(const A*, void* = 0) { }
typedef decltype(hc_help_fun((T*) 0, (T*) 0)) result_type;
typedef decltype(hc_help_fun((T*) 0, (T*) 0)) result_type;
public:
static const bool value = std::is_same<bool, result_type>::value;
static const bool value = std::is_same<bool, result_type>::value;
};
......
......@@ -9,32 +9,32 @@ template<typename T1, typename T2>
class is_comparable
{
// SFINAE: If you pass a "bool*" as third argument, then
// decltype(cmp_help_fun(...)) is bool if there's an
// operator==(A,B) because
// cmp_help_fun(A*, B*, bool*) is a better match than
// cmp_help_fun(A*, B*, void*). If there's no operator==(A,B)
// available, then cmp_help_fun(A*, B*, void*) is the only
// candidate and thus decltype(cmp_help_fun(...)) is void.
template<typename A, typename B>
static bool cmp_help_fun(const A* arg0, const B* arg1,
decltype(*arg0 == *arg1)* = nullptr)
{
return true;
}
template<typename A, typename B>
static void cmp_help_fun(const A*, const B*, void* = nullptr) { }
typedef decltype(cmp_help_fun(static_cast<T1*>(nullptr),
static_cast<T2*>(nullptr),
static_cast<bool*>(nullptr)))
result_type;
// SFINAE: If you pass a "bool*" as third argument, then
// decltype(cmp_help_fun(...)) is bool if there's an
// operator==(A,B) because
// cmp_help_fun(A*, B*, bool*) is a better match than
// cmp_help_fun(A*, B*, void*). If there's no operator==(A,B)
// available, then cmp_help_fun(A*, B*, void*) is the only
// candidate and thus decltype(cmp_help_fun(...)) is void.
template<typename A, typename B>
static bool cmp_help_fun(const A* arg0, const B* arg1,
decltype(*arg0 == *arg1)* = nullptr)
{
return true;
}
template<typename A, typename B>
static void cmp_help_fun(const A*, const B*, void* = nullptr) { }
typedef decltype(cmp_help_fun(static_cast<T1*>(nullptr),
static_cast<T2*>(nullptr),
static_cast<bool*>(nullptr)))
result_type;
public:
static const bool value = std::is_same<bool, result_type>::value;
static const bool value = std::is_same<bool, result_type>::value;
};
......
......@@ -9,22 +9,22 @@ template<bool IsAbstract, typename T>
class is_copyable_
{
template<typename A>
static bool cpy_help_fun(const A* arg0, decltype(new A(*arg0)) = nullptr)
{
return true;
}
template<typename A>
static bool cpy_help_fun(const A* arg0, decltype(new A(*arg0)) = nullptr)
{
return true;
}
template<typename A>
static void cpy_help_fun(const A*, void* = nullptr) { }
template<typename A>
static void cpy_help_fun(const A*, void* = nullptr) { }
typedef decltype(cpy_help_fun(static_cast<T*>(nullptr),
static_cast<T*>(nullptr)))
result_type;
typedef decltype(cpy_help_fun(static_cast<T*>(nullptr),
static_cast<T*>(nullptr)))
result_type;
public:
static const bool value = std::is_same<bool, result_type>::value;
static const bool value = std::is_same<bool, result_type>::value;
};
......@@ -34,7 +34,7 @@ class is_copyable_<true, T>
public:
static const bool value = false;
static const bool value = false;
};
......@@ -48,7 +48,7 @@ struct is_copyable
public:
static const bool value = detail::is_copyable_<std::is_abstract<T>::value, T>::value;
static const bool value = detail::is_copyable_<std::is_abstract<T>::value, T>::value;
};
......
......@@ -8,8 +8,8 @@ namespace cppa { namespace util {
template<typename T>
struct is_legal_tuple_type
{
static const bool value = !std::is_pointer<T>::value
&& !std::is_reference<T>::value;
static const bool value = std::is_pointer<T>::value == false
&& std::is_reference<T>::value == false;
};
} } // namespace cppa::util
......
......@@ -11,7 +11,7 @@ struct is_one_of;
template<typename T, typename X, typename... Types>
struct is_one_of<T, X, Types...>
: disjunction<std::is_same<T, X>, is_one_of<T, Types...>>
: disjunction<std::is_same<T, X>, is_one_of<T, Types...>>
{
};
......
......@@ -6,13 +6,13 @@ namespace cppa { namespace util {
template<typename T>
struct remove_const_reference
{
typedef T type;
typedef T type;
};
template<typename T>
struct remove_const_reference<const T&>
{
typedef T type;
typedef T type;
};
} } // namespace cppa::util
......
......@@ -10,13 +10,13 @@ namespace cppa { namespace detail {
template<bool DoReplace, typename T, typename ReplaceType>
struct replace_type
{
typedef T type;
typedef T type;
};
template<typename T, typename ReplaceType>
struct replace_type<true, T, ReplaceType>
{
typedef ReplaceType type;
typedef ReplaceType type;
};
} } // namespace cppa::detail
......@@ -26,9 +26,9 @@ namespace cppa { namespace util {
template<typename What, typename With, typename... IfStmt>
struct replace_type
{
static const bool do_replace = disjunction<IfStmt...>::value;
typedef typename detail::replace_type<do_replace, What, With>::type
type;
static const bool do_replace = disjunction<IfStmt...>::value;
typedef typename detail::replace_type<do_replace, What, With>::type
type;
};
} } // namespace cppa::util
......
......@@ -12,15 +12,15 @@ struct reverse_type_list;
template<typename HeadA, typename... TailA, typename... ListB>
struct reverse_type_list<type_list<HeadA, TailA...>, type_list<ListB...>>
{
typedef typename reverse_type_list<type_list<TailA...>,
type_list<HeadA, ListB...>>::type
type;
typedef typename reverse_type_list<type_list<TailA...>,
type_list<HeadA, ListB...>>::type
type;
};
template<typename... Types>
struct reverse_type_list<type_list<>, type_list<Types...>>
{
typedef type_list<Types...> type;
typedef type_list<Types...> type;
};
} } // namespace cppa::util
......
......@@ -13,158 +13,158 @@ template<typename T>
class single_reader_queue
{
typedef boost::unique_lock<boost::mutex> lock_type;
typedef boost::unique_lock<boost::mutex> lock_type;
public:
typedef T element_type;
/**
* @warning call only from the reader (owner)
*/
element_type* pop()
{
wait_for_data();
element_type* result = take_head();
return result;
}
/**
* @warning call only from the reader (owner)
*/
element_type* try_pop()
{
return take_head();
}
/**
* @warning call only from the reader (owner)
*/
void push_front(element_type* element)
{
element->next = m_head;
m_head = element;
}
/**
* @warning call only from the reader (owner)
*/
void push_front(element_type* first, element_type* last)
{
last->next = m_head;
m_head = first;
}
/**
* @warning call only from the reader (owner)
*/
template<typename List>
void push_front(List&& list)
{
if (!list.empty())
{
auto p = list.take();
if (p.first)
{
push_front(p.first, p.second);
}
}
}
void push_back(element_type* new_element)
{
element_type* e = m_tail.load();
for (;;)
{
new_element->next = e;
if (!e)
{
lock_type guard(m_mtx);
if (m_tail.compare_exchange_weak(e, new_element))
{
m_cv.notify_one();
return;
}
}
else
{
if (m_tail.compare_exchange_weak(e, new_element))
{
return;
}
}
}
}
/**
* @warning call only from the reader (owner)
*/
bool empty()
{
return !m_head && !(m_tail.load());
}
single_reader_queue() : m_tail(0), m_head(0) { }
typedef T element_type;
/**
* @warning call only from the reader (owner)
*/
element_type* pop()
{
wait_for_data();
element_type* result = take_head();
return result;
}
/**
* @warning call only from the reader (owner)
*/
element_type* try_pop()
{
return take_head();
}
/**
* @warning call only from the reader (owner)
*/
void push_front(element_type* element)
{
element->next = m_head;
m_head = element;
}
/**
* @warning call only from the reader (owner)
*/
void push_front(element_type* first, element_type* last)
{
last->next = m_head;
m_head = first;
}
/**
* @warning call only from the reader (owner)
*/
template<typename List>
void push_front(List&& list)
{
if (!list.empty())
{
auto p = list.take();
if (p.first)
{
push_front(p.first, p.second);
}
}
}
void push_back(element_type* new_element)
{
element_type* e = m_tail.load();
for (;;)
{
new_element->next = e;
if (!e)
{
lock_type guard(m_mtx);
if (m_tail.compare_exchange_weak(e, new_element))
{
m_cv.notify_one();
return;
}
}
else
{
if (m_tail.compare_exchange_weak(e, new_element))
{
return;
}
}
}
}
/**
* @warning call only from the reader (owner)
*/
bool empty()
{
return !m_head && !(m_tail.load());
}
single_reader_queue() : m_tail(0), m_head(0) { }
private:
// exposed to "outside" access
std::atomic<element_type*> m_tail;
// accessed only by the owner
element_type* m_head;
// locked on enqueue/dequeue operations to/from an empty list
boost::mutex m_mtx;
boost::condition_variable m_cv;
void wait_for_data()
{
if (!m_head && !(m_tail.load()))
{
lock_type guard(m_mtx);
while (!(m_tail.load())) m_cv.wait(guard);
}
}
// atomically set public_tail to nullptr and enqueue all
bool fetch_new_data()
{
element_type* e = m_tail.load();
while (e)
{
if (m_tail.compare_exchange_weak(e, 0))
{
// public_tail (e) has LIFO order,
// but private_head requires FIFO order
while (e)
{
// next iteration element
element_type* next = e->next;
// enqueue e to private_head
e->next = m_head;
m_head = e;
// next iteration
e = next;
}
return true;
}
// next iteration
}
// !public_tail
return false;
}
element_type* take_head()
{
if (m_head || fetch_new_data())
{
element_type* result = m_head;
m_head = result->next;
return result;
}
return 0;
}
// exposed to "outside" access
std::atomic<element_type*> m_tail;
// accessed only by the owner
element_type* m_head;
// locked on enqueue/dequeue operations to/from an empty list
boost::mutex m_mtx;
boost::condition_variable m_cv;
void wait_for_data()
{
if (!m_head && !(m_tail.load()))
{
lock_type guard(m_mtx);
while (!(m_tail.load())) m_cv.wait(guard);
}
}
// atomically set public_tail to nullptr and enqueue all
bool fetch_new_data()
{
element_type* e = m_tail.load();
while (e)
{
if (m_tail.compare_exchange_weak(e, 0))
{
// public_tail (e) has LIFO order,
// but private_head requires FIFO order
while (e)
{
// next iteration element
element_type* next = e->next;
// enqueue e to private_head
e->next = m_head;
m_head = e;
// next iteration
e = next;
}
return true;
}
// next iteration
}
// !public_tail
return false;
}
element_type* take_head()
{
if (m_head || fetch_new_data())
{
element_type* result = m_head;
m_head = result->next;
return result;
}
return 0;
}
};
......
......@@ -9,48 +9,48 @@ template<typename T>
class singly_linked_list
{
T* m_head;
T* m_tail;
T* m_head;
T* m_tail;
public:
typedef T element_type;
singly_linked_list() : m_head(0), m_tail(0) { }
~singly_linked_list()
{
while (m_head)
{
T* next = m_head->next;
delete m_head;
m_head = next;
}
}
inline bool empty() const { return m_head == 0; }
void push_back(element_type* what)
{
what->next = 0;
if (m_tail)
{
m_tail->next = what;
m_tail = what;
}
else
{
m_head = m_tail = what;
}
}
std::pair<element_type*, element_type*> take()
{
element_type* first = m_head;
element_type* last = m_tail;
m_head = m_tail = 0;
return { first, last };
}
typedef T element_type;
singly_linked_list() : m_head(0), m_tail(0) { }
~singly_linked_list()
{
while (m_head)
{
T* next = m_head->next;
delete m_head;
m_head = next;
}
}
inline bool empty() const { return m_head == 0; }
void push_back(element_type* what)
{
what->next = 0;
if (m_tail)
{
m_tail->next = what;
m_tail = what;
}
else
{
m_head = m_tail = what;
}
}
std::pair<element_type*, element_type*> take()
{
element_type* first = m_head;
element_type* last = m_tail;
m_head = m_tail = 0;
return { first, last };
}
};
......
#ifndef SINK_HPP
#define SINK_HPP
#include <cstddef>
#include "cppa/ref_counted.hpp"
namespace cppa { namespace util {
struct sink : public virtual ref_counted
{
virtual void write(std::size_t buf_size, const void* buf) = 0;
virtual void flush() = 0;
};
} } // namespace cppa::util
#endif // SINK_HPP
#ifndef SOURCE_HPP
#define SOURCE_HPP
#include <cstddef>
#include "cppa/ref_counted.hpp"
namespace cppa { namespace util {
struct source : public virtual ref_counted
{
virtual std::size_t read_some(std::size_t buf_size, void* buf) = 0;
virtual void read(std::size_t buf_size, void* buf) = 0;
};
} } // namespace cppa::util
#endif // SOURCE_HPP
......@@ -11,13 +11,13 @@ namespace cppa { namespace util {
template<std::size_t N, typename TypeList>
struct type_at
{
typedef typename type_at<N-1, typename TypeList::tail_type>::type type;
typedef typename type_at<N-1, typename TypeList::tail_type>::type type;
};
template<typename TypeList>
struct type_at<0, TypeList>
{
typedef typename TypeList::head_type type;
typedef typename TypeList::head_type type;
};
} } // namespace cppa::util
......
......@@ -3,7 +3,6 @@
#include <typeinfo>
#include "cppa/any_type.hpp"
//#include "cppa/uniform_type_info.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/abstract_type_list.hpp"
......@@ -38,7 +37,10 @@ struct type_list<Head, Tail...> : abstract_type_list
static const std::size_t type_list_size = tail_type::type_list_size + 1;
type_list() { init<type_list>(m_arr); }
type_list()
{
init<type_list>(m_arr);
}
virtual const_iterator begin() const
{
......@@ -69,14 +71,6 @@ struct type_list<Head, Tail...> : abstract_type_list
++what;
init<typename TypeList::tail_type>(what);
}
/*
what[0] = &uniform_type_info<typename TypeList::head_type>();
if (TypeList::type_list_size > 1)
{
++what;
init<typename TypeList::tail_type>(what);
}
*/
}
private:
......
......@@ -12,17 +12,17 @@ namespace cppa { namespace util {
template <typename List, template <typename> class What>
struct type_list_apply
{
typedef typename What<typename List::head_type>::type head_type;
typedef typename concat_type_lists<
type_list<head_type>,
typename type_list_apply<typename List::tail_type, What>::type>::type
type;
typedef typename What<typename List::head_type>::type head_type;
typedef typename concat_type_lists<
type_list<head_type>,
typename type_list_apply<typename List::tail_type, What>::type>::type
type;
};
template<template <typename> class What>
struct type_list_apply<type_list<>, What>
{
typedef type_list<> type;
typedef type_list<> type;
};
} } // namespace cppa::util
......
......@@ -9,8 +9,8 @@ namespace cppa { namespace util {
template<typename List>
struct type_list_pop_back
{
typedef typename reverse_type_list<List>::type rlist;
typedef typename reverse_type_list<typename rlist::tail_type>::type type;
typedef typename reverse_type_list<List>::type rlist;
typedef typename reverse_type_list<typename rlist::tail_type>::type type;
};
} } // namespace cppa::util
......
......@@ -8,8 +8,8 @@ template<typename... Types> struct type_list;
struct void_type
{
typedef void_type head_type;
typedef type_list<> tail_type;
typedef void_type head_type;
typedef type_list<> tail_type;
};
inline bool operator==(const void_type&, const void_type&) { return true; }
......
......@@ -68,7 +68,8 @@ HEADERS = cppa/actor.hpp \
cppa/util/type_list_pop_back.hpp \
cppa/util/void_type.hpp
SOURCES = src/actor.cpp \
SOURCES = src/abstract_type_list.cpp \
src/actor.cpp \
src/actor_behavior.cpp \
src/binary_deserializer.cpp \
src/binary_serializer.cpp \
......
#include "cppa/util/abstract_type_list.hpp"
namespace cppa { namespace util {
abstract_type_list::~abstract_type_list()
{
}
abstract_type_list::const_iterator
abstract_type_list::const_iterator::operator++(int)
{
const_iterator tmp(*this);
operator++();
return tmp;
}
abstract_type_list::const_iterator
abstract_type_list::const_iterator::operator--(int)
{
const_iterator tmp(*this);
operator--();
return tmp;
}
} } // namespace cppa::util
......@@ -2,6 +2,12 @@
namespace cppa {
void actor_behavior::on_exit() { }
actor_behavior::~actor_behavior()
{
}
void actor_behavior::on_exit()
{
}
} // namespace cppa
......@@ -5,11 +5,16 @@
#include <boost/thread.hpp>
#include "cppa/scheduler.hpp"
namespace {
void cleanup_fun(cppa::context* what)
{
if (what && !what->deref()) delete what;
if (what && !what->deref())
{
delete what;
}
}
boost::thread_specific_ptr<cppa::context> m_this_context(cleanup_fun);
......@@ -20,30 +25,31 @@ namespace cppa {
void context::enqueue(const message& msg)
{
mailbox().enqueue(msg);
mailbox().enqueue(msg);
}
context* self()
{
context* result = m_this_context.get();
if (!result)
{
result = new detail::converted_thread_context;
result->ref();
m_this_context.reset(result);
}
return result;
context* result = m_this_context.get();
if (!result)
{
result = new detail::converted_thread_context;
result->ref();
get_scheduler()->register_converted_context(result);
m_this_context.reset(result);
}
return result;
}
void set_self(context* ctx)
{
if (ctx) ctx->ref();
context* old = m_this_context.get();
m_this_context.reset(ctx);
if (old)
{
cleanup_fun(ctx);
}
if (ctx) ctx->ref();
context* old = m_this_context.get();
m_this_context.reset(ctx);
if (old)
{
cleanup_fun(ctx);
}
}
} // namespace cppa
#include <string>
#include "cppa/object.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/detail/to_uniform_name.hpp"
namespace cppa {
......@@ -6,4 +11,16 @@ deserializer::~deserializer()
{
}
deserializer& operator>>(deserializer& d, object& what)
{
std::string tname = d.peek_object();
auto mtype = uniform_type_info::by_uniform_name(tname);
if (mtype == nullptr)
{
throw std::logic_error("no uniform type info found for " + tname);
}
what = std::move(mtype->deserialize(&d));
return d;
}
} // namespace cppa
......@@ -10,10 +10,10 @@
#include "cppa/message.hpp"
#include "cppa/context.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/actor_behavior.hpp"
#include "cppa/detail/mock_scheduler.hpp"
#include "cppa/detail/converted_thread_context.hpp"
namespace {
......@@ -23,23 +23,21 @@ boost::mutex m_ra_mtx;
boost::condition_variable m_ra_cv;
void run_actor(cppa::intrusive_ptr<cppa::context> m_self,
cppa::actor_behavior* behavior)
cppa::actor_behavior* behavior)
{
cppa::set_self(m_self.get());
if (behavior)
{
try
{
behavior->act();
}
catch(...) { }
behavior->on_exit();
}
if (--m_running_actors == 0)
{
boost::mutex::scoped_lock lock(m_ra_mtx);
m_ra_cv.notify_all();
}
cppa::set_self(m_self.get());
if (behavior)
{
try { behavior->act(); }
catch(...) { }
try { behavior->on_exit(); }
catch(...) { }
}
if (--m_running_actors <= 1)
{
boost::mutex::scoped_lock lock(m_ra_mtx);
m_ra_cv.notify_all();
}
}
} // namespace <anonymous>
......@@ -48,19 +46,33 @@ namespace cppa { namespace detail {
actor_ptr mock_scheduler::spawn(actor_behavior* ab, scheduling_hint)
{
++m_running_actors;
intrusive_ptr<context> ctx(new detail::converted_thread_context);
boost::thread(run_actor, ctx, ab).detach();
return ctx;
++m_running_actors;
intrusive_ptr<context> ctx(new detail::converted_thread_context);
boost::thread(run_actor, ctx, ab).detach();
return ctx;
}
void mock_scheduler::register_converted_context(context*)
{
++m_running_actors;
}
void mock_scheduler::unregister_converted_context(context*)
{
if (--m_running_actors <= 1)
{
boost::mutex::scoped_lock lock(m_ra_mtx);
m_ra_cv.notify_all();
}
}
void mock_scheduler::await_all_done()
void mock_scheduler::await_others_done()
{
boost::mutex::scoped_lock lock(m_ra_mtx);
while (m_running_actors.load() > 0)
{
m_ra_cv.wait(lock);
}
boost::mutex::scoped_lock lock(m_ra_mtx);
while (m_running_actors.load() > 1)
{
m_ra_cv.wait(lock);
}
}
} } // namespace detail
......@@ -11,6 +11,7 @@
#include "cppa/config.hpp"
#include "cppa/actor.hpp"
#include "cppa/announce.hpp"
#include "cppa/any_type.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/uniform_type_info.hpp"
......@@ -48,8 +49,8 @@ inline const char* raw_name(const std::type_info& tinfo)
}
template<typename T>
struct is_signed : std::integral_constant<bool,
std::numeric_limits<T>::is_signed>
struct is_signed
: std::integral_constant<bool, std::numeric_limits<T>::is_signed>
{
};
......@@ -177,7 +178,6 @@ class uniform_type_info_map
insert<long double>();
}
insert<any_type>();
// insert<actor_ptr>();
// first: signed
// second: unsigned
std::map<int, std::pair<string_set, string_set>> ints;
......@@ -236,10 +236,11 @@ class uniform_type_info_map
}
bool insert(std::set<std::string> plain_names,
uniform_type_info* what)
uniform_type_info* what)
{
if (m_by_uname.count(what->name()) > 0)
{
delete what;
return false;
}
m_by_uname.insert(std::make_pair(what->name(), what));
......@@ -287,6 +288,11 @@ inline int next_id() { return s_ids.fetch_add(1); }
namespace cppa {
bool announce(const std::type_info& tinfo, uniform_type_info* utype)
{
return detail::s_uniform_type_info_map().insert({ raw_name(tinfo) }, utype);
}
uniform_type_info::uniform_type_info(const std::string& uname)
: m_id(next_id()), m_name(uname)
{
......
......@@ -2,64 +2,64 @@
unsigned int MurmurHash2 ( const void * key, int len, unsigned int seed )
{
static_assert(sizeof(int) == 4,
"MurmurHash2 requires sizeof(int) == 4");
static_assert(sizeof(int) == 4,
"MurmurHash2 requires sizeof(int) == 4");
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
const unsigned int m = 0x5bd1e995;
const int r = 24;
const unsigned int m = 0x5bd1e995;
const int r = 24;
// Initialize the hash to a 'random' value
// Initialize the hash to a 'random' value
unsigned int h = seed ^ len;
unsigned int h = seed ^ len;
// Mix 4 bytes at a time into the hash
// Mix 4 bytes at a time into the hash
const unsigned char * data = (const unsigned char *)key;
const unsigned char * data = (const unsigned char *)key;
while(len >= 4)
{
unsigned int k = *(unsigned int *)data;
while(len >= 4)
{
unsigned int k = *(unsigned int *)data;
k *= m;
k ^= k >> r;
k *= m;
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
h *= m;
h ^= k;
data += 4;
len -= 4;
}
data += 4;
len -= 4;
}
// Handle the last few bytes of the input array
// Handle the last few bytes of the input array
switch(len)
{
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
};
switch(len)
{
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
};
// Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
// Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
h ^= h >> 13;
h *= m;
h ^= h >> 15;
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
return h;
}
unsigned int hash_of(const char* what, int what_length)
{
return MurmurHash2(what, what_length, 0x15091984);
return MurmurHash2(what, what_length, 0x15091984);
}
unsigned int hash_of(const std::string& what)
{
return MurmurHash2(what.c_str(), what.size(), 0x15091984);
return MurmurHash2(what.c_str(), what.size(), 0x15091984);
}
......@@ -23,6 +23,7 @@
#include "cppa/match.hpp"
#include "cppa/tuple.hpp"
#include "cppa/announce.hpp"
#include "cppa/serializer.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/deserializer.hpp"
......@@ -369,108 +370,11 @@ class string_deserializer : public deserializer
};
std::map<std::string, std::unique_ptr<uniform_type_info> > s_types;
void announce(uniform_type_info* utype)
{
const auto& uname = utype->name();
if (s_types.count(uname) == 0)
{
std::unique_ptr<uniform_type_info> uptr(utype);
s_types.insert(std::make_pair(uname, std::move(uptr)));
}
else
{
cerr << utype->name() << " already announced" << endl;
delete utype;
}
}
uniform_type_info* get_meta_type(const std::string& tname)
{
auto i = s_types.find(tname);
return (i != s_types.end()) ? i->second.get() : nullptr;
}
uniform_type_info* get_meta_type(const std::type_info& tinfo)
{
return get_meta_type(detail::to_uniform_name(tinfo));
}
template<typename T>
uniform_type_info* get_meta_type()
{
return get_meta_type(detail::to_uniform_name(typeid(T)));
}
template<int>
inline void _announce_all() { }
template<int, typename T0, typename... Tn>
inline void _announce_all()
{
announce(new detail::default_uniform_type_info_impl<T0>);
_announce_all<0, Tn...>();
}
template<typename... Tn>
void announce_all()
{
_announce_all<0, Tn...>();
}
namespace {
class root_object_type
{
public:
root_object_type()
{
announce_all<std::int8_t, std::int16_t, std::int32_t, std::int64_t,
std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t,
float, double, long double,
std::string, std::u16string, std::u32string>();
}
template<typename T>
void serialize(const T& what, serializer* where) const
{
uniform_type_info* mtype = get_meta_type(detail::to_uniform_name(typeid(T)));
if (!mtype)
{
throw std::logic_error("no meta found for "
+ cppa::detail::to_uniform_name(typeid(T)));
}
mtype->serialize(&what, where);
}
/**
* @brief Deserializes a new object from @p source and returns the
* new (deserialized) instance with its meta_type.
*/
object deserialize(deserializer* source) const
{
std::string tname = source->peek_object();
uniform_type_info* mtype = get_meta_type(tname);
if (!mtype)
{
throw std::logic_error("no meta object found for " + tname);
}
return mtype->deserialize(source);
}
}
root_object;
} // namespace <anonymous>
template<typename T>
std::string to_string(const T& what)
{
std::string tname = detail::to_uniform_name(typeid(T));
auto mobj = get_meta_type(tname);
auto mobj = uniform_typeid<T>();
if (!mobj) throw std::logic_error(tname + " not found");
std::ostringstream osstr;
string_serializer strs(osstr);
......@@ -478,25 +382,6 @@ std::string to_string(const T& what)
return osstr.str();
}
template<typename T, typename... Args>
uniform_type_info* meta_object(const Args&... args)
{
return new detail::default_uniform_type_info_impl<T>(args...);
}
template<class C, class Parent, typename... Args>
std::pair<C Parent::*, uniform_type_info_base<C>*>
compound_member(C Parent::*c_ptr, const Args&... args)
{
return std::make_pair(c_ptr, meta_object<C>(args...));
}
template<typename T, typename... Args>
void announce(const Args&... args)
{
announce(meta_object<T>(args...));
}
std::size_t test__serialization()
{
CPPA_TEST(test__serialization);
......@@ -508,17 +393,14 @@ std::size_t test__serialization()
CPPA_CHECK_EQUAL((is_iterable<std::map<int,int>>::value), true);
// test meta_object implementation for primitive types
{
auto meta_int = get_meta_type<std::uint32_t>();
auto meta_int = uniform_typeid<std::uint32_t>();
CPPA_CHECK(meta_int != nullptr);
if (meta_int)
{
/*
auto o = meta_int->create();
auto str = to_string(*i);
CPPA_CHECK_EQUAL(*i, 0);
CPPA_CHECK_EQUAL(str, "@u32 ( 0 )");
meta_int->delete_instance(i);
*/
get_ref<std::uint32_t>(o) = 42;
auto str = to_string(get<std::uint32_t>(o));
CPPA_CHECK_EQUAL(str, "@u32 ( 42 )");
}
}
// test serializers / deserializers with struct_b
......@@ -538,27 +420,25 @@ std::size_t test__serialization()
"{ 4, 5, 6, 7, 8, 9, 10 } )";
// verify
CPPA_CHECK_EQUAL((to_string(b1)), b1str);
// binary buffer
std::pair<size_t, char*> buf;
{
// serialize b1 to buf
binary_serializer bs;
root_object.serialize(b1, &bs);
bs << b1;
// deserialize b2 from buf
binary_deserializer bd(bs.data(), bs.size());
object res = root_object.deserialize(&bd);
object res;
bd >> res;
CPPA_CHECK_EQUAL(res.type().name(), "struct_b");
b2 = get<struct_b>(res);
}
// cleanup
delete buf.second;
// verify result of serialization / deserialization
CPPA_CHECK_EQUAL(b1, b2);
CPPA_CHECK_EQUAL(to_string(b2), b1str);
// deserialize b3 from string, using string_deserializer
{
string_deserializer strd(b1str);
auto res = root_object.deserialize(&strd);
object res;
strd >> res;
CPPA_CHECK_EQUAL(res.type().name(), "struct_b");
b3 = get<struct_b>(res);
}
......@@ -574,10 +454,11 @@ std::size_t test__serialization()
{
// serialize c1 to buf
binary_serializer bs;
root_object.serialize(c1, &bs);
bs << c1;
// serialize c2 from buf
binary_deserializer bd(bs.data(), bs.size());
auto res = root_object.deserialize(&bd);
object res;
bd >> res;
CPPA_CHECK_EQUAL(res.type().name(), "struct_c");
c2 = get<struct_c>(res);
}
......
......@@ -14,27 +14,22 @@ using namespace cppa;
void pong()
{
receive(on<int>() >> [](int value) {
reply((value * 20) + 2);
});
receive(on<int>() >> [](int value) {
reply((value * 20) + 2);
});
}
std::size_t test__spawn()
{
CPPA_TEST(test__spawn);
{
auto sl = spawn(pong);
send(sl, 23.f);
send(sl, 2);
receive(on<int>() >> [&](int value) {
CPPA_CHECK_EQUAL(value, 42);
});
}
await_all_actors_done();
return CPPA_TEST_RESULT;
CPPA_TEST(test__spawn);
{
auto sl = spawn(pong);
send(sl, 23.f);
send(sl, 2);
receive(on<int>() >> [&](int value) {
CPPA_CHECK_EQUAL(value, 42);
});
}
await_all_actors_done();
return CPPA_TEST_RESULT;
}
......@@ -44,13 +44,13 @@ std::size_t test__type_list()
type_list<std::int32_t, float, char> ifc;
auto i = ifc.begin();
CPPA_CHECK((i != ifc.end()));
CPPA_CHECK(((*i)->name() == "@i32"));
CPPA_CHECK((i->name() == "@i32"));
++i;
CPPA_CHECK((i != ifc.end()));
CPPA_CHECK(((*i)->name() == "float"));
CPPA_CHECK((i->name() == "float"));
++i;
CPPA_CHECK((i != ifc.end()));
CPPA_CHECK(((*i)->name() == "@i8"));
CPPA_CHECK((i->name() == "@i8"));
++i;
CPPA_CHECK((i == ifc.end()));
......
......@@ -15,6 +15,7 @@
#include "test.hpp"
#include "cppa/announce.hpp"
#include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/uniform_type_info.hpp"
......@@ -33,106 +34,76 @@ struct foo
explicit foo(int val = 0) : value(val) { }
};
bool operator==(const foo& lhs, const foo& rhs)
inline bool operator==(const foo& lhs, const foo& rhs)
{
return lhs.value == rhs.value;
}
inline bool operator!=(const foo& lhs, const foo& rhs)
{
return !(lhs == rhs);
}
} // namespace <anonymous>
using namespace cppa;
namespace {
bool unused1 = true;
/*
bool unused1 =
uniform_type_info::announce<foo>(
[] (serializer& s, const foo& f) {
s << f.value;
},
[] (deserializer& d, foo& f) {
d >> f.value;
},
[] (const foo& f) -> std::string {
std::ostringstream ostr;
ostr << f.value;
return ostr.str();
},
[] (const std::string& str) -> foo* {
std::istringstream istr(str);
int tmp;
istr >> tmp;
return new foo(tmp);
}
);
*/
bool unused2 = false;// = uniform_type_info::announce(typeid(foo), new uti_impl<foo>);
bool unused3 = false;//= uniform_type_info::announce(typeid(foo), new uti_impl<foo>);
bool unused4 = false;//= uniform_type_info::announce(typeid(foo), new uti_impl<foo>);
bool announce1 = announce<foo>(&foo::value);
bool announce2 = announce<foo>(&foo::value);
bool announce3 = announce<foo>(&foo::value);
bool announce4 = announce<foo>(&foo::value);
} // namespace <anonymous>
std::size_t test__uniform_type()
{
CPPA_TEST(test__uniform_type);
/*
{
//bar.create_object();
object obj1 = uniform_typeid<foo>()->create();
object obj2(obj1);
CPPA_CHECK_EQUAL(obj1, obj2);
get<foo>(obj1).value = 42;
get_ref<foo>(obj1).value = 42;
CPPA_CHECK(obj1 != obj2);
CPPA_CHECK_EQUAL(get<foo>(obj1).value, 42);
CPPA_CHECK_EQUAL(get<foo>(obj2).value, 0);
}
*/
int successful_announces = (unused1 ? 1 : 0)
+ (unused2 ? 1 : 0)
+ (unused3 ? 1 : 0)
+ (unused4 ? 1 : 0);
int successful_announces = (announce1 ? 1 : 0)
+ (announce2 ? 1 : 0)
+ (announce3 ? 1 : 0)
+ (announce4 ? 1 : 0);
CPPA_CHECK_EQUAL(successful_announces, 1);
// these types (and only those) are present if
// the uniform_type_info implementation is correct
std::set<std::string> expected =
{
// "@_::foo", // name of <anonymous namespace>::foo
"@i8", "@i16", "@i32", "@i64", // signed integer names
"@u8", "@u16", "@u32", "@u64", // unsigned integer names
"@str", "@u16str", "@u32str", // strings
"float", "double", // floating points
"@0", // util::void_type
// default announced cppa types
"cppa::any_type",
"cppa::intrusive_ptr<cppa::actor>"
"@_::foo", // <anonymous namespace>::foo
"@i8", "@i16", "@i32", "@i64", // signed integer names
"@u8", "@u16", "@u32", "@u64", // unsigned integer names
"@str", "@u16str", "@u32str", // strings
"float", "double", // floating points
"@0", // cppa::util::void_type
"cppa::any_type", // default announced cppa type
"cppa::intrusive_ptr<cppa::actor>" // default announced cppa type
};
if (sizeof(double) != sizeof(long double))
{
// long double is only present if it's not an alias for double
expected.insert("long double");
}
// holds the type names we see at runtime
std::set<std::string> found;
// fetch all available type names
// fetch all available type names
auto types = uniform_type_info::instances();
for (uniform_type_info* tinfo : types)
{
found.insert(tinfo->name());
}
// compare the two sets
CPPA_CHECK_EQUAL(expected.size(), found.size());
bool expected_equals_found = false;
if (expected.size() == found.size())
{
expected_equals_found = std::equal(found.begin(),
......
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