Commit 1d3cce57 authored by neverlord's avatar neverlord

type system

parent d0c322ae
...@@ -64,8 +64,6 @@ src/deserializer.cpp ...@@ -64,8 +64,6 @@ src/deserializer.cpp
cppa/util/eval_type_list.hpp cppa/util/eval_type_list.hpp
cppa/util/is_legal_tuple_type.hpp cppa/util/is_legal_tuple_type.hpp
cppa/util/replace_type.hpp cppa/util/replace_type.hpp
cppa/util/source.hpp
cppa/util/sink.hpp
src/untyped_tuple.cpp src/untyped_tuple.cpp
cppa/util/abstract_type_list.hpp cppa/util/abstract_type_list.hpp
cppa/detail/serialize_tuple.hpp cppa/detail/serialize_tuple.hpp
...@@ -143,3 +141,5 @@ src/binary_serializer.cpp ...@@ -143,3 +141,5 @@ src/binary_serializer.cpp
cppa/binary_deserializer.hpp cppa/binary_deserializer.hpp
src/binary_deserializer.cpp src/binary_deserializer.cpp
src/actor.cpp src/actor.cpp
cppa/announce.hpp
src/abstract_type_list.cpp
...@@ -8,9 +8,9 @@ class actor_behavior ...@@ -8,9 +8,9 @@ class actor_behavior
public: public:
virtual void act() = 0; virtual ~actor_behavior();
virtual void on_exit(); 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,6 +5,7 @@ namespace cppa { ...@@ -5,6 +5,7 @@ namespace cppa {
struct any_type struct any_type
{ {
constexpr any_type() { }
inline operator any_type*() { return 0; } inline operator any_type*() { return 0; }
}; };
...@@ -25,9 +26,9 @@ template<typename T> ...@@ -25,9 +26,9 @@ template<typename T>
inline bool operator!=(const any_type&, const T&) { return false; } inline bool operator!=(const any_type&, const T&) { return false; }
#ifdef __GNUC__ #ifdef __GNUC__
static any_type any_val __attribute__ ((unused)); static constexpr any_type any_val __attribute__ ((unused));
#else #else
static any_type any_val; static constexpr any_type any_val;
#endif #endif
} // namespace cppa } // 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 #ifndef CPPA_HPP
#define CPPA_HPP #define CPPA_HPP
...@@ -98,7 +126,7 @@ void reply(const Arg0& arg0, const Args&... args) ...@@ -98,7 +126,7 @@ void reply(const Arg0& arg0, const Args&... args)
inline void await_all_actors_done() inline void await_all_actors_done()
{ {
get_scheduler()->await_all_done(); get_scheduler()->await_others_done();
} }
} // namespace cppa } // namespace cppa
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
namespace cppa { namespace cppa {
class object;
class deserializer class deserializer
{ {
...@@ -42,6 +44,8 @@ class deserializer ...@@ -42,6 +44,8 @@ class deserializer
}; };
deserializer& operator>>(deserializer& d, object& what);
} // namespace cppa } // namespace cppa
#endif // DESERIALIZER_HPP #endif // DESERIALIZER_HPP
...@@ -22,7 +22,7 @@ struct matcher<Head, Tail...> ...@@ -22,7 +22,7 @@ struct matcher<Head, Tail...>
auto head_uti = uniform_typeid<Head>(); auto head_uti = uniform_typeid<Head>();
if (begin != end) if (begin != end)
{ {
if (*(*begin) == *head_uti) if (*begin == *head_uti)
{ {
if (res) if (res)
{ {
......
...@@ -10,8 +10,10 @@ class mock_scheduler : public scheduler ...@@ -10,8 +10,10 @@ class mock_scheduler : public scheduler
public: public:
actor_ptr spawn(actor_behavior* behavior, scheduling_hint hint); void await_others_done();
void await_all_done(); void register_converted_context(context*);
void unregister_converted_context(context*);
actor_ptr spawn(actor_behavior*, scheduling_hint);
}; };
......
#ifndef PRIMITIVE_MEMBER_HPP #ifndef PRIMITIVE_MEMBER_HPP
#define PRIMITIVE_MEMBER_HPP #define PRIMITIVE_MEMBER_HPP
#include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/primitive_type.hpp" #include "cppa/primitive_type.hpp"
#include "cppa/primitive_variant.hpp" #include "cppa/primitive_variant.hpp"
#include "cppa/detail/type_to_ptype.hpp" #include "cppa/detail/type_to_ptype.hpp"
......
...@@ -116,7 +116,7 @@ struct object_caster ...@@ -116,7 +116,7 @@ struct object_caster
} // namespace detail } // namespace detail
template<typename T> template<typename T>
T& get(object& obj) T& get_ref(object& obj)
{ {
static_assert(util::disjunction<std::is_pointer<T>, static_assert(util::disjunction<std::is_pointer<T>,
std::is_reference<T>>::value == false, std::is_reference<T>>::value == false,
...@@ -128,7 +128,7 @@ template<typename T> ...@@ -128,7 +128,7 @@ template<typename T>
const T& get(const object& obj) const T& get(const object& obj)
{ {
static_assert(util::disjunction<std::is_pointer<T>, 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."); "T is a reference a pointer type.");
return detail::object_caster<T>::_(obj); return detail::object_caster<T>::_(obj);
} }
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
#define SCHEDULER_HPP #define SCHEDULER_HPP
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/context.hpp"
#include "cppa/actor_behavior.hpp"
#include "cppa/scheduling_hint.hpp" #include "cppa/scheduling_hint.hpp"
namespace cppa { namespace cppa {
class context;
class actor_behavior;
class scheduler class scheduler
{ {
...@@ -16,16 +17,30 @@ class scheduler ...@@ -16,16 +17,30 @@ class scheduler
virtual ~scheduler(); virtual ~scheduler();
/** /**
* @brief Spawn a new actor that executes <code>behavior->act()</code> * @brief Spawns a new actor that executes <code>behavior->act()</code>
* with the scheduling policy @p hint if possible. * with the scheduling policy @p hint if possible.
*/ */
virtual actor_ptr spawn(actor_behavior* behavior, virtual actor_ptr spawn(actor_behavior* behavior,
scheduling_hint hint) = 0; scheduling_hint hint) = 0;
/** /**
* @brief Wait until all (other) actors finished execution. * @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_all_done() = 0; virtual void await_others_done() = 0;
}; };
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
#include <string> #include <string>
#include <cstddef> // size_t #include <cstddef> // size_t
#include "cppa/uniform_type_info.hpp"
#include "cppa/detail/to_uniform_name.hpp"
namespace cppa { namespace cppa {
// forward declaration // forward declaration
...@@ -36,6 +39,19 @@ class serializer ...@@ -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 } // namespace cppa
#endif // SERIALIZER_HPP #endif // SERIALIZER_HPP
...@@ -9,8 +9,6 @@ ...@@ -9,8 +9,6 @@
#include <type_traits> #include <type_traits>
#include "cppa/object.hpp" #include "cppa/object.hpp"
#include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/util/comparable.hpp" #include "cppa/util/comparable.hpp"
#include "cppa/util/disjunction.hpp" #include "cppa/util/disjunction.hpp"
...@@ -21,6 +19,8 @@ ...@@ -21,6 +19,8 @@
namespace cppa { namespace cppa {
class serializer;
class deserializer;
class uniform_type_info; class uniform_type_info;
const uniform_type_info* uniform_typeid(const std::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> ...@@ -68,7 +68,7 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
public: public:
// enable copy constructor // enable copy constructor (only)
identifier(const identifier&) = default; identifier(const identifier&) = default;
// needed by cppa::detail::comparable<identifier> // needed by cppa::detail::comparable<identifier>
...@@ -136,29 +136,6 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info> ...@@ -136,29 +136,6 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
return id().compare(other.id()); 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. * @brief Creates an object of this type.
*/ */
......
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
#include "cppa/util/reverse_type_list.hpp" #include "cppa/util/reverse_type_list.hpp"
#include "cppa/util/single_reader_queue.hpp" #include "cppa/util/single_reader_queue.hpp"
#include "cppa/util/singly_linked_list.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_at.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/type_list_apply.hpp" #include "cppa/util/type_list_apply.hpp"
......
...@@ -18,8 +18,8 @@ struct amb_helper : util::conjunction<util::is_one_of<HeadA, HeadB, any_type>, ...@@ -18,8 +18,8 @@ struct amb_helper : util::conjunction<util::is_one_of<HeadA, HeadB, any_type>,
typename TailB::head_type, typename TailB::head_type,
typename TailB::tail_type>> typename TailB::tail_type>>
{ {
static_assert( !std::is_same<HeadB, any_type>::value static_assert( std::is_same<HeadB, any_type>::value == false
&& !std::is_same<HeadB, any_type*>::value, && std::is_same<HeadB, any_type*>::value == false,
"any_type in right hand type list"); "any_type in right hand type list");
}; };
...@@ -49,7 +49,7 @@ struct amb_helper<any_type*, TailA, HeadB, TailB> ...@@ -49,7 +49,7 @@ struct amb_helper<any_type*, TailA, HeadB, TailB>
typename TailB::head_type, typename TailB::head_type,
typename TailB::tail_type>> typename TailB::tail_type>>
{ {
static_assert(!std::is_same<HeadB, any_type>::value, static_assert(std::is_same<HeadB, any_type>::value == false,
"any_type in right hand type list"); "any_type in right hand type list");
}; };
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
#define ABSTRACT_TYPE_LIST_HPP #define ABSTRACT_TYPE_LIST_HPP
#include <iterator> #include <iterator>
#include "cppa/uniform_type_info.hpp"
namespace cppa { class serializer; } // forward declaration
namespace cppa { class uniform_type_info; }
namespace cppa { namespace util { namespace cppa { namespace util {
...@@ -19,12 +19,10 @@ struct abstract_type_list ...@@ -19,12 +19,10 @@ struct abstract_type_list
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 inline bool operator==(const const_iterator& other) const
...@@ -37,14 +35,14 @@ struct abstract_type_list ...@@ -37,14 +35,14 @@ struct abstract_type_list
return p != other.p; return p != other.p;
} }
inline const uniform_type_info* operator*() inline const uniform_type_info& operator*() const
{ {
return *p; return *(*p);
} }
inline const uniform_type_info* const* operator->() inline const uniform_type_info* operator->() const
{ {
return p; return *p;
} }
inline const_iterator& operator++() inline const_iterator& operator++()
...@@ -53,12 +51,7 @@ struct abstract_type_list ...@@ -53,12 +51,7 @@ struct abstract_type_list
return *this; return *this;
} }
inline const_iterator operator++(int) const_iterator operator++(int);
{
const_iterator tmp(*this);
operator++();
return tmp;
}
inline const_iterator& operator--() inline const_iterator& operator--()
{ {
...@@ -66,15 +59,12 @@ struct abstract_type_list ...@@ -66,15 +59,12 @@ struct abstract_type_list
return *this; return *this;
} }
inline const_iterator operator--(int) const_iterator operator--(int);
{
const_iterator tmp(*this);
operator--();
return tmp;
}
}; };
virtual ~abstract_type_list();
virtual abstract_type_list* copy() const = 0; virtual abstract_type_list* copy() const = 0;
virtual const_iterator begin() const = 0; virtual const_iterator begin() const = 0;
......
...@@ -53,7 +53,6 @@ struct min_ ...@@ -53,7 +53,6 @@ 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::detail
namespace cppa { namespace util { namespace cppa { namespace util {
......
...@@ -8,8 +8,8 @@ namespace cppa { namespace util { ...@@ -8,8 +8,8 @@ namespace cppa { namespace util {
template<typename T> template<typename T>
struct is_legal_tuple_type struct is_legal_tuple_type
{ {
static const bool value = !std::is_pointer<T>::value static const bool value = std::is_pointer<T>::value == false
&& !std::is_reference<T>::value; && std::is_reference<T>::value == false;
}; };
} } // namespace cppa::util } } // namespace cppa::util
......
#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
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
#include <typeinfo> #include <typeinfo>
#include "cppa/any_type.hpp" #include "cppa/any_type.hpp"
//#include "cppa/uniform_type_info.hpp"
#include "cppa/util/void_type.hpp" #include "cppa/util/void_type.hpp"
#include "cppa/util/abstract_type_list.hpp" #include "cppa/util/abstract_type_list.hpp"
...@@ -38,7 +37,10 @@ struct type_list<Head, Tail...> : abstract_type_list ...@@ -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; 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 virtual const_iterator begin() const
{ {
...@@ -69,14 +71,6 @@ struct type_list<Head, Tail...> : abstract_type_list ...@@ -69,14 +71,6 @@ struct type_list<Head, Tail...> : abstract_type_list
++what; ++what;
init<typename TypeList::tail_type>(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: private:
......
...@@ -68,7 +68,8 @@ HEADERS = cppa/actor.hpp \ ...@@ -68,7 +68,8 @@ HEADERS = cppa/actor.hpp \
cppa/util/type_list_pop_back.hpp \ cppa/util/type_list_pop_back.hpp \
cppa/util/void_type.hpp cppa/util/void_type.hpp
SOURCES = src/actor.cpp \ SOURCES = src/abstract_type_list.cpp \
src/actor.cpp \
src/actor_behavior.cpp \ src/actor_behavior.cpp \
src/binary_deserializer.cpp \ src/binary_deserializer.cpp \
src/binary_serializer.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 @@ ...@@ -2,6 +2,12 @@
namespace cppa { namespace cppa {
void actor_behavior::on_exit() { } actor_behavior::~actor_behavior()
{
}
void actor_behavior::on_exit()
{
}
} // namespace cppa } // namespace cppa
...@@ -5,11 +5,16 @@ ...@@ -5,11 +5,16 @@
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include "cppa/scheduler.hpp"
namespace { namespace {
void cleanup_fun(cppa::context* what) 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); boost::thread_specific_ptr<cppa::context> m_this_context(cleanup_fun);
...@@ -30,6 +35,7 @@ context* self() ...@@ -30,6 +35,7 @@ context* self()
{ {
result = new detail::converted_thread_context; result = new detail::converted_thread_context;
result->ref(); result->ref();
get_scheduler()->register_converted_context(result);
m_this_context.reset(result); m_this_context.reset(result);
} }
return result; return result;
......
#include <string>
#include "cppa/object.hpp"
#include "cppa/deserializer.hpp" #include "cppa/deserializer.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/detail/to_uniform_name.hpp"
namespace cppa { namespace cppa {
...@@ -6,4 +11,16 @@ deserializer::~deserializer() ...@@ -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 } // namespace cppa
...@@ -10,10 +10,10 @@ ...@@ -10,10 +10,10 @@
#include "cppa/message.hpp" #include "cppa/message.hpp"
#include "cppa/context.hpp" #include "cppa/context.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/scheduler.hpp" #include "cppa/scheduler.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/actor_behavior.hpp"
#include "cppa/detail/mock_scheduler.hpp" #include "cppa/detail/mock_scheduler.hpp"
#include "cppa/detail/converted_thread_context.hpp" #include "cppa/detail/converted_thread_context.hpp"
namespace { namespace {
...@@ -28,14 +28,12 @@ void run_actor(cppa::intrusive_ptr<cppa::context> m_self, ...@@ -28,14 +28,12 @@ void run_actor(cppa::intrusive_ptr<cppa::context> m_self,
cppa::set_self(m_self.get()); cppa::set_self(m_self.get());
if (behavior) if (behavior)
{ {
try try { behavior->act(); }
{ catch(...) { }
behavior->act(); try { behavior->on_exit(); }
}
catch(...) { } catch(...) { }
behavior->on_exit();
} }
if (--m_running_actors == 0) if (--m_running_actors <= 1)
{ {
boost::mutex::scoped_lock lock(m_ra_mtx); boost::mutex::scoped_lock lock(m_ra_mtx);
m_ra_cv.notify_all(); m_ra_cv.notify_all();
...@@ -54,10 +52,24 @@ actor_ptr mock_scheduler::spawn(actor_behavior* ab, scheduling_hint) ...@@ -54,10 +52,24 @@ actor_ptr mock_scheduler::spawn(actor_behavior* ab, scheduling_hint)
return ctx; return ctx;
} }
void mock_scheduler::await_all_done() 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_others_done()
{ {
boost::mutex::scoped_lock lock(m_ra_mtx); boost::mutex::scoped_lock lock(m_ra_mtx);
while (m_running_actors.load() > 0) while (m_running_actors.load() > 1)
{ {
m_ra_cv.wait(lock); m_ra_cv.wait(lock);
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/announce.hpp"
#include "cppa/any_type.hpp" #include "cppa/any_type.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
...@@ -48,8 +49,8 @@ inline const char* raw_name(const std::type_info& tinfo) ...@@ -48,8 +49,8 @@ inline const char* raw_name(const std::type_info& tinfo)
} }
template<typename T> template<typename T>
struct is_signed : std::integral_constant<bool, struct is_signed
std::numeric_limits<T>::is_signed> : std::integral_constant<bool, std::numeric_limits<T>::is_signed>
{ {
}; };
...@@ -177,7 +178,6 @@ class uniform_type_info_map ...@@ -177,7 +178,6 @@ class uniform_type_info_map
insert<long double>(); insert<long double>();
} }
insert<any_type>(); insert<any_type>();
// insert<actor_ptr>();
// first: signed // first: signed
// second: unsigned // second: unsigned
std::map<int, std::pair<string_set, string_set>> ints; std::map<int, std::pair<string_set, string_set>> ints;
...@@ -240,6 +240,7 @@ class uniform_type_info_map ...@@ -240,6 +240,7 @@ class uniform_type_info_map
{ {
if (m_by_uname.count(what->name()) > 0) if (m_by_uname.count(what->name()) > 0)
{ {
delete what;
return false; return false;
} }
m_by_uname.insert(std::make_pair(what->name(), what)); m_by_uname.insert(std::make_pair(what->name(), what));
...@@ -287,6 +288,11 @@ inline int next_id() { return s_ids.fetch_add(1); } ...@@ -287,6 +288,11 @@ inline int next_id() { return s_ids.fetch_add(1); }
namespace cppa { 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) uniform_type_info::uniform_type_info(const std::string& uname)
: m_id(next_id()), m_name(uname) : m_id(next_id()), m_name(uname)
{ {
......
...@@ -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/announce.hpp"
#include "cppa/serializer.hpp" #include "cppa/serializer.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/deserializer.hpp" #include "cppa/deserializer.hpp"
...@@ -369,108 +370,11 @@ class string_deserializer : public deserializer ...@@ -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> 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)); 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"); if (!mobj) throw std::logic_error(tname + " not found");
std::ostringstream osstr; std::ostringstream osstr;
string_serializer strs(osstr); string_serializer strs(osstr);
...@@ -478,25 +382,6 @@ std::string to_string(const T& what) ...@@ -478,25 +382,6 @@ std::string to_string(const T& what)
return osstr.str(); 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() std::size_t test__serialization()
{ {
CPPA_TEST(test__serialization); CPPA_TEST(test__serialization);
...@@ -508,17 +393,14 @@ std::size_t test__serialization() ...@@ -508,17 +393,14 @@ std::size_t test__serialization()
CPPA_CHECK_EQUAL((is_iterable<std::map<int,int>>::value), true); CPPA_CHECK_EQUAL((is_iterable<std::map<int,int>>::value), true);
// test meta_object implementation for primitive types // 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); CPPA_CHECK(meta_int != nullptr);
if (meta_int) if (meta_int)
{ {
/*
auto o = meta_int->create(); auto o = meta_int->create();
auto str = to_string(*i); get_ref<std::uint32_t>(o) = 42;
CPPA_CHECK_EQUAL(*i, 0); auto str = to_string(get<std::uint32_t>(o));
CPPA_CHECK_EQUAL(str, "@u32 ( 0 )"); CPPA_CHECK_EQUAL(str, "@u32 ( 42 )");
meta_int->delete_instance(i);
*/
} }
} }
// test serializers / deserializers with struct_b // test serializers / deserializers with struct_b
...@@ -538,27 +420,25 @@ std::size_t test__serialization() ...@@ -538,27 +420,25 @@ std::size_t test__serialization()
"{ 4, 5, 6, 7, 8, 9, 10 } )"; "{ 4, 5, 6, 7, 8, 9, 10 } )";
// verify // verify
CPPA_CHECK_EQUAL((to_string(b1)), b1str); CPPA_CHECK_EQUAL((to_string(b1)), b1str);
// binary buffer
std::pair<size_t, char*> buf;
{ {
// serialize b1 to buf // serialize b1 to buf
binary_serializer bs; binary_serializer bs;
root_object.serialize(b1, &bs); bs << b1;
// deserialize b2 from buf // deserialize b2 from buf
binary_deserializer bd(bs.data(), bs.size()); 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"); CPPA_CHECK_EQUAL(res.type().name(), "struct_b");
b2 = get<struct_b>(res); b2 = get<struct_b>(res);
} }
// cleanup
delete buf.second;
// verify result of serialization / deserialization // verify result of serialization / deserialization
CPPA_CHECK_EQUAL(b1, b2); CPPA_CHECK_EQUAL(b1, b2);
CPPA_CHECK_EQUAL(to_string(b2), b1str); CPPA_CHECK_EQUAL(to_string(b2), b1str);
// deserialize b3 from string, using string_deserializer // deserialize b3 from string, using string_deserializer
{ {
string_deserializer strd(b1str); string_deserializer strd(b1str);
auto res = root_object.deserialize(&strd); object res;
strd >> res;
CPPA_CHECK_EQUAL(res.type().name(), "struct_b"); CPPA_CHECK_EQUAL(res.type().name(), "struct_b");
b3 = get<struct_b>(res); b3 = get<struct_b>(res);
} }
...@@ -574,10 +454,11 @@ std::size_t test__serialization() ...@@ -574,10 +454,11 @@ std::size_t test__serialization()
{ {
// serialize c1 to buf // serialize c1 to buf
binary_serializer bs; binary_serializer bs;
root_object.serialize(c1, &bs); bs << c1;
// serialize c2 from buf // serialize c2 from buf
binary_deserializer bd(bs.data(), bs.size()); 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"); CPPA_CHECK_EQUAL(res.type().name(), "struct_c");
c2 = get<struct_c>(res); c2 = get<struct_c>(res);
} }
......
...@@ -21,9 +21,7 @@ void pong() ...@@ -21,9 +21,7 @@ void pong()
std::size_t test__spawn() std::size_t test__spawn()
{ {
CPPA_TEST(test__spawn); CPPA_TEST(test__spawn);
{ {
auto sl = spawn(pong); auto sl = spawn(pong);
send(sl, 23.f); send(sl, 23.f);
...@@ -32,9 +30,6 @@ std::size_t test__spawn() ...@@ -32,9 +30,6 @@ std::size_t test__spawn()
CPPA_CHECK_EQUAL(value, 42); CPPA_CHECK_EQUAL(value, 42);
}); });
} }
await_all_actors_done(); await_all_actors_done();
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
...@@ -44,13 +44,13 @@ std::size_t test__type_list() ...@@ -44,13 +44,13 @@ std::size_t test__type_list()
type_list<std::int32_t, float, char> ifc; type_list<std::int32_t, float, char> ifc;
auto i = ifc.begin(); auto i = ifc.begin();
CPPA_CHECK((i != ifc.end())); CPPA_CHECK((i != ifc.end()));
CPPA_CHECK(((*i)->name() == "@i32")); CPPA_CHECK((i->name() == "@i32"));
++i; ++i;
CPPA_CHECK((i != ifc.end())); CPPA_CHECK((i != ifc.end()));
CPPA_CHECK(((*i)->name() == "float")); CPPA_CHECK((i->name() == "float"));
++i; ++i;
CPPA_CHECK((i != ifc.end())); CPPA_CHECK((i != ifc.end()));
CPPA_CHECK(((*i)->name() == "@i8")); CPPA_CHECK((i->name() == "@i8"));
++i; ++i;
CPPA_CHECK((i == ifc.end())); CPPA_CHECK((i == ifc.end()));
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "test.hpp" #include "test.hpp"
#include "cppa/announce.hpp"
#include "cppa/serializer.hpp" #include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp" #include "cppa/deserializer.hpp"
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
...@@ -33,106 +34,76 @@ struct foo ...@@ -33,106 +34,76 @@ struct foo
explicit foo(int val = 0) : value(val) { } 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; return lhs.value == rhs.value;
} }
inline bool operator!=(const foo& lhs, const foo& rhs)
{
return !(lhs == rhs);
}
} // namespace <anonymous> } // namespace <anonymous>
using namespace cppa; using namespace cppa;
namespace { namespace {
bool unused1 = true; bool announce1 = announce<foo>(&foo::value);
/* bool announce2 = announce<foo>(&foo::value);
bool unused1 = bool announce3 = announce<foo>(&foo::value);
uniform_type_info::announce<foo>( bool announce4 = announce<foo>(&foo::value);
[] (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>);
} // namespace <anonymous> } // namespace <anonymous>
std::size_t test__uniform_type() std::size_t test__uniform_type()
{ {
CPPA_TEST(test__uniform_type); CPPA_TEST(test__uniform_type);
/*
{ {
//bar.create_object(); //bar.create_object();
object obj1 = uniform_typeid<foo>()->create(); object obj1 = uniform_typeid<foo>()->create();
object obj2(obj1); object obj2(obj1);
CPPA_CHECK_EQUAL(obj1, obj2); CPPA_CHECK_EQUAL(obj1, obj2);
get<foo>(obj1).value = 42; get_ref<foo>(obj1).value = 42;
CPPA_CHECK(obj1 != obj2); CPPA_CHECK(obj1 != obj2);
CPPA_CHECK_EQUAL(get<foo>(obj1).value, 42); CPPA_CHECK_EQUAL(get<foo>(obj1).value, 42);
CPPA_CHECK_EQUAL(get<foo>(obj2).value, 0); CPPA_CHECK_EQUAL(get<foo>(obj2).value, 0);
} }
*/ int successful_announces = (announce1 ? 1 : 0)
+ (announce2 ? 1 : 0)
int successful_announces = (unused1 ? 1 : 0) + (announce3 ? 1 : 0)
+ (unused2 ? 1 : 0) + (announce4 ? 1 : 0);
+ (unused3 ? 1 : 0)
+ (unused4 ? 1 : 0);
CPPA_CHECK_EQUAL(successful_announces, 1); CPPA_CHECK_EQUAL(successful_announces, 1);
// these types (and only those) are present if // these types (and only those) are present if
// the uniform_type_info implementation is correct // the uniform_type_info implementation is correct
std::set<std::string> expected = std::set<std::string> expected =
{ {
// "@_::foo", // name of <anonymous namespace>::foo "@_::foo", // <anonymous namespace>::foo
"@i8", "@i16", "@i32", "@i64", // signed integer names "@i8", "@i16", "@i32", "@i64", // signed integer names
"@u8", "@u16", "@u32", "@u64", // unsigned integer names "@u8", "@u16", "@u32", "@u64", // unsigned integer names
"@str", "@u16str", "@u32str", // strings "@str", "@u16str", "@u32str", // strings
"float", "double", // floating points "float", "double", // floating points
"@0", // util::void_type "@0", // cppa::util::void_type
// default announced cppa types "cppa::any_type", // default announced cppa type
"cppa::any_type", "cppa::intrusive_ptr<cppa::actor>" // default announced cppa type
"cppa::intrusive_ptr<cppa::actor>"
}; };
if (sizeof(double) != sizeof(long double)) if (sizeof(double) != sizeof(long double))
{ {
// long double is only present if it's not an alias for double // long double is only present if it's not an alias for double
expected.insert("long double"); expected.insert("long double");
} }
// holds the type names we see at runtime // holds the type names we see at runtime
std::set<std::string> found; std::set<std::string> found;
// fetch all available type names
// fetch all available type names
auto types = uniform_type_info::instances(); auto types = uniform_type_info::instances();
for (uniform_type_info* tinfo : types) for (uniform_type_info* tinfo : types)
{ {
found.insert(tinfo->name()); found.insert(tinfo->name());
} }
// compare the two sets // compare the two sets
CPPA_CHECK_EQUAL(expected.size(), found.size()); CPPA_CHECK_EQUAL(expected.size(), found.size());
bool expected_equals_found = false; bool expected_equals_found = false;
if (expected.size() == found.size()) if (expected.size() == found.size())
{ {
expected_equals_found = std::equal(found.begin(), 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