Commit 61cf341e authored by neverlord's avatar neverlord

uniform_type_info changes

parent 03e2d174
CXX = /opt/local/bin/g++-mp-4.6 CXX = /opt/local/bin/g++-mp-4.6
CXXFLAGS = -std=c++0x -pedantic -Wall -Wextra -O2 -I/opt/local/include/ #CXXFLAGS = -std=c++0x -pedantic -Wall -Wextra -O2 -I/opt/local/include/ -fpermissive
#CXXFLAGS = -std=c++0x -pedantic -Wall -Wextra -g -O0 -I/opt/local/include/ CXXFLAGS = -std=c++0x -pedantic -Wall -Wextra -g -O0 -I/opt/local/include/ -fpermissive
LIBS = -L/opt/local/lib -lboost_thread-mt LIBS = -L/opt/local/lib -lboost_thread-mt
...@@ -60,15 +60,15 @@ ...@@ -60,15 +60,15 @@
<valuemap type="QVariantMap"> <valuemap type="QVariantMap">
<value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">all</value> <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">all</value>
<valuelist key="abstractProcess.Environment" type="QVariantList"> <valuelist key="abstractProcess.Environment" type="QVariantList">
<value type="QString">Apple_PubSub_Socket_Render=/tmp/launch-qTxq6l/Render</value> <value type="QString">Apple_PubSub_Socket_Render=/tmp/launch-tO8Wwx/Render</value>
<value type="QString">COMMAND_MODE=unix2003</value> <value type="QString">COMMAND_MODE=unix2003</value>
<value type="QString">DISPLAY=/tmp/launch-b33dXE/org.x:0</value> <value type="QString">DISPLAY=/tmp/launch-w1qNYf/org.x:0</value>
<value type="QString">HOME=/Users/neverlord</value> <value type="QString">HOME=/Users/neverlord</value>
<value type="QString">LOGNAME=neverlord</value> <value type="QString">LOGNAME=neverlord</value>
<value type="QString">PATH=/usr/bin:/bin:/usr/sbin:/sbin</value> <value type="QString">PATH=/usr/bin:/bin:/usr/sbin:/sbin</value>
<value type="QString">SHELL=/bin/bash</value> <value type="QString">SHELL=/bin/bash</value>
<value type="QString">SSH_AUTH_SOCK=/tmp/launch-ZcReR3/Listeners</value> <value type="QString">SSH_AUTH_SOCK=/tmp/launch-dnUZas/Listeners</value>
<value type="QString">TMPDIR=/var/folders/1p/1p6iuPgbH7GoDkrjrT20tU+++TI/-Tmp-/</value> <value type="QString">TMPDIR=/var/folders/SE/SEReyCW0H-yDPCnNCe8mN++++TI/-Tmp-/</value>
<value type="QString">USER=neverlord</value> <value type="QString">USER=neverlord</value>
<value type="QString">__CF_USER_TEXT_ENCODING=0x1F5:0:3</value> <value type="QString">__CF_USER_TEXT_ENCODING=0x1F5:0:3</value>
</valuelist> </valuelist>
......
...@@ -19,7 +19,6 @@ cppa/detail/abstract_tuple.hpp ...@@ -19,7 +19,6 @@ cppa/detail/abstract_tuple.hpp
cppa/tuple_view.hpp cppa/tuple_view.hpp
cppa/untyped_tuple.hpp cppa/untyped_tuple.hpp
cppa/any_type.hpp cppa/any_type.hpp
cppa/util/utype_iterator.hpp
cppa/detail/matcher.hpp cppa/detail/matcher.hpp
cppa/detail/tuple_vals.hpp cppa/detail/tuple_vals.hpp
cppa/match.hpp cppa/match.hpp
...@@ -28,7 +27,6 @@ cppa/cow_ptr.hpp ...@@ -28,7 +27,6 @@ cppa/cow_ptr.hpp
cppa/util/detach.hpp cppa/util/detach.hpp
cppa/detail/ref_counted_impl.hpp cppa/detail/ref_counted_impl.hpp
cppa/intrusive_ptr.hpp cppa/intrusive_ptr.hpp
cppa/detail/scheduler.hpp
unit_testing/test__spawn.cpp unit_testing/test__spawn.cpp
src/mock_scheduler.cpp src/mock_scheduler.cpp
cppa/actor.hpp cppa/actor.hpp
...@@ -60,8 +58,6 @@ cppa/deserializer.hpp ...@@ -60,8 +58,6 @@ cppa/deserializer.hpp
cppa/util/is_serializable.hpp cppa/util/is_serializable.hpp
cppa/util/enable_if.hpp cppa/util/enable_if.hpp
cppa/object.hpp cppa/object.hpp
cppa/utype.hpp
cppa/detail/utype_impl.hpp
cppa/detail/object_impl.hpp cppa/detail/object_impl.hpp
cppa/detail/swap_bytes.hpp cppa/detail/swap_bytes.hpp
src/serializer.cpp src/serializer.cpp
...@@ -107,3 +103,18 @@ queue_performances/blocking_sutter_list.hpp ...@@ -107,3 +103,18 @@ queue_performances/blocking_sutter_list.hpp
queue_performances/lockfree_list.hpp queue_performances/lockfree_list.hpp
queue_performances/intrusive_sutter_list.hpp queue_performances/intrusive_sutter_list.hpp
cppa/detail/cpp0x_thread_wrapper.hpp cppa/detail/cpp0x_thread_wrapper.hpp
src/context.cpp
cppa/scheduler.hpp
cppa/detail/mock_scheduler.hpp
src/scheduler.cpp
cppa/detail/blocking_message_queue.hpp
src/blocking_message_queue.cpp
cppa/detail/converted_thread_context.hpp
src/converted_thread_context.cpp
unit_testing/test__uniform_type.cpp
cppa/detail/demangle.hpp
src/demangle.cpp
cppa/detail/to_uniform_name.hpp
src/to_uniform_name.cpp
cppa/util/default_object_base.hpp
cppa/detail/default_object_impl.hpp
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#if defined(__APPLE__) #if defined(__APPLE__)
# define CPPA_MACOS # define CPPA_MACOS
# define _GLIBCXX_HAS_GTHREADS
#elif defined(__GNUC__) && defined(__linux__) #elif defined(__GNUC__) && defined(__linux__)
# define CPPA_LINUX # define CPPA_LINUX
#elif defined(WIN32) #elif defined(WIN32)
......
...@@ -13,8 +13,24 @@ class context : public actor ...@@ -13,8 +13,24 @@ class context : public actor
virtual message_queue& mailbox() = 0; virtual message_queue& mailbox() = 0;
/**
* @brief Default implementation of
* {@link channel::enqueue(const message&)}.
*
* Calls <code>mailbox().enqueue(msg)</code>.
*/
virtual void enqueue /*[[override]]*/ (const message& msg);
}; };
/**
* @brief Get a pointer to the current active context.
*/
context* self();
// "private" function
void set_self(context*);
} // namespace cppa } // namespace cppa
#endif // CONTEXT_HPP #endif // CONTEXT_HPP
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include "cppa/invoke_rules.hpp" #include "cppa/invoke_rules.hpp"
#include "cppa/actor_behavior.hpp" #include "cppa/actor_behavior.hpp"
#include "cppa/scheduling_hint.hpp" #include "cppa/scheduling_hint.hpp"
#include "cppa/detail/scheduler.hpp" #include "cppa/scheduler.hpp"
namespace cppa { namespace cppa {
...@@ -26,7 +26,7 @@ actor_ptr spawn(scheduling_hint hint, F fun) ...@@ -26,7 +26,7 @@ actor_ptr spawn(scheduling_hint hint, F fun)
m_fun(); m_fun();
} }
}; };
return detail::scheduler::spawn(new fun_behavior(fun), hint); return get_scheduler()->spawn(new fun_behavior(fun), hint);
} }
template<typename F, typename Arg0, typename... Args> template<typename F, typename Arg0, typename... Args>
...@@ -44,17 +44,12 @@ inline actor_ptr spawn(F fun, const Args&... args) ...@@ -44,17 +44,12 @@ inline actor_ptr spawn(F fun, const Args&... args)
inline actor_ptr spawn(scheduling_hint hint, actor_behavior* ab) inline actor_ptr spawn(scheduling_hint hint, actor_behavior* ab)
{ {
return detail::scheduler::spawn(ab, hint); return get_scheduler()->spawn(ab, hint);
} }
inline actor_ptr spawn(actor_behavior* ab) inline actor_ptr spawn(actor_behavior* ab)
{ {
return detail::scheduler::spawn(ab, scheduled); return get_scheduler()->spawn(ab, scheduled);
}
inline context* self()
{
return detail::scheduler::get_context();
} }
inline const message& receive() inline const message& receive()
...@@ -103,7 +98,7 @@ void reply(const Arg0& arg0, const Args&... args) ...@@ -103,7 +98,7 @@ void reply(const Arg0& arg0, const Args&... args)
inline void await_all_actors_done() inline void await_all_actors_done()
{ {
detail::scheduler::await_all_done(); get_scheduler()->await_all_done();
} }
} // namespace cppa } // namespace cppa
......
...@@ -18,7 +18,7 @@ struct abstract_tuple : ref_counted ...@@ -18,7 +18,7 @@ struct abstract_tuple : ref_counted
virtual std::size_t size() const = 0; virtual std::size_t size() const = 0;
virtual abstract_tuple* copy() const = 0; virtual abstract_tuple* copy() const = 0;
virtual const void* at(std::size_t pos) const = 0; virtual const void* at(std::size_t pos) const = 0;
virtual const utype& utype_at(std::size_t pos) const = 0; virtual const uniform_type_info* utype_at(std::size_t pos) const = 0;
virtual const util::abstract_type_list& types() const = 0; virtual const util::abstract_type_list& types() const = 0;
virtual bool equal_to(const abstract_tuple& other) const = 0; virtual bool equal_to(const abstract_tuple& other) const = 0;
virtual void serialize(serializer&) const = 0; virtual void serialize(serializer&) const = 0;
......
#ifndef ACTOR_PRIVATE_HPP #ifndef ACTOR_PRIVATE_HPP
#define ACTOR_PRIVATE_HPP #define ACTOR_PRIVATE_HPP
/*
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include "cppa/invoke_rules.hpp" #include "cppa/invoke_rules.hpp"
...@@ -54,4 +56,6 @@ inline const message& last_dequeued() ...@@ -54,4 +56,6 @@ inline const message& last_dequeued()
} // namespace cppa } // namespace cppa
*/
#endif // ACTOR_PRIVATE_HPP #endif // ACTOR_PRIVATE_HPP
#ifndef ACTOR_PUBLIC_HPP #ifndef ACTOR_PUBLIC_HPP
#define ACTOR_PUBLIC_HPP #define ACTOR_PUBLIC_HPP
/*
#include "cppa/detail/channel.hpp" #include "cppa/detail/channel.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
...@@ -13,4 +15,6 @@ struct actor_public : channel ...@@ -13,4 +15,6 @@ struct actor_public : channel
} } // namespace cppa::detail } } // namespace cppa::detail
*/
#endif // ACTOR_PUBLIC_HPP #endif // ACTOR_PUBLIC_HPP
#ifndef BLOCKING_MESSAGE_QUEUE_HPP
#define BLOCKING_MESSAGE_QUEUE_HPP
#include "cppa/message.hpp"
#include "cppa/message_queue.hpp"
#include "cppa/util/single_reader_queue.hpp"
namespace cppa { namespace detail {
// blocks if single_reader_queue blocks
class blocking_message_queue : public message_queue
{
struct queue_node
{
queue_node* next;
message msg;
queue_node(const message& from) : next(0), msg(from) { }
};
message m_last_dequeued;
util::single_reader_queue<queue_node> m_queue;
public:
virtual void enqueue /*[[override]]*/ (const message& msg);
virtual const message& dequeue /*[[override]]*/ ();
virtual void dequeue /*[[override]]*/ (invoke_rules& rules);
virtual bool try_dequeue /*[[override]]*/ (message& msg);
virtual bool try_dequeue /*[[override]]*/ (invoke_rules& rules);
virtual const message& last_dequeued /*[[override]]*/ ();
};
} } // namespace hamcast::detail
#endif // BLOCKING_MESSAGE_QUEUE_HPP
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
// Barton–Nackman trick
template<typename Subclass, typename T = Subclass> template<typename Subclass, typename T = Subclass>
class comparable class comparable
{ {
......
#ifndef CONVERTED_THREAD_CONTEXT_HPP
#define CONVERTED_THREAD_CONTEXT_HPP
#include "cppa/config.hpp"
#include <map>
#include <set>
#include <mutex>
#include "cppa/context.hpp"
#include "cppa/detail/blocking_message_queue.hpp"
namespace cppa { namespace detail {
class converted_thread_context : public context
{
// mailbox implementation
detail::blocking_message_queue m_mailbox;
// 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;
// manages group subscriptions
std::map<group_ptr, intrusive_ptr<group::subscription>> m_subscriptions;
// manages actor links
std::set<actor_ptr> m_links;
public:
message_queue& mailbox /*[[override]]*/ ();
void join /*[[override]]*/ (group_ptr& what);
void leave /*[[override]]*/ (const group_ptr& what);
void link /*[[override]]*/ (intrusive_ptr<actor>& other);
void unlink /*[[override]]*/ (intrusive_ptr<actor>& other);
bool remove_backlink /*[[override]]*/ (const intrusive_ptr<actor>& to);
bool establish_backlink /*[[override]]*/ (const intrusive_ptr<actor>& to);
};
} } // namespace cppa::detail
#endif // CONVERTED_THREAD_CONTEXT_HPP
#ifndef CPPA_DETAIL_CPP0X_THREAD_WRAPPER_HPP #ifndef CPPA_DETAIL_CPP0X_THREAD_WRAPPER_HPP
#define CPPA_DETAIL_CPP0X_THREAD_WRAPPER_HPP #define CPPA_DETAIL_CPP0X_THREAD_WRAPPER_HPP
// This header imports C++0x compatible parts of the boost threading library
// to the std namespace. It's a workaround to the missing stl threading
// library on GCC 4.6 under Mac OS X
#include <boost/thread.hpp> #include <boost/thread.hpp>
namespace std { namespace std {
......
...@@ -50,7 +50,7 @@ class decorated_tuple : public abstract_tuple ...@@ -50,7 +50,7 @@ class decorated_tuple : public abstract_tuple
return m_decorated->at(m_mappings[pos]); return m_decorated->at(m_mappings[pos]);
} }
virtual const utype& utype_at(std::size_t pos) const virtual const uniform_type_info* utype_at(std::size_t pos) const
{ {
return m_decorated->utype_at(m_mappings[pos]); return m_decorated->utype_at(m_mappings[pos]);
} }
......
#ifndef DEFAULT_OBJECT_IMPL_HPP
#define DEFAULT_OBJECT_IMPL_HPP
#include <sstream>
#include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/util/default_object_base.hpp"
namespace cppa { namespace detail {
template<typename T>
class default_object_impl : public util::default_object_base<T>
{
typedef util::default_object_base<T> super;
public:
default_object_impl(const uniform_type_info* uti, const T& val = T())
: super(uti, val)
{
}
object* copy /*[[override]]*/ () const
{
return new default_object_impl(this->type(), this->m_value);
}
std::string to_string /*[[override]]*/ () const
{
std::ostringstream sstr;
sstr << this->m_value;
return sstr.str();
}
void from_string /*[[override]]*/ (const std::string& str)
{
T tmp;
std::istringstream istr(str);
istr >> tmp;
this->m_value = std::move(tmp);
}
void deserialize /*[[override]]*/ (deserializer& d)
{
d >> this->m_value;
}
void serialize /*[[override]]*/ (serializer& s) const
{
s << this->m_value;
}
};
} } // namespace cppa::detail
#endif // DEFAULT_OBJECT_IMPL_HPP
#ifndef DEMANGLE_HPP
#define DEMANGLE_HPP
#include <string>
namespace cppa { namespace detail {
std::string demangle(const char* typeid_name);
} } // namespace cppa::detail
#endif // DEMANGLE_HPP
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
#include <vector> #include <vector>
#include "cppa/any_type.hpp" #include "cppa/any_type.hpp"
#include "cppa/util/utype_iterator.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/util/abstract_type_list.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
...@@ -13,14 +14,15 @@ template<typename... Types> struct matcher; ...@@ -13,14 +14,15 @@ template<typename... Types> struct matcher;
template<typename Head, typename... Tail> template<typename Head, typename... Tail>
struct matcher<Head, Tail...> struct matcher<Head, Tail...>
{ {
static bool match(util::utype_iterator& begin, static bool match(util::abstract_type_list::const_iterator& begin,
util::utype_iterator& end, util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr, std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0) std::size_t pos = 0)
{ {
auto head_uti = uniform_typeid<Head>();
if (begin != end) if (begin != end)
{ {
if (begin->native() == typeid(Head)) if (*(*begin) == *head_uti)
{ {
if (res) if (res)
{ {
...@@ -38,8 +40,8 @@ struct matcher<Head, Tail...> ...@@ -38,8 +40,8 @@ struct matcher<Head, Tail...>
template<typename... Tail> template<typename... Tail>
struct matcher<any_type, Tail...> struct matcher<any_type, Tail...>
{ {
static bool match(util::utype_iterator &begin, static bool match(util::abstract_type_list::const_iterator& begin,
util::utype_iterator &end, util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr, std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0) std::size_t pos = 0)
{ {
...@@ -56,15 +58,15 @@ struct matcher<any_type, Tail...> ...@@ -56,15 +58,15 @@ struct matcher<any_type, Tail...>
template<typename Next, typename... Tail> template<typename Next, typename... Tail>
struct matcher<any_type*, Next, Tail...> struct matcher<any_type*, Next, Tail...>
{ {
static bool match(util::utype_iterator &begin, static bool match(util::abstract_type_list::const_iterator& begin,
util::utype_iterator &end, util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* res = nullptr, std::vector<std::size_t>* res = nullptr,
std::size_t pos = 0) std::size_t pos = 0)
{ {
bool result = false; bool result = false;
while (!result) while (!result)
{ {
util::utype_iterator begin_cpy = begin; util::abstract_type_list::const_iterator begin_cpy = begin;
result = matcher<Next, Tail...>::match(begin_cpy,end,nullptr,pos); result = matcher<Next, Tail...>::match(begin_cpy,end,nullptr,pos);
if (!result) if (!result)
{ {
...@@ -86,8 +88,8 @@ struct matcher<any_type*, Next, Tail...> ...@@ -86,8 +88,8 @@ struct matcher<any_type*, Next, Tail...>
template<> template<>
struct matcher<any_type*> struct matcher<any_type*>
{ {
static bool match(util::utype_iterator&, static bool match(util::abstract_type_list::const_iterator&,
util::utype_iterator&, util::abstract_type_list::const_iterator&,
std::vector<std::size_t>* = nullptr, std::vector<std::size_t>* = nullptr,
std::size_t = 0) std::size_t = 0)
{ {
...@@ -98,8 +100,8 @@ struct matcher<any_type*> ...@@ -98,8 +100,8 @@ struct matcher<any_type*>
template<> template<>
struct matcher<> struct matcher<>
{ {
static bool match(util::utype_iterator& begin, static bool match(util::abstract_type_list::const_iterator& begin,
util::utype_iterator& end, util::abstract_type_list::const_iterator& end,
std::vector<std::size_t>* = nullptr, std::vector<std::size_t>* = nullptr,
std::size_t = 0) std::size_t = 0)
{ {
......
#ifndef MOCK_SCHEDULER_HPP
#define MOCK_SCHEDULER_HPP
#include "cppa/scheduler.hpp"
namespace cppa { namespace detail {
class mock_scheduler : public scheduler
{
public:
actor_ptr spawn(actor_behavior* behavior, scheduling_hint hint);
void await_all_done();
};
} } // namespace cppa::detail
#endif // MOCK_SCHEDULER_HPP
...@@ -16,7 +16,7 @@ struct serialize_tuple ...@@ -16,7 +16,7 @@ struct serialize_tuple
template<typename T> template<typename T>
inline static void _(serializer& s, const T* self) inline static void _(serializer& s, const T* self)
{ {
s << uniform_type_info<typename List::head_type>().name() s << uniform_typeid<typename List::head_type>()->name()
<< *reinterpret_cast<const typename List::head_type*>(self->at(Pos)); << *reinterpret_cast<const typename List::head_type*>(self->at(Pos));
serialize_tuple<typename List::tail_type, Pos + 1>::_(s, self); serialize_tuple<typename List::tail_type, Pos + 1>::_(s, self);
} }
......
#ifndef TO_UNIFORM_NAME_HPP
#define TO_UNIFORM_NAME_HPP
#include <string>
namespace cppa { namespace detail {
std::string to_uniform_name(const std::string& demangled_name);
} } // namespace cppa::detail
#endif // TO_UNIFORM_NAME_HPP
...@@ -75,7 +75,7 @@ class tuple_vals : public abstract_tuple ...@@ -75,7 +75,7 @@ class tuple_vals : public abstract_tuple
return tdata_at(m_data, pos); return tdata_at(m_data, pos);
} }
virtual const utype& utype_at(std::size_t pos) const virtual const uniform_type_info* utype_at(std::size_t pos) const
{ {
return m_types.at(pos); return m_types.at(pos);
} }
......
#ifndef UTYPE_IMPL_HPP
#define UTYPE_IMPL_HPP
#include <map>
#include <string>
#include "cppa/utype.hpp"
#include "cppa/detail/object_impl.hpp"
namespace cppa { namespace detail {
std::string demangle(const char*);
std::map<std::string, utype*>& uniform_types();
// default implementation of utype
template<typename T>
class utype_impl : public utype
{
const std::string m_name;
const std::type_info& m_native;
utype_impl() : m_name(demangle(typeid(T).name())), m_native(typeid(T))
{
(uniform_types())[m_name] = this;
}
public:
static const utype_impl instance;
std::uint8_t announce_helper() const { return 42; }
virtual object* create() const
{
return new obj_impl<T>;
}
virtual const std::string& name() const
{
return m_name;
}
virtual const std::type_info& native() const
{
return m_native;
}
};
template<typename A> const utype_impl<A> utype_impl<A>::instance;
} } // namespace cppa::detail
#endif // UTYPE_IMPL_HPP
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "cppa/util/compare_tuples.hpp" #include "cppa/util/compare_tuples.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/is_comparable.hpp" #include "cppa/util/is_comparable.hpp"
#include "cppa/util/utype_iterator.hpp"
#include "cppa/util/eval_type_lists.hpp" #include "cppa/util/eval_type_lists.hpp"
#include "cppa/util/filter_type_list.hpp" #include "cppa/util/filter_type_list.hpp"
...@@ -22,16 +21,16 @@ namespace cppa { ...@@ -22,16 +21,16 @@ namespace cppa {
template<typename... MatchRules> template<typename... MatchRules>
bool match(const untyped_tuple& what) bool match(const untyped_tuple& what)
{ {
util::utype_iterator begin = what.types().begin(); util::abstract_type_list::const_iterator begin = what.types().begin();
util::utype_iterator end = what.types().end(); util::abstract_type_list::const_iterator end = what.types().end();
return detail::matcher<MatchRules...>::match(begin, end); return detail::matcher<MatchRules...>::match(begin, end);
} }
template<typename... MatchRules> template<typename... MatchRules>
bool match(const untyped_tuple& what, std::vector<std::size_t>& mappings) bool match(const untyped_tuple& what, std::vector<std::size_t>& mappings)
{ {
util::utype_iterator begin = what.types().begin(); util::abstract_type_list::const_iterator begin = what.types().begin();
util::utype_iterator end = what.types().end(); util::abstract_type_list::const_iterator end = what.types().end();
return detail::matcher<MatchRules...>::match(begin, end, &mappings); return detail::matcher<MatchRules...>::match(begin, end, &mappings);
} }
...@@ -72,8 +71,8 @@ get_view(const Tuple<TupleTypes...>& t) ...@@ -72,8 +71,8 @@ get_view(const Tuple<TupleTypes...>& t)
util::type_list<TupleTypes...>>::value, util::type_list<TupleTypes...>>::value,
"MatchRules does not match Tuple"); "MatchRules does not match Tuple");
std::vector<std::size_t> mappings; std::vector<std::size_t> mappings;
util::utype_iterator begin = t.types().begin(); util::abstract_type_list::const_iterator begin = t.types().begin();
util::utype_iterator end = t.types().end(); util::abstract_type_list::const_iterator end = t.types().end();
if (detail::matcher<MatchRules...>::match(begin, end, &mappings)) if (detail::matcher<MatchRules...>::match(begin, end, &mappings))
{ {
return { t.vals(), std::move(mappings) }; return { t.vals(), std::move(mappings) };
......
#ifndef OBJECT_HPP #ifndef OBJECT_HPP
#define OBJECT_HPP #define OBJECT_HPP
#include <string>
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
namespace cppa { namespace cppa {
struct utype; class uniform_type_info;
class serializer; class serializer;
class deserializer; class deserializer;
struct object : public ref_counted class object : public ref_counted
{ {
public:
// mutators // mutators
virtual void* mutable_value() = 0; virtual void* mutable_value() = 0;
virtual void deserialize(deserializer&) = 0; virtual void deserialize(deserializer&) = 0;
virtual void from_string(const std::string&) = 0;
// accessors // accessors
virtual object* copy() const = 0; virtual object* copy() const = 0;
virtual const utype& type() const = 0; virtual const uniform_type_info* type() const = 0;
virtual const void* value() const = 0; virtual const void* value() const = 0;
virtual std::string to_string() const = 0;
virtual void serialize(serializer&) const = 0; virtual void serialize(serializer&) const = 0;
}; };
......
...@@ -6,17 +6,31 @@ ...@@ -6,17 +6,31 @@
#include "cppa/actor_behavior.hpp" #include "cppa/actor_behavior.hpp"
#include "cppa/scheduling_hint.hpp" #include "cppa/scheduling_hint.hpp"
namespace cppa { namespace detail { namespace cppa {
struct scheduler class scheduler
{ {
static actor_ptr spawn(actor_behavior*, scheduling_hint); public:
static context* get_context();
static void await_all_done(); 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;
}; };
} } // namespace cppa::detail scheduler* get_scheduler();
} // namespace cppa::detail
#endif // SCHEDULER_HPP #endif // SCHEDULER_HPP
...@@ -121,7 +121,7 @@ class tuple ...@@ -121,7 +121,7 @@ class tuple
const void* at(std::size_t p) const { return m_vals->at(p); } const void* at(std::size_t p) const { return m_vals->at(p); }
const utype& utype_at(std::size_t p) const { return m_vals->utype_at(p); } const uniform_type_info* utype_at(std::size_t p) const { return m_vals->utype_at(p); }
const util::abstract_type_list& types() const { return m_vals->types(); } const util::abstract_type_list& types() const { return m_vals->types(); }
......
...@@ -2,34 +2,156 @@ ...@@ -2,34 +2,156 @@
#define UNIFORM_TYPE_INFO_HPP #define UNIFORM_TYPE_INFO_HPP
#include <map> #include <map>
#include <vector>
#include <string> #include <string>
#include <cstdint> #include <cstdint>
#include <typeinfo> #include <typeinfo>
#include "cppa/utype.hpp"
#include "cppa/object.hpp" #include "cppa/object.hpp"
#include "cppa/serializer.hpp" #include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp" #include "cppa/deserializer.hpp"
#include "cppa/detail/utype_impl.hpp" #include "cppa/detail/demangle.hpp"
#include "cppa/detail/object_impl.hpp" #include "cppa/detail/to_uniform_name.hpp"
namespace cppa { namespace cppa {
/** /**
* @brief Get the uniform type information ({@link utype}) for @p T. * @brief Provides a platform independent type name and (very primitive)
* reflection in combination with {@link cppa::object object}.
*
* The platform dependent type name (from GCC or Microsofts VC++ Compiler) is
* translated to a (usually) shorter and platform independent name.
*
* This name is usually equal to the "in-sourcecode-name",
* with a few exceptions:
* - <i>std::string</i> is named <code>@str</code>
* - <i>std::wstring</i> is named <code>@wstr</code>
* - <i>integers</i> are named <code>@(i|u)$size</code>\n
* e.g.: @i32 is a 32 bit signed integer; @u16 is a 16 bit unsigned integer
* - <i>anonymous namespace</i> is named <b>@_</b>\n
* e.g.: <code>namespace { class foo { }; }</code> is mapped to
* <code>@_::foo</code>
*/ */
class uniform_type_info : cppa::detail::comparable<uniform_type_info>
{
template<typename T> friend uniform_type_info* uniform_typeid();
public:
class identifier : cppa::detail::comparable<identifier>
{
friend class uniform_type_info;
friend class cppa::detail::comparable<identifier>;
int m_value;
identifier(int val) : m_value(val) { }
// enable default copy and move constructors
identifier(identifier&&) = default;
identifier(const identifier&) = default;
// disable any assignment
identifier& operator=(identifier&&) = delete;
identifier& operator=(const identifier&) = delete;
public:
inline int compare(const identifier& other) const
{
return m_value - other.m_value;
}
};
private:
// unique identifier
identifier m_id;
// uniform type name
std::string m_name;
// prohibit all default constructors
uniform_type_info() = delete;
uniform_type_info(uniform_type_info&&) = delete;
uniform_type_info(const uniform_type_info&) = delete;
// prohibit all assignment operators
uniform_type_info& operator=(uniform_type_info&&) = delete;
uniform_type_info& operator=(const uniform_type_info&) = delete;
static uniform_type_info* by_type_info(const std::type_info& tinfo);
protected:
uniform_type_info(const std::string& uniform_type_name);
public:
virtual ~uniform_type_info();
inline const std::string& name() const { return m_name; }
inline const identifier& id() const { return m_id; }
inline int compare(const uniform_type_info& other) const
{
return id().compare(other.id());
}
virtual object* create() const = 0;
static uniform_type_info* by_uniform_name(const std::string& uniform_name);
static bool announce(const std::type_info& plain_type,
uniform_type_info* uniform_type);
template<class ObjectImpl>
static bool announce(const std::type_info& plain_type);
static std::vector<uniform_type_info*> get_all();
};
template<typename T> template<typename T>
const utype& uniform_type_info() uniform_type_info* uniform_typeid()
{ {
return detail::utype_impl<T>::instance; return uniform_type_info::by_type_info(typeid(T));
} }
/** namespace detail {
* @brief Get the uniform type information ({@link utype}) associated with
* the name @p uniform_type_name. template<class ObjectImpl>
*/ class default_uniform_type_info_impl : public uniform_type_info
const utype& uniform_type_info(const std::string& uniform_type_name); {
public:
default_uniform_type_info_impl(const std::string& tname)
: uniform_type_info(tname)
{
}
object* create /*[[override]]*/ () const
{
return new ObjectImpl(this);
}
};
} // namespace detail
template<class ObjImpl>
bool uniform_type_info::announce(const std::type_info& plain)
{
std::string uname = detail::to_uniform_name(detail::demangle(plain.name()));
return announce(plain,
new detail::default_uniform_type_info_impl<ObjImpl>(uname));
}
} // namespace cppa } // namespace cppa
...@@ -37,15 +159,17 @@ const utype& uniform_type_info(const std::string& uniform_type_name); ...@@ -37,15 +159,17 @@ const utype& uniform_type_info(const std::string& uniform_type_name);
#define CPPA_CONCAT_I(lhs, rhs) CPPA_CONCAT_II(lhs ## rhs) #define CPPA_CONCAT_I(lhs, rhs) CPPA_CONCAT_II(lhs ## rhs)
#define CPPA_CONCAT(lhs, rhs) CPPA_CONCAT_I( lhs, rhs ) #define CPPA_CONCAT(lhs, rhs) CPPA_CONCAT_I( lhs, rhs )
/*
#ifdef __GNUC__ #ifdef __GNUC__
# define CPPA_ANNOUNCE(what) \ # define CPPA_ANNOUNCE(what) \
static const std::uint8_t CPPA_CONCAT( __unused_val , __LINE__ ) \ static const std::uint8_t CPPA_CONCAT( __unused_val , __LINE__ ) \
__attribute__ ((unused)) \ __attribute__ ((unused)) \
= cppa::detail::utype_impl< what >::instance.announce_helper() = cppa::detail::utype_impl< what >::announce_helper()
#else #else
# define CPPA_ANNOUNCE(what) \ # define CPPA_ANNOUNCE(what) \
static const std::uint8_t CPPA_CONCAT( __unused_val , __LINE__ ) \ static const std::uint8_t CPPA_CONCAT( __unused_val , __LINE__ ) \
= cppa::detail::utype_impl< what >::instance.announce_helper() = cppa::detail::utype_impl< what >::announce_helper()
#endif #endif
*/
#endif // UNIFORM_TYPE_INFO_HPP #endif // UNIFORM_TYPE_INFO_HPP
...@@ -28,7 +28,7 @@ class untyped_tuple ...@@ -28,7 +28,7 @@ class untyped_tuple
const void* at(std::size_t p) const { return m_vals->at(p); } const void* at(std::size_t p) const { return m_vals->at(p); }
const utype& utype_at(std::size_t p) const { return m_vals->utype_at(p); } const uniform_type_info* utype_at(std::size_t p) const { return m_vals->utype_at(p); }
const util::abstract_type_list& types() const { return m_vals->types(); } const util::abstract_type_list& types() const { return m_vals->types(); }
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#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"
#include "cppa/util/type_list_pop_back.hpp" #include "cppa/util/type_list_pop_back.hpp"
#include "cppa/util/utype_iterator.hpp"
#include "cppa/util/void_type.hpp" #include "cppa/util/void_type.hpp"
#endif // UTIL_HPP #endif // UTIL_HPP
#ifndef ABSTRACT_TYPE_LIST_HPP #ifndef ABSTRACT_TYPE_LIST_HPP
#define ABSTRACT_TYPE_LIST_HPP #define ABSTRACT_TYPE_LIST_HPP
#include "cppa/util/utype_iterator.hpp" #include <iterator>
#include "cppa/uniform_type_info.hpp"
namespace cppa { class serializer; } namespace cppa { class serializer; }
...@@ -10,9 +11,69 @@ namespace cppa { namespace util { ...@@ -10,9 +11,69 @@ namespace cppa { namespace util {
struct abstract_type_list struct abstract_type_list
{ {
typedef utype_iterator iterator; class const_iterator : public std::iterator<std::bidirectional_iterator_tag,
const uniform_type_info*>
{
typedef utype_iterator const_iterator; const uniform_type_info* const* p;
public:
inline const_iterator(const uniform_type_info* const* x = nullptr) : p(x) { }
const_iterator(const_iterator&&) = default;
const_iterator(const const_iterator&) = default;
const_iterator& operator=(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 const uniform_type_info* operator*()
{
return *p;
}
inline const uniform_type_info* const* operator->()
{
return p;
}
inline const_iterator& operator++()
{
++p;
return *this;
}
inline const_iterator operator++(int)
{
const_iterator tmp(*this);
operator++();
return tmp;
}
inline const_iterator& operator--()
{
--p;
return *this;
}
inline const_iterator operator--(int)
{
const_iterator tmp(*this);
operator--();
return tmp;
}
};
virtual abstract_type_list* copy() const = 0; virtual abstract_type_list* copy() const = 0;
...@@ -20,7 +81,7 @@ struct abstract_type_list ...@@ -20,7 +81,7 @@ struct abstract_type_list
virtual const_iterator end() const = 0; virtual const_iterator end() const = 0;
virtual const utype& at(std::size_t pos) const = 0; virtual const uniform_type_info* at(std::size_t pos) const = 0;
}; };
......
#ifndef DEFAULT_OBJECT_BASE_HPP
#define DEFAULT_OBJECT_BASE_HPP
#include "cppa/object.hpp"
#include "cppa/uniform_type_info.hpp"
namespace cppa { namespace util {
template<typename T>
class default_object_base : public object
{
const uniform_type_info* m_type;
protected:
T m_value;
public:
default_object_base(const uniform_type_info* uti, const T& val = T())
: m_type(uti), m_value(val)
{
}
// mutators
void* mutable_value /*[[override]]*/ ()
{
return &m_value;
}
const uniform_type_info* type /*[[override]]*/ () const
{
return m_type;
}
const void* value /*[[override]]*/ () const
{
return &m_value;
}
};
} } // namespace cppa::util
#endif // DEFAULT_OBJECT_BASE_HPP
...@@ -65,18 +65,11 @@ class single_reader_queue ...@@ -65,18 +65,11 @@ class single_reader_queue
{ {
auto p = list.take(); auto p = list.take();
if (p.first) if (p.first)
{
if (p.first == p.second)
{
push_front(p.first);
}
else
{ {
push_front(p.first, p.second); push_front(p.first, p.second);
} }
} }
} }
}
void push_back(element_type* new_element) void push_back(element_type* new_element)
{ {
...@@ -103,6 +96,9 @@ class single_reader_queue ...@@ -103,6 +96,9 @@ class single_reader_queue
} }
} }
/**
* @warning call only from the reader (owner)
*/
bool empty() bool empty()
{ {
return !m_head && !(m_tail.load()); return !m_head && !(m_tail.load());
......
...@@ -41,14 +41,9 @@ struct type_list<Head, Tail...> : abstract_type_list ...@@ -41,14 +41,9 @@ struct type_list<Head, Tail...> : abstract_type_list
return m_arr + type_list_size; return m_arr + type_list_size;
} }
const utype& operator[](std::size_t pos) const virtual const uniform_type_info* at(std::size_t pos) const
{ {
return *m_arr[pos]; return m_arr[pos];
}
virtual const utype& at(std::size_t pos) const
{
return *m_arr[pos];
} }
virtual type_list* copy() const virtual type_list* copy() const
...@@ -57,19 +52,27 @@ struct type_list<Head, Tail...> : abstract_type_list ...@@ -57,19 +52,27 @@ struct type_list<Head, Tail...> : abstract_type_list
} }
template<typename TypeList> template<typename TypeList>
static void init(const utype** what) static void init(const uniform_type_info** what)
{
what[0] = uniform_typeid<typename TypeList::head_type>();
if (TypeList::type_list_size > 1)
{ {
++what;
init<typename TypeList::tail_type>(what);
}
/*
what[0] = &uniform_type_info<typename TypeList::head_type>(); what[0] = &uniform_type_info<typename TypeList::head_type>();
if (TypeList::type_list_size > 1) if (TypeList::type_list_size > 1)
{ {
++what; ++what;
init<typename TypeList::tail_type>(what); init<typename TypeList::tail_type>(what);
} }
*/
} }
private: private:
const utype* m_arr[type_list_size]; const uniform_type_info* m_arr[type_list_size];
}; };
......
#ifndef UTYPE_ITERATOR_HPP
#define UTYPE_ITERATOR_HPP
#include "cppa/uniform_type_info.hpp"
namespace cppa { namespace util {
struct utype_iterator
{
typedef const utype* const* arr_ptr;
arr_ptr m_pos;
public:
utype_iterator(arr_ptr p) : m_pos(p) { }
inline utype_iterator& operator++()
{
++m_pos;
return *this;
}
inline bool operator==(const utype_iterator& other) const
{
return m_pos == other.m_pos;
}
inline bool operator!=(const utype_iterator& other) const
{
return !(*this == other);
}
inline const utype& operator*()
{
return *m_pos[0];
}
inline const utype* operator->()
{
return m_pos[0];
}
};
} } // namespace cppa::util
#endif // UTYPE_ITERATOR_HPP
#ifndef UTYPE_HPP
#define UTYPE_HPP
#include <string>
#include <typeinfo>
#include "cppa/object.hpp"
#include "cppa/detail/comparable.hpp"
namespace cppa {
/**
* @brief Uniform type information.
*/
struct utype : detail::comparable<utype>,
detail::comparable<utype, std::type_info>
{
/**
* @brief Create an object of this type, initialized with
* the default constructor.
*/
virtual object* create() const = 0;
/**
* @brief Get the uniform type name (equal on all supported plattforms).
*/
virtual const std::string& name() const = 0;
/**
* @brief Get the result of typeid(T) where T is the native type.
*/
virtual const std::type_info& native() const = 0;
inline bool equal_to(const std::type_info& what) const
{
return native() == what;
}
inline bool equal_to(const utype& what) const
{
return native() == what.native();
}
};
} // namespace cppa
#endif // UTYPE_HPP
...@@ -7,28 +7,38 @@ INCLUDES = -I./ ...@@ -7,28 +7,38 @@ INCLUDES = -I./
HEADERS = cppa/actor.hpp \ HEADERS = cppa/actor.hpp \
cppa/any_type.hpp \ cppa/any_type.hpp \
cppa/config.hpp \ cppa/config.hpp \
cppa/context.hpp \
cppa/cow_ptr.hpp \ cppa/cow_ptr.hpp \
cppa/cppa.hpp \
cppa/deserializer.hpp \
cppa/get.hpp \ cppa/get.hpp \
cppa/group.hpp \
cppa/intrusive_ptr.hpp \ cppa/intrusive_ptr.hpp \
cppa/invoke.hpp \ cppa/invoke.hpp \
cppa/invoke_rules.hpp \ cppa/invoke_rules.hpp \
cppa/match.hpp \ cppa/match.hpp \
cppa/message.hpp \ cppa/message.hpp \
cppa/message_queue.hpp \
cppa/object.hpp \
cppa/on.hpp \ cppa/on.hpp \
cppa/ref_counted.hpp \ cppa/ref_counted.hpp \
cppa/scheduler.hpp \
cppa/scheduling_hint.hpp \
cppa/serializer.hpp \
cppa/tuple.hpp \ cppa/tuple.hpp \
cppa/tuple_view.hpp \ cppa/tuple_view.hpp \
cppa/uniform_type_info.hpp \ cppa/uniform_type_info.hpp \
cppa/untyped_tuple.hpp \ cppa/untyped_tuple.hpp \
cppa/util.hpp \ cppa/util.hpp \
cppa/detail/abstract_tuple.hpp \ cppa/detail/abstract_tuple.hpp \
cppa/detail/blocking_message_queue.hpp \
cppa/detail/converted_thread_context.hpp \
cppa/detail/decorated_tuple.hpp \ cppa/detail/decorated_tuple.hpp \
cppa/detail/channel.hpp \ cppa/detail/channel.hpp \
cppa/detail/intermediate.hpp \ cppa/detail/intermediate.hpp \
cppa/detail/invokable.hpp \ cppa/detail/invokable.hpp \
cppa/detail/matcher.hpp \ cppa/detail/matcher.hpp \
cppa/detail/ref_counted_impl.hpp \ cppa/detail/ref_counted_impl.hpp \
cppa/detail/scheduler.hpp \
cppa/detail/tdata.hpp \ cppa/detail/tdata.hpp \
cppa/detail/tuple_vals.hpp \ cppa/detail/tuple_vals.hpp \
cppa/util/a_matches_b.hpp \ cppa/util/a_matches_b.hpp \
...@@ -51,15 +61,20 @@ HEADERS = cppa/actor.hpp \ ...@@ -51,15 +61,20 @@ HEADERS = cppa/actor.hpp \
cppa/util/type_list.hpp \ cppa/util/type_list.hpp \
cppa/util/type_list_apply.hpp \ cppa/util/type_list_apply.hpp \
cppa/util/type_list_pop_back.hpp \ cppa/util/type_list_pop_back.hpp \
cppa/util/utype_iterator.hpp \
cppa/util/void_type.hpp cppa/util/void_type.hpp
SOURCES = src/actor_behavior.cpp \ SOURCES = src/actor_behavior.cpp \
src/blocking_message_queue.cpp \
src/channel.cpp \ src/channel.cpp \
src/context.cpp \
src/converted_thread_context.cpp \
src/demangle.cpp \
src/deserializer.cpp \ src/deserializer.cpp \
src/group.cpp \ src/group.cpp \
src/mock_scheduler.cpp \ src/mock_scheduler.cpp \
src/scheduler.cpp \
src/serializer.cpp \ src/serializer.cpp \
src/to_uniform_name.cpp \
src/uniform_type_info.cpp \ src/uniform_type_info.cpp \
src/untyped_tuple.cpp src/untyped_tuple.cpp
......
#include "cppa/invoke_rules.hpp"
#include "cppa/util/singly_linked_list.hpp"
#include "cppa/detail/intermediate.hpp"
#include "cppa/detail/blocking_message_queue.hpp"
namespace cppa { namespace detail {
void blocking_message_queue::enqueue(const message& msg)
{
m_queue.push_back(new queue_node(msg));
}
const message& blocking_message_queue::dequeue()
{
queue_node* msg = m_queue.pop();
m_last_dequeued = std::move(msg->msg);
delete msg;
return m_last_dequeued;
}
void blocking_message_queue::dequeue(invoke_rules& rules)
{
queue_node* amsg = m_queue.pop();
util::singly_linked_list<queue_node> buffer;
intrusive_ptr<detail::intermediate> imd;
while (!(imd = rules.get_intermediate(amsg->msg.data())))
{
buffer.push_back(amsg);
amsg = m_queue.pop();
}
m_last_dequeued = amsg->msg;
if (!buffer.empty()) m_queue.push_front(std::move(buffer));
imd->invoke();
delete amsg;
}
bool blocking_message_queue::try_dequeue(message& msg)
{
if (!m_queue.empty())
{
msg = dequeue();
return true;
}
return false;
}
bool blocking_message_queue::try_dequeue(invoke_rules& rules)
{
if (!m_queue.empty())
{
dequeue(rules);
return true;
}
return false;
}
const message& blocking_message_queue::last_dequeued()
{
return m_last_dequeued;
}
} } // namespace hamcast::detail
#include "cppa/context.hpp"
#include "cppa/message.hpp"
#include "cppa/detail/converted_thread_context.hpp"
#include <boost/thread.hpp>
namespace {
void cleanup_fun(cppa::context* what)
{
if (what && !what->deref()) delete what;
}
boost::thread_specific_ptr<cppa::context> m_this_context(cleanup_fun);
} // namespace <anonymous>
namespace cppa {
void context::enqueue(const message& 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;
}
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);
}
}
} // namespace cppa
#include "cppa/detail/converted_thread_context.hpp"
namespace cppa { namespace detail {
void converted_thread_context::link(intrusive_ptr<actor>& other)
{
std::lock_guard<std::mutex> guard(m_mtx);
if (other && !m_exited && other->establish_backlink(this))
{
m_links.insert(other);
}
}
bool converted_thread_context::remove_backlink(const intrusive_ptr<actor>& other)
{
if (other && other != this)
{
std::lock_guard<std::mutex> guard(m_mtx);
return m_links.erase(other) > 0;
}
return false;
}
bool converted_thread_context::establish_backlink(const intrusive_ptr<actor>& other)
{
if (other && other != this)
{
std::lock_guard<std::mutex> guard(m_mtx);
return m_links.insert(other).second;
}
return false;
}
void converted_thread_context::unlink(intrusive_ptr<actor>& other)
{
std::lock_guard<std::mutex> guard(m_mtx);
if (other && !m_exited && other->remove_backlink(this))
{
m_links.erase(other);
}
}
void converted_thread_context::join(group_ptr& what)
{
std::lock_guard<std::mutex> guard(m_mtx);
if (!m_exited && m_subscriptions.count(what) == 0)
{
m_subscriptions[what] = what->subscribe(this);
}
}
void converted_thread_context::leave(const group_ptr& what)
{
std::lock_guard<std::mutex> guard(m_mtx);
m_subscriptions.erase(what);
}
message_queue& converted_thread_context::mailbox()
{
return m_mailbox;
}
} } // namespace cppa::detail
#include <stdexcept>
#include "cppa/config.hpp"
#include "cppa/detail/demangle.hpp"
#ifdef CPPA_GCC
#include <cxxabi.h>
#endif
namespace cppa { namespace detail {
std::string demangle(const char* typeid_name)
{
size_t size;
int status;
char* undecorated = abi::__cxa_demangle(typeid_name, NULL, &size, &status);
if (status != 0)
{
std::string error_msg = "Could not demangle type name ";
error_msg += typeid_name;
throw std::logic_error(error_msg);
}
std::string result; // the undecorated typeid name
result.reserve(size);
const char* cstr = undecorated;
// this loop filter unnecessary characters from undecorated
for (char c = *cstr; c != '\0'; c = *++cstr)
{
if (c == ' ')
{
char previous_c = result.empty() ? ' ' : *(result.rbegin());
// get next non-space character
do { c = *++cstr; } while (c == ' ');
// skip whitespace unless it separates two alphanumeric
// characters (such as in "unsigned int")
if (isalnum(c) && isalnum(previous_c))
{
result += ' ';
result += c;
}
else
{
result += c;
}
}
else
{
result += c;
}
}
free(undecorated);
return result;
}
} } // namespace cppa::detail
#include "cppa/config.hpp"
#include <set> #include <set>
#include <map> #include <map>
#ifdef __APPLE__
#include "cppa/detail/cpp0x_thread_wrapper.hpp"
#else
#include <thread> #include <thread>
#endif
// for thread_specific_ptr // for thread_specific_ptr
// needed unless the new keyword "thread_local" works in GCC // needed unless the new keyword "thread_local" works in GCC
...@@ -14,201 +11,29 @@ ...@@ -14,201 +11,29 @@
#include "cppa/message.hpp" #include "cppa/message.hpp"
#include "cppa/context.hpp" #include "cppa/context.hpp"
#include "cppa/invoke_rules.hpp" #include "cppa/invoke_rules.hpp"
#include "cppa/detail/scheduler.hpp" #include "cppa/scheduler.hpp"
#include "cppa/detail/mock_scheduler.hpp"
#include "cppa/util/singly_linked_list.hpp"
#include "cppa/util/single_reader_queue.hpp"
using namespace cppa; #include "cppa/detail/converted_thread_context.hpp"
namespace { namespace {
struct actor_message
{
actor_message* next;
message msg;
actor_message(const message& from) : next(0), msg(from) { }
};
struct actor_impl;
void cleanup_fun(context* what);
boost::thread_specific_ptr<context> m_this_context(cleanup_fun);
struct mbox : message_queue
{
message m_last_dequeued;
util::single_reader_queue<actor_message> m_impl;
void enqueue(const message& msg)
{
m_impl.push_back(new actor_message(msg));
}
virtual const message& dequeue()
{
actor_message* msg = m_impl.pop();
m_last_dequeued = std::move(msg->msg);
delete msg;
return m_last_dequeued;
}
virtual void dequeue(invoke_rules& rules)
{
actor_message* amsg = m_impl.pop();
util::singly_linked_list<actor_message> buffer;
intrusive_ptr<detail::intermediate> imd;
while (!(imd = rules.get_intermediate(amsg->msg.data())))
{
buffer.push_back(amsg);
amsg = m_impl.pop();
}
m_last_dequeued = amsg->msg;
if (!buffer.empty()) m_impl.push_front(std::move(buffer));
imd->invoke();
delete amsg;
}
virtual bool try_dequeue(message& msg)
{
if (!m_impl.empty())
{
msg = dequeue();
return true;
}
return false;
}
virtual bool try_dequeue(invoke_rules& rules)
{
if (!m_impl.empty())
{
dequeue(rules);
return true;
}
return false;
}
virtual const message& last_dequeued()
{
return m_last_dequeued;
}
};
struct actor_impl : context
{
actor_behavior* m_behavior;
bool m_exited;
// guards m_exited, m_grp_lst and m_links
boost::mutex m_mtx;
std::map<group_ptr, intrusive_ptr<group::subscription> > m_grp_lst;
std::set<actor_ptr> m_links;
mbox m_mbox;
actor_impl(actor_behavior* b = nullptr) : m_behavior(b), m_exited(false) { }
~actor_impl()
{
if (m_behavior) delete m_behavior;
}
virtual void enqueue(const message& msg)
{
m_mbox.enqueue(msg);
}
virtual void link(intrusive_ptr<actor>& other)
{
boost::mutex::scoped_lock guard(m_mtx);
if (other && !m_exited && other->establish_backlink(this))
{
m_links.insert(other);
}
}
virtual bool remove_backlink(const intrusive_ptr<actor>& other)
{
if (other && other != this)
{
boost::mutex::scoped_lock guard(m_mtx);
return m_links.erase(other) > 0;
}
return false;
}
virtual bool establish_backlink(const intrusive_ptr<actor>& other)
{
if (other && other != this)
{
boost::mutex::scoped_lock guard(m_mtx);
return m_links.insert(other).second;
}
return false;
}
virtual void unlink(intrusive_ptr<actor>& other)
{
boost::mutex::scoped_lock guard(m_mtx);
if (other && !m_exited && other->remove_backlink(this))
{
m_links.erase(other);
}
}
virtual void join(group_ptr& what)
{
boost::mutex::scoped_lock guard(m_mtx);
if (!m_exited && m_grp_lst.count(what) == 0)
{
m_grp_lst[what] = what->subscribe(this);
}
}
virtual void leave(const group_ptr& what)
{
boost::mutex::scoped_lock guard(m_mtx);
m_grp_lst.erase(what);
}
virtual message_queue& mailbox()
{
return m_mbox;
}
};
void cleanup_fun(context* what)
{
if (what && !what->deref()) delete what;
}
std::atomic<int> m_running_actors(0); std::atomic<int> m_running_actors(0);
boost::mutex m_ra_mtx; boost::mutex m_ra_mtx;
boost::condition_variable m_ra_cv; boost::condition_variable m_ra_cv;
void run_actor_impl(intrusive_ptr<actor_impl> m_impl) void run_actor(cppa::intrusive_ptr<cppa::context> m_self,
cppa::actor_behavior* behavior)
{ {
{ cppa::set_self(m_self.get());
actor_impl* self_ptr = m_impl.get(); if (behavior)
self_ptr->ref();
m_this_context.reset(self_ptr);
}
actor_behavior* ab = m_impl->m_behavior;
if (ab)
{ {
try try
{ {
ab->act(); behavior->act();
} }
catch(...) { } catch(...) { }
ab->on_exit(); behavior->on_exit();
} }
if (--m_running_actors == 0) if (--m_running_actors == 0)
{ {
...@@ -221,27 +46,15 @@ void run_actor_impl(intrusive_ptr<actor_impl> m_impl) ...@@ -221,27 +46,15 @@ void run_actor_impl(intrusive_ptr<actor_impl> m_impl)
namespace cppa { namespace detail { namespace cppa { namespace detail {
actor_ptr scheduler::spawn(actor_behavior* ab, scheduling_hint) actor_ptr mock_scheduler::spawn(actor_behavior* ab, scheduling_hint)
{ {
++m_running_actors; ++m_running_actors;
intrusive_ptr<actor_impl> result(new actor_impl(ab)); intrusive_ptr<context> ctx(new detail::converted_thread_context);
boost::thread(run_actor_impl, result).detach(); boost::thread(run_actor, ctx, ab).detach();
return result; return ctx;
}
context* scheduler::get_context()
{
context* result = m_this_context.get();
if (!result)
{
result = new actor_impl;
result->ref();
m_this_context.reset(result);
}
return result;
} }
void scheduler::await_all_done() void mock_scheduler::await_all_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() > 0)
......
#include <atomic>
#define _GLIBCXX_HAS_GTHREADS
#include <mutex>
#include "cppa/scheduler.hpp"
#include "cppa/detail/mock_scheduler.hpp"
namespace {
std::mutex m_instance_mtx;
std::atomic<cppa::scheduler*> m_instance;
}
namespace cppa {
scheduler::~scheduler() { }
scheduler* get_scheduler()
{
scheduler* result = m_instance.load();
if (!result)
{
std::lock_guard<std::mutex> lock(m_instance_mtx);
result = m_instance.load();
if (!result)
{
result = new detail::mock_scheduler;
m_instance.store(result);
}
}
return result;
}
} // namespace cppa
#include <map>
#include <cwchar>
#include <limits>
#include <vector>
#include <typeinfo>
#include <stdexcept>
#include <algorithm>
#include "cppa/detail/demangle.hpp"
#include "cppa/detail/to_uniform_name.hpp"
namespace {
constexpr const char* mapped_int_names[][2] =
{
{ nullptr, nullptr }, // sizeof 0 { invalid }
{ "@i8", "@u8" }, // sizeof 1 -> signed / unsigned int8
{ "@i16", "@u16" }, // sizeof 2 -> signed / unsigned int16
{ nullptr, nullptr }, // sizeof 3 { invalid }
{ "@i32", "@u32" }, // sizeof 4 -> signed / unsigned int32
{ nullptr, nullptr }, // sizeof 5 { invalid }
{ nullptr, nullptr }, // sizeof 6 { invalid }
{ nullptr, nullptr }, // sizeof 7 { invalid }
{ "@i64", "@u64" } // sizeof 8 -> signed / unsigned int64
};
template<typename T>
constexpr size_t sign_index()
{
static_assert(std::numeric_limits<T>::is_integer, "T is not an integer");
return std::numeric_limits<T>::is_signed ? 0 : 1;
}
template<typename T>
inline std::string demangled()
{
return cppa::detail::demangle(typeid(T).name());
}
template<typename T>
constexpr const char* mapped_int_name()
{
return mapped_int_names[sizeof(T)][sign_index<T>()];
}
template<typename Iterator>
std::string to_uniform_name_impl(Iterator begin, Iterator end,
bool first_run = false)
{
// all integer type names as uniform representation
static std::map<std::string, std::string> mapped_demangled_names =
{
{ demangled<char>(), mapped_int_name<char>() },
{ demangled<signed char>(), mapped_int_name<signed char>() },
{ demangled<unsigned char>(), mapped_int_name<unsigned char>() },
{ demangled<short>(), mapped_int_name<short>() },
{ demangled<signed short>(), mapped_int_name<signed short>() },
{ demangled<unsigned short>(), mapped_int_name<unsigned short>() },
{ demangled<short int>(), mapped_int_name<short int>() },
{ demangled<signed short int>(), mapped_int_name<signed short int>() },
{ demangled<unsigned short int>(), mapped_int_name<unsigned short int>()},
{ demangled<int>(), mapped_int_name<int>() },
{ demangled<signed int>(), mapped_int_name<signed int>() },
{ demangled<unsigned int>(), mapped_int_name<unsigned int>() },
{ demangled<long int>(), mapped_int_name<long int>() },
{ demangled<signed long int>(), mapped_int_name<signed long int>() },
{ demangled<unsigned long int>(), mapped_int_name<unsigned long int>() },
{ demangled<long>(), mapped_int_name<long>() },
{ demangled<signed long>(), mapped_int_name<signed long>() },
{ demangled<unsigned long>(), mapped_int_name<unsigned long>() },
{ demangled<long long>(), mapped_int_name<long long>() },
{ demangled<signed long long>(), mapped_int_name<signed long long>() },
{ demangled<unsigned long long>(), mapped_int_name<unsigned long long>()},
{ demangled<wchar_t>(), mapped_int_name<wchar_t>() },
{ demangled<char16_t>(), mapped_int_name<char16_t>() },
{ demangled<char32_t>(), mapped_int_name<char32_t>() },
{ demangled<std::wstring>(), "@wstr" },
{ demangled<std::string>(), "@str" }
};
// check if we could find the whole string in our lookup map
if (first_run)
{
std::string tmp(begin, end);
auto i = mapped_demangled_names.find(tmp);
if (i != mapped_demangled_names.end())
{
return i->second;
}
}
// does [begin, end) represents an empty string?
if (begin == end) return "";
// derived reverse_iterator type
typedef std::reverse_iterator<Iterator> reverse_iterator;
// a subsequence [begin', end') within [begin, end)
typedef std::pair<Iterator, Iterator> subseq;
std::vector<subseq> substrings;
// explode string if we got a list of types
int open_brackets = 0; // counts "open" '<'
// denotes the begin of a possible subsequence
Iterator anchor = begin;
for (Iterator i = begin; i != end; /* i is incemented in the loop */)
{
switch (*i)
{
case '<':
++open_brackets;
++i;
break;
case '>':
if (--open_brackets < 0)
{
throw std::runtime_error("malformed string");
}
++i;
break;
case ',':
if (open_brackets == 0)
{
substrings.push_back(std::make_pair(anchor, i));
++i;
anchor = i;
}
else
{
++i;
}
break;
default:
++i;
break;
}
}
// call recursively for each list argument
if (!substrings.empty())
{
std::string result;
substrings.push_back(std::make_pair(anchor, end));
for (const subseq& sstr : substrings)
{
if (!result.empty()) result += ",";
result += to_uniform_name_impl(sstr.first, sstr.second);
}
return result;
}
// we didn't got a list, compute unify name
else
{
// is [begin, end) a template?
Iterator substr_begin = std::find(begin, end, '<');
if (substr_begin == end)
{
// not a template, return mapping
std::string arg(begin, end);
auto mapped = mapped_demangled_names.find(arg);
return (mapped == mapped_demangled_names.end()) ? arg : mapped->second;
}
// skip leading '<'
++substr_begin;
// find trailing '>'
Iterator substr_end = std::find(reverse_iterator(end),
reverse_iterator(substr_begin),
'>')
// get as an Iterator
.base();
// skip trailing '>'
--substr_end;
if (substr_end == substr_begin)
{
throw std::runtime_error("substr_end == substr_begin");
}
std::string result;
// template name (part before leading '<')
result.append(begin, substr_begin);
// get mappings of all template parameter(s)
result += to_uniform_name_impl(substr_begin, substr_end);
result.append(substr_end, end);
return result;
}
}
} // namespace <anonymous>
namespace cppa { namespace detail {
std::string to_uniform_name(const std::string& dname)
{
static std::string an = "(anonymous namespace)";
static std::string an_replacement = "@_";
auto r = to_uniform_name_impl(dname.begin(), dname.end(), true);
// replace all occurrences of an with "@_"
if (r.size() > an.size())
{
auto i = std::search(r.begin(), r.end(), an.begin(), an.end());
while (i != r.end())
{
auto substr_end = i + an.size();
r.replace(i, substr_end, an_replacement);
// next iteration
i = std::search(r.begin(), r.end(), an.begin(), an.end());
}
}
return r;
}
} } // namespace cppa::detail
This diff is collapsed.
...@@ -14,7 +14,7 @@ struct empty_type_list : cppa::util::abstract_type_list ...@@ -14,7 +14,7 @@ struct empty_type_list : cppa::util::abstract_type_list
virtual const_iterator end() const { return 0; } virtual const_iterator end() const { return 0; }
virtual const cppa::utype& at(std::size_t) const virtual const cppa::uniform_type_info* at(std::size_t) const
{ {
throw std::range_error("empty_type_list::at()"); throw std::range_error("empty_type_list::at()");
} }
...@@ -40,7 +40,7 @@ struct empty_tuple : cppa::detail::abstract_tuple ...@@ -40,7 +40,7 @@ struct empty_tuple : cppa::detail::abstract_tuple
throw std::range_error("empty_tuple::at()"); throw std::range_error("empty_tuple::at()");
} }
virtual const cppa::utype& utype_at(std::size_t) const virtual const cppa::uniform_type_info* utype_at(std::size_t) const
{ {
throw std::range_error("empty_tuple::utype_at()"); throw std::range_error("empty_tuple::utype_at()");
} }
......
...@@ -22,6 +22,7 @@ SOURCES = hash_of.cpp \ ...@@ -22,6 +22,7 @@ SOURCES = hash_of.cpp \
test__serialization.cpp \ test__serialization.cpp \
test__spawn.cpp \ test__spawn.cpp \
test__tuple.cpp \ test__tuple.cpp \
test__uniform_type.cpp \
test__type_list.cpp test__type_list.cpp
OBJECTS = $(SOURCES:.cpp=.o) OBJECTS = $(SOURCES:.cpp=.o)
......
...@@ -54,14 +54,15 @@ int main(int argc, char** c_argv) ...@@ -54,14 +54,15 @@ int main(int argc, char** c_argv)
{ {
std::cout << std::boolalpha; std::cout << std::boolalpha;
std::size_t errors = 0; std::size_t errors = 0;
RUN_TEST(test__a_matches_b); RUN_TEST(test__uniform_type);
RUN_TEST(test__intrusive_ptr); RUN_TEST(test__intrusive_ptr);
RUN_TEST(test__spawn); RUN_TEST(test__a_matches_b);
RUN_TEST(test__tuple);
RUN_TEST(test__type_list); RUN_TEST(test__type_list);
RUN_TEST(test__tuple);
RUN_TEST(test__serialization); RUN_TEST(test__serialization);
RUN_TEST(test__atom); RUN_TEST(test__spawn);
RUN_TEST(test__local_group); RUN_TEST(test__local_group);
RUN_TEST(test__atom);
cout << endl cout << endl
<< "error(s) in all tests: " << errors << "error(s) in all tests: " << errors
<< endl; << endl;
......
...@@ -13,8 +13,7 @@ struct cppa_test_scope \ ...@@ -13,8 +13,7 @@ struct cppa_test_scope \
{ \ { \
std::cout << error_count << " error(s) detected" << std::endl; \ std::cout << error_count << " error(s) detected" << std::endl; \
} \ } \
} cppa_ts; \ } cppa_ts;
std::size_t& error_count = cppa_ts.error_count
#define CPPA_TEST_RESULT cppa_ts.error_count #define CPPA_TEST_RESULT cppa_ts.error_count
...@@ -23,7 +22,7 @@ if (!(line_of_code)) \ ...@@ -23,7 +22,7 @@ if (!(line_of_code)) \
{ \ { \
std::cerr << "ERROR in file " << __FILE__ << " on line " << __LINE__ \ std::cerr << "ERROR in file " << __FILE__ << " on line " << __LINE__ \
<< " => " << #line_of_code << std::endl; \ << " => " << #line_of_code << std::endl; \
++error_count; \ ++cppa_ts.error_count; \
} ((void) 0) } ((void) 0)
#define CPPA_CHECK_EQUAL(lhs_loc, rhs_loc) \ #define CPPA_CHECK_EQUAL(lhs_loc, rhs_loc) \
...@@ -31,9 +30,10 @@ if ((lhs_loc) != (rhs_loc)) \ ...@@ -31,9 +30,10 @@ if ((lhs_loc) != (rhs_loc)) \
{ \ { \
std::cerr << "ERROR in file " << __FILE__ << " on line " << __LINE__ \ std::cerr << "ERROR in file " << __FILE__ << " on line " << __LINE__ \
<< " => " << #lhs_loc << " != " << #rhs_loc << std::endl; \ << " => " << #lhs_loc << " != " << #rhs_loc << std::endl; \
++error_count; \ ++cppa_ts.error_count; \
} ((void) 0) } ((void) 0)
std::size_t test__uniform_type();
std::size_t test__type_list(); std::size_t test__type_list();
std::size_t test__a_matches_b(); std::size_t test__a_matches_b();
std::size_t test__atom(); std::size_t test__atom();
......
...@@ -89,11 +89,11 @@ struct storage ...@@ -89,11 +89,11 @@ struct storage
template<typename T> template<typename T>
T& get(const std::string& key) T& get(const std::string& key)
{ {
const utype& uti = uniform_type_info<T>(); auto uti = uniform_type_info::by_type_info(typeid(T));
auto i = m_map.find(key); auto i = m_map.find(key);
if (i == m_map.end()) if (i == m_map.end())
{ {
i = m_map.insert(std::make_pair(key, uti.create())).first; i = m_map.insert(std::make_pair(key, uti->create())).first;
} }
else if (uti != i->second->type()) else if (uti != i->second->type())
{ {
......
...@@ -27,21 +27,14 @@ using std::endl; ...@@ -27,21 +27,14 @@ using std::endl;
using namespace cppa; using namespace cppa;
using namespace cppa::util; using namespace cppa::util;
class format_error : public std::exception class format_error : public std::runtime_error
{ {
std::string m_what; typedef std::runtime_error super;
public: public:
format_error(const std::string& what_str) : m_what(what_str) { } format_error(const std::string& what_str) : super(what_str) { }
virtual const char* what() const throw()
{
return m_what.c_str();
}
virtual ~format_error() throw() { }
}; };
...@@ -171,22 +164,22 @@ struct obj_types : util::abstract_type_list ...@@ -171,22 +164,22 @@ struct obj_types : util::abstract_type_list
{ {
std::size_t m_size; std::size_t m_size;
const utype** m_arr; const uniform_type_info** m_arr;
public: public:
obj_types(const std::vector<intrusive_ptr<object>>& objs) : m_size(objs.size()) obj_types(const std::vector<intrusive_ptr<object>>& objs) : m_size(objs.size())
{ {
m_arr = new const utype*[m_size]; m_arr = new const uniform_type_info*[m_size];
for (std::size_t i = 0; i != m_size; ++i) for (std::size_t i = 0; i != m_size; ++i)
{ {
m_arr[i] = &(objs[i]->type()); m_arr[i] = objs[i]->type();
} }
} }
obj_types(const obj_types& other) : m_size(other.size()) obj_types(const obj_types& other) : m_size(other.size())
{ {
m_arr = new const utype*[m_size]; m_arr = new const uniform_type_info*[m_size];
for (std::size_t i = 0; i != m_size; ++i) for (std::size_t i = 0; i != m_size; ++i)
{ {
m_arr[i] = other.m_arr[i]; m_arr[i] = other.m_arr[i];
...@@ -215,9 +208,9 @@ struct obj_types : util::abstract_type_list ...@@ -215,9 +208,9 @@ struct obj_types : util::abstract_type_list
return m_arr + m_size; return m_arr + m_size;
} }
virtual const utype& at(std::size_t pos) const virtual const uniform_type_info* at(std::size_t pos) const
{ {
return *m_arr[pos]; return m_arr[pos];
} }
}; };
...@@ -258,7 +251,7 @@ class obj_tuple : public detail::abstract_tuple ...@@ -258,7 +251,7 @@ class obj_tuple : public detail::abstract_tuple
return m_obj[pos]->value(); return m_obj[pos]->value();
} }
virtual const utype& utype_at(std::size_t pos) const virtual const uniform_type_info* utype_at(std::size_t pos) const
{ {
return m_obj[pos]->type(); return m_obj[pos]->type();
} }
...@@ -279,7 +272,7 @@ class obj_tuple : public detail::abstract_tuple ...@@ -279,7 +272,7 @@ class obj_tuple : public detail::abstract_tuple
for (std::size_t i = 0; i < m_obj.size(); ++i) for (std::size_t i = 0; i < m_obj.size(); ++i)
{ {
decltype(m_obj[i]) o = m_obj[i]; decltype(m_obj[i]) o = m_obj[i];
s << o->type().name(); s << o->type()->name();
o->serialize(s); o->serialize(s);
} }
} }
...@@ -342,7 +335,7 @@ struct serialize_tuple_at ...@@ -342,7 +335,7 @@ struct serialize_tuple_at
{ {
inline static void _(serializer& s, const Tuple& t) inline static void _(serializer& s, const Tuple& t)
{ {
s << uniform_type_info<typename type_at<Pos, Tuple>::type>().name() s << uniform_typeid<typename type_at<Pos, Tuple>::type>()->name()
<< t.get<Pos>(); << t.get<Pos>();
serialize_tuple_at<Pos + 1, Size, Tuple>::_(s, t); serialize_tuple_at<Pos + 1, Size, Tuple>::_(s, t);
} }
...@@ -365,15 +358,6 @@ serializer& operator<<(serializer& s, const tuple<Types...>& t) ...@@ -365,15 +358,6 @@ serializer& operator<<(serializer& s, const tuple<Types...>& t)
serializer& operator<<(serializer& s, const untyped_tuple& ut) serializer& operator<<(serializer& s, const untyped_tuple& ut)
{ {
/*
auto tsize = static_cast<std::uint8_t>(ut.size());
s << tsize;
for (std::size_t i = 0; i < ut.size(); ++i)
{
s << ut.utype_at(i).name();
}
*/
ut.vals()->serialize(s); ut.vals()->serialize(s);
return s; return s;
} }
...@@ -387,7 +371,7 @@ deserializer& operator>>(deserializer& d, untyped_tuple& ut) ...@@ -387,7 +371,7 @@ deserializer& operator>>(deserializer& d, untyped_tuple& ut)
{ {
std::string type_name; std::string type_name;
d >> type_name; d >> type_name;
object* obj = uniform_type_info(type_name).create(); object* obj = uniform_type_info::by_uniform_name(type_name)->create();
obj->deserialize(d); obj->deserialize(d);
obj_vec.push_back(obj); obj_vec.push_back(obj);
} }
...@@ -423,8 +407,8 @@ std::size_t test__serialization() ...@@ -423,8 +407,8 @@ std::size_t test__serialization()
obj_vec.reserve(2); obj_vec.reserve(2);
obj_vec.push_back(uniform_type_info<std::string>().create()); obj_vec.push_back(uniform_typeid<std::string>()->create());
obj_vec.push_back(uniform_type_info<int>().create()); obj_vec.push_back(uniform_typeid<int>()->create());
cow_ptr<detail::abstract_tuple> vals(new obj_tuple(obj_vec)); cow_ptr<detail::abstract_tuple> vals(new obj_tuple(obj_vec));
untyped_tuple ut0(vals); untyped_tuple ut0(vals);
...@@ -465,15 +449,6 @@ std::size_t test__serialization() ...@@ -465,15 +449,6 @@ std::size_t test__serialization()
deserializer d(io1); deserializer d(io1);
untyped_tuple ut3; untyped_tuple ut3;
d >> ut3; d >> ut3;
/*
cout << "ut3 (size = " << ut3.size() << "): ";
for (std::size_t i = 0; i < ut3.size(); ++i)
{
if (i > 0) cout << ", ";
cout << ut3.utype_at(i).name();
}
cout << endl;
*/
std::vector<std::size_t> mappings; std::vector<std::size_t> mappings;
bool does_match = match<std::string, std::string, int, int, int>(ut3, mappings); bool does_match = match<std::string, std::string, int, int, int>(ut3, mappings);
CPPA_CHECK_EQUAL(does_match, true); CPPA_CHECK_EQUAL(does_match, true);
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include "cppa/on.hpp" #include "cppa/on.hpp"
#include "cppa/cppa.hpp" #include "cppa/cppa.hpp"
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/detail/scheduler.hpp"
using std::cout; using std::cout;
using std::endl; using std::endl;
......
#include <string> #include <string>
#include <cstdint>
#include <typeinfo> #include <typeinfo>
#include <type_traits> #include <type_traits>
...@@ -46,6 +47,20 @@ std::size_t test__type_list() ...@@ -46,6 +47,20 @@ std::size_t test__type_list()
CPPA_CHECK((is_same<int, l2::head_type>::value)); CPPA_CHECK((is_same<int, l2::head_type>::value));
CPPA_CHECK((is_same<l1, l2::tail_type>::value)); CPPA_CHECK((is_same<l1, l2::tail_type>::value));
type_list<std::int32_t, float, char> ifc;
auto i = ifc.begin();
CPPA_CHECK((i != ifc.end()));
CPPA_CHECK(((*i)->name() == "@i32"));
++i;
CPPA_CHECK((i != ifc.end()));
CPPA_CHECK(((*i)->name() == "float"));
++i;
CPPA_CHECK((i != ifc.end()));
CPPA_CHECK(((*i)->name() == "@i8"));
++i;
CPPA_CHECK((i == ifc.end()));
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
#include <map>
#include <set>
#include <cctype>
#include <atomic>
#include <vector>
#include <string>
#include <cstdint>
#include <cstring>
#include <sstream>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <stdexcept>
#include "test.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/default_object_base.hpp"
using std::cout;
using std::endl;
using cppa::uniform_type_info;
namespace {
struct foo
{
int value;
foo(int val = 0) : value(val) { }
};
class foo_object : public cppa::util::default_object_base<foo>
{
typedef default_object_base<foo> super;
public:
foo_object(const uniform_type_info* uti, const foo& val = foo())
: super(uti, val) { }
object* copy /*[[override]]*/ () const
{
return new foo_object(type(), m_value);
}
std::string to_string /*[[override]]*/ () const
{
std::ostringstream sstr;
sstr << m_value.value;
return sstr.str();
}
void from_string /*[[override]]*/ (const std::string& str)
{
int tmp;
std::istringstream istr(str);
istr >> tmp;
m_value.value = tmp;
}
void deserialize(cppa::deserializer&) { }
void serialize(cppa::serializer&) const { }
};
bool unused1 = cppa::uniform_type_info::announce<foo_object>(typeid(foo));
bool unused2 = cppa::uniform_type_info::announce<foo_object>(typeid(foo));
bool unused3 = cppa::uniform_type_info::announce<foo_object>(typeid(foo));
bool unused4 = cppa::uniform_type_info::announce<foo_object>(typeid(foo));
typedef cppa::intrusive_ptr<cppa::object> obj_ptr;
} // namespace <anonymous>
std::size_t test__uniform_type()
{
CPPA_TEST(test__uniform_type);
int successful_announces = (unused1 ? 1 : 0)
+ (unused2 ? 1 : 0)
+ (unused3 ? 1 : 0)
+ (unused4 ? 1 : 0);
CPPA_CHECK_EQUAL(successful_announces, 1);
// test foo_object implementation
obj_ptr o = cppa::uniform_typeid<foo>()->create();
o->from_string("123");
CPPA_CHECK_EQUAL(o->to_string(), "123");
int val = reinterpret_cast<const foo*>(o->value())->value;
CPPA_CHECK_EQUAL(val, 123);
// 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", "@wstr", // strings
"float", "double", // floating points
// default announced cppa types
"cppa::any_type",
"cppa::intrusive_ptr<cppa::actor>"
};
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
auto types = cppa::uniform_type_info::get_all();
for (cppa::uniform_type_info* tinfo : types)
{
found.insert(tinfo->name());
}
// compare the two sets
CPPA_CHECK_EQUAL(expected.size(), found.size());
if (expected.size() == found.size())
{
CPPA_CHECK((std::equal(found.begin(), found.end(), expected.begin())));
}
return CPPA_TEST_RESULT;
}
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