Commit f6038a61 authored by neverlord's avatar neverlord

documentation

parent 27746169
...@@ -9,6 +9,11 @@ ...@@ -9,6 +9,11 @@
namespace cppa { namespace cppa {
/**
* @addtogroup TypeSystem
* @{
*/
/** /**
* @brief A simple example for @c announce with public accessible members. * @brief A simple example for @c announce with public accessible members.
* *
...@@ -49,6 +54,12 @@ namespace cppa { ...@@ -49,6 +54,12 @@ namespace cppa {
* @example announce_example_4.cpp * @example announce_example_4.cpp
*/ */
/**
* @brief An advanced example for @c announce implementing serialization
* for a user-defined tree data type.
* @example announce_example_5.cpp
*/
/** /**
* @brief Adds a new type mapping to the libcppa type system. * @brief Adds a new type mapping to the libcppa type system.
* @param tinfo C++ RTTI for the new type * @param tinfo C++ RTTI for the new type
...@@ -107,6 +118,10 @@ inline bool announce(const Args&... args) ...@@ -107,6 +118,10 @@ inline bool announce(const Args&... args)
new detail::default_uniform_type_info_impl<T>(args...)); new detail::default_uniform_type_info_impl<T>(args...));
} }
/**
* @}
*/
} // namespace cppa } // namespace cppa
#endif // ANNOUNCE_HPP #endif // ANNOUNCE_HPP
...@@ -63,22 +63,42 @@ ...@@ -63,22 +63,42 @@
* *
* @section Intro Introduction * @section Intro Introduction
* *
* This library provides an implementation of the Actor model for C++. * This library provides an implementation of the actor model for C++.
* It uses a network transparent messaging system to ease development * It uses a network transparent messaging system to ease development
* of both concurrent and distributed software using C++. * of both concurrent and distributed software using C++.
* *
* @p libcppa uses a thread pool to schedule actors by default. * @p libcppa uses a thread pool to schedule actors by default.
* A scheduled actor should not call blocking functions.
* Individual actors can be spawned (created) with a special flag to run in * Individual actors can be spawned (created) with a special flag to run in
* an own thread if needed. * an own thread if one needs to make use of blocking APIs.
* *
* In @p libcppa, each context is an actor. Even main is implicitly * Writing applications in @p libcppa requires a minimum of gluecode.
* converted to an actor if needed. * You don't have to derive a particular class to implement an actor and
* each context <i>is</i> an actor. Even main is implicitly
* converted to an actor if needed, as the following example shows:
* *
* @subsection IntroHelloWorld Hello World Example * @subsection IntroHelloWorld Hello World Example
* *
* @include hello_world_example.cpp * @include hello_world_example.cpp
* *
* @section GettingStarted Getting started with libcppa * @section GettingStarted Getting Started
*
* To build @p libcppa, you need <tt>GCC >= 4.6</tt>, @p Automake
* and the <tt>Boost.Thread</tt> library.
*
* The usual build steps on Linux and Mac OS X are:
*
* - <tt>autoreconf -i</tt>
* - <tt>./configure</tt>
* - <tt>make</tt>
* - <tt>make install</tt> (as root, optionally)
*
* Use <tt>./configure --help</tt> if the script doesn't auto-select
* the correct @p GCC binary or doesn't find your <tt>Boost.Thread</tt>
* installation.
*
* Windows is not supported yet, because MVSC++ doesn't implement the
* C++11 features needed to compile @p libcppa.
* *
* @namespace cppa * @namespace cppa
* @brief This is the root namespace of libcppa. * @brief This is the root namespace of libcppa.
...@@ -160,13 +180,12 @@ ...@@ -160,13 +180,12 @@
* *
* receive * receive
* ( * (
* // equal to on(std::string("hello actor!")) * // equal to: on(std::string("hello actor!"))
* on("hello actor!") >> []() { } * on("hello actor!") >> []() { }
* ); * );
* @endcode * @endcode
*/ */
namespace cppa { namespace cppa {
/** /**
......
...@@ -11,6 +11,10 @@ namespace cppa { ...@@ -11,6 +11,10 @@ namespace cppa {
class object; class object;
/**
* @ingroup Serialize
* @brief Technology-independent deserialization interface.
*/
class deserializer class deserializer
{ {
...@@ -24,8 +28,8 @@ class deserializer ...@@ -24,8 +28,8 @@ class deserializer
virtual ~deserializer(); virtual ~deserializer();
/** /**
* @brief Seeks the beginning of the next object and return its * @brief Seeks the beginning of the next object and return
* uniform type name. * its uniform type name.
*/ */
virtual std::string seek_object() = 0; virtual std::string seek_object() = 0;
...@@ -35,15 +39,43 @@ class deserializer ...@@ -35,15 +39,43 @@ class deserializer
*/ */
virtual std::string peek_object() = 0; virtual std::string peek_object() = 0;
/**
* @brief Begins deserialization of an object of type @p type_name.
* @param type_name The platform-independent @p libcppa type name.
*/
virtual void begin_object(const std::string& type_name) = 0; virtual void begin_object(const std::string& type_name) = 0;
/**
* @brief Ends deserialization of an object.
*/
virtual void end_object() = 0; virtual void end_object() = 0;
/**
* @brief Begins deserialization of a sequence.
* @returns The size of the sequence.
*/
virtual size_t begin_sequence() = 0; virtual size_t begin_sequence() = 0;
/**
* @brief Ends deserialization of a sequence.
*/
virtual void end_sequence() = 0; virtual void end_sequence() = 0;
/**
* @brief Reads a primitive value from the data source of type @p ptype.
* @param ptype Expected primitive data type.
* @returns A primitive value of type @p ptype.
*/
virtual primitive_variant read_value(primitive_type ptype) = 0; virtual primitive_variant read_value(primitive_type ptype) = 0;
virtual void read_tuple(size_t size, /**
* @brief Reads a tuple of primitive values from the data
* source of the types @p ptypes.
* @param num The size of the tuple.
* @param ptype Array of expected primitive data types.
* @param storage Array of size @p num, storing the result of this function.
*/
virtual void read_tuple(size_t num,
const primitive_type* ptypes, const primitive_type* ptypes,
primitive_variant* storage ) = 0; primitive_variant* storage ) = 0;
......
...@@ -9,9 +9,17 @@ ...@@ -9,9 +9,17 @@
namespace cppa { namespace cppa {
/**
* @defgroup Serialize Serialization of custom data types.
*/
// forward declaration // forward declaration
class primitive_variant; class primitive_variant;
/**
* @ingroup Serialize
* @brief Technology-independent serialization interface.
*/
class serializer class serializer
{ {
...@@ -24,23 +32,40 @@ class serializer ...@@ -24,23 +32,40 @@ class serializer
virtual ~serializer(); virtual ~serializer();
/**
* @brief Begins serialization of an object of the type
* named @p type_name.
* @param type_name The platform-independent @p libcppa type name.
*/
virtual void begin_object(const std::string& type_name) = 0; virtual void begin_object(const std::string& type_name) = 0;
/**
* @brief Ends serialization of an object.
*/
virtual void end_object() = 0; virtual void end_object() = 0;
virtual void begin_sequence(size_t size) = 0; /**
* @brief Begins serialization of a sequence of size @p num.
*/
virtual void begin_sequence(size_t num) = 0;
/**
* @brief Ends serialization of a sequence.
*/
virtual void end_sequence() = 0; virtual void end_sequence() = 0;
/** /**
* @brief Writes a single value. * @brief Writes a single value to the data sink.
* @param value A primitive data value.
*/ */
virtual void write_value(const primitive_variant& value) = 0; virtual void write_value(const primitive_variant& value) = 0;
/** /**
* @brief Writes @p size values. * @brief Writes @p num values as a tuple to the data sink.
* @param num Size of the array @p values.
* @param values An array of size @p num of primitive data values.
*/ */
virtual void write_tuple(size_t size, const primitive_variant* values) = 0; virtual void write_tuple(size_t num, const primitive_variant* values) = 0;
}; };
......
...@@ -26,6 +26,83 @@ class uniform_type_info; ...@@ -26,6 +26,83 @@ class uniform_type_info;
const uniform_type_info* uniform_typeid(const std::type_info&); const uniform_type_info* uniform_typeid(const std::type_info&);
/** /**
* @defgroup TypeSystem libcppa's platform-independent type system.
*
* @p libcppa provides a fully network transparent communication between
* actors. Thus, @p libcppa needs to serialize and deserialize message objects.
* Unfortunately, this is not possible using the C++ RTTI system.
*
* Since it is not possible to extend <tt>std::type_info</tt>, @p libcppa
* uses its own type abstraction:
* {@link cppa::uniform_type_info uniform_type_info}.
*
* Unlike <tt>std::type_info::name()</tt>,
* {@link cppa::uniform_type_info::name() uniform_type_info::name()}
* is guaranteed to return the same name on all supported platforms.
* Furthermore, it allows to create an instance of a type by name:
*
* @code
* // creates a signed, 32 bit integer
* cppa::object i = cppa::uniform_type_info::by_uniform_name("@i32")->create();
* @endcode
*
* However, you should rarely if ever need to use {@link cppa::object object}
* or {@link cppa::uniform_type_info uniform_type_info}.
*
* There is one exception, though, where you need to care about
* <tt>libcppa</tt>'s type system: using custom data types in messages.
* The source code below compiles fine, but crashes with an exception during
* runtime.
*
* @code
* #include "cppa/cppa.hpp"
* using namespace cppa;
*
* struct foo { int a; int b; };
*
* int main()
* {
* send(self(), foo{1,2});
* return 0;
* }
* @endcode
*
* Depending on your platform, the error message looks somewhat like this:
*
* <tt>
* terminate called after throwing an instance of 'std::runtime_error'
* <br>
* what(): uniform_type_info::by_type_info(): foo is an unknown typeid name
* </tt>
*
* The user-defined struct @p foo is not known by the @p libcppa type system.
* Thus, @p libcppa is unable to serialize/deserialize @p foo and rejects it.
*
* Fortunately, there is an easy way to add @p foo the type system,
* without needing to implement serialize/deserialize by yourself:
*
* @code
* cppa::announce<foo>(&foo::a, &foo::b);
* @endcode
*
* {@link cppa::announce announce()} takes the class as template
* parameter and pointers to all members (or getter/setter pairs)
* as arguments. This works for all primitive data types and STL compliant
* containers. See the announce {@link announce_example_1.cpp example 1},
* {@link announce_example_2.cpp example 2},
* {@link announce_example_3.cpp example 3} and
* {@link announce_example_4.cpp example 4} for more details.
*
* Obviously, there are limitations. If your class does implement
* an unsupported data structure, you have to implement serialize/deserialize
* by yourself. {@link announce_example_5.cpp Example 5} shows, how to
* announce a tree data structure to the @p libcppa type system.
* Make sure to read the @ref Serialize "serialization section" of
* this documentation before.
*/
/**
* @ingroup TypeSystem
* @brief Provides a platform independent type name and a (very primitive) * @brief Provides a platform independent type name and a (very primitive)
* kind of reflection in combination with {@link cppa::object object}. * kind of reflection in combination with {@link cppa::object object}.
* *
...@@ -40,7 +117,6 @@ const uniform_type_info* uniform_typeid(const std::type_info&); ...@@ -40,7 +117,6 @@ const uniform_type_info* uniform_typeid(const std::type_info&);
* - the <em>anonymous namespace</em> is named @c \@_ \n * - the <em>anonymous namespace</em> is named @c \@_ \n
* e.g.: <tt>namespace { class foo { }; }</tt> is mapped to * e.g.: <tt>namespace { class foo { }; }</tt> is mapped to
* @c \@_::foo * @c \@_::foo
* - {@link cppa::util::void_type} is named @c \@0
*/ */
class uniform_type_info : cppa::util::comparable<uniform_type_info> class uniform_type_info : cppa::util::comparable<uniform_type_info>
{ {
...@@ -103,7 +179,7 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info> ...@@ -103,7 +179,7 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
/** /**
* @brief Get instance by uniform name. * @brief Get instance by uniform name.
* @param uniform_name The libCPPA internal name for a type. * @param uniform_name The @p libcppa internal name for a type.
* @returns The instance associated to @p uniform_name. * @returns The instance associated to @p uniform_name.
*/ */
static uniform_type_info* by_uniform_name(const std::string& uniform_name); static uniform_type_info* by_uniform_name(const std::string& uniform_name);
...@@ -117,8 +193,8 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info> ...@@ -117,8 +193,8 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
virtual ~uniform_type_info(); virtual ~uniform_type_info();
/** /**
* @brief Get the internal libCPPA name for this type. * @brief Get the internal @p libcppa name for this type.
* @returns A string describing the libCPPA internal type name. * @returns A string describing the @p libcppa internal type name.
*/ */
inline const std::string& name() const { return m_name; } inline const std::string& name() const { return m_name; }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* This example shows how to implement serialize/deserialize to announce * * This example shows how to implement serialize/deserialize to announce *
* non-trivial data structures to the libcppa type system. * * non-trivial data structures to the libcppa type system. *
* * * *
* However, announce() auto-detects STL compliant containers and provides * * Announce() auto-detects STL compliant containers and provides *
* an easy way to tell libcppa how to serialize user defined types. * * an easy way to tell libcppa how to serialize user defined types. *
* See announce_example 1-4 for usage examples. * * See announce_example 1-4 for usage examples. *
* * * *
...@@ -78,7 +78,7 @@ struct tree ...@@ -78,7 +78,7 @@ struct tree
}; };
// tree node are equals if values and all values of all children are equal // tree nodes are equals if values and all values of all children are equal
bool operator==(const tree_node& lhs, const tree_node& rhs) bool operator==(const tree_node& lhs, const tree_node& rhs)
{ {
if (lhs.value == rhs.value && lhs.children.size() == rhs.children.size()) if (lhs.value == rhs.value && lhs.children.size() == rhs.children.size())
...@@ -145,26 +145,27 @@ class tree_type_info : public util::abstract_uniform_type_info<tree> ...@@ -145,26 +145,27 @@ class tree_type_info : public util::abstract_uniform_type_info<tree>
void serialize_node(const tree_node& node, serializer* sink) const void serialize_node(const tree_node& node, serializer* sink) const
{ {
// serialize { value, number of children } ... children ... // serialize { value, number of children } ... children ...
std::uint32_t num_children = node.children.size();
sink->write_value(node.value); sink->write_value(node.value);
sink->write_value(num_children); sink->begin_sequence(node.children.size());
for (const tree_node& subnode : node.children) for (const tree_node& subnode : node.children)
{ {
serialize_node(subnode, sink); serialize_node(subnode, sink);
} }
sink->end_sequence();
} }
void deserialize_node(tree_node& node, deserializer* source) const void deserialize_node(tree_node& node, deserializer* source) const
{ {
// deserialize { value, number of children } ... children ... // deserialize { value, number of children } ... children ...
auto value = get<std::uint32_t>(source->read_value(pt_uint32)); auto value = get<std::uint32_t>(source->read_value(pt_uint32));
auto num_children = get<std::uint32_t>(source->read_value(pt_uint32));
node.value = value; node.value = value;
for (std::uint32_t i = 0; i < num_children; ++i) auto num_children = source->begin_sequence();
for (size_t i = 0; i < num_children; ++i)
{ {
node.add_child(); node.add_child();
deserialize_node(node.children.back(), source); deserialize_node(node.children.back(), source);
} }
source->end_sequence();
} }
}; };
...@@ -203,10 +204,12 @@ int main() ...@@ -203,10 +204,12 @@ int main()
on<tree>() >> [](const tree& tmsg) on<tree>() >> [](const tree& tmsg)
{ {
// prints the tree in its serialized format: // prints the tree in its serialized format:
// @<> ( { tree ( 0, 2, 10, 3, 11, 0, 12, 0, 13, 0, 20, 2, 21, 0, 22, 0 ) } ) // @<> ( { tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } ) } )
cout << "to_string(last_received()): " << to_string(last_received()) cout << "to_string(last_received()): "
<< to_string(last_received())
<< endl; << endl;
// prints: 0 { 10 { 11, 12, 13 } , 20 { 21, 22 } } // prints the tree using the print member function:
// 0 { 10 { 11, 12, 13 } , 20 { 21, 22 } }
tmsg.print(); tmsg.print();
} }
); );
......
...@@ -14,7 +14,7 @@ void echo_actor() ...@@ -14,7 +14,7 @@ void echo_actor()
{ {
// prints "Hello World!" // prints "Hello World!"
std::cout << what << std::endl; std::cout << what << std::endl;
// reply "!dlroW olleH" // replies "!dlroW olleH"
reply(std::string(what.rbegin(), what.rend())); reply(std::string(what.rbegin(), what.rend()));
} }
); );
...@@ -32,6 +32,7 @@ int main() ...@@ -32,6 +32,7 @@ int main()
( (
on<std::string>() >> [](const std::string& what) on<std::string>() >> [](const std::string& what)
{ {
// prints "!dlroW olleH"
std::cout << what << std::endl; std::cout << what << std::endl;
} }
); );
......
...@@ -109,6 +109,7 @@ class string_serializer : public serializer ...@@ -109,6 +109,7 @@ class string_serializer : public serializer
void end_sequence() void end_sequence()
{ {
out << (m_after_value ? " }" : "}"); out << (m_after_value ? " }" : "}");
m_after_value = true;
} }
void write_value(const primitive_variant& value) void write_value(const primitive_variant& value)
......
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