From 0f3dae74b1647a3cef5ba6b4a9967ebd9cd20e9e Mon Sep 17 00:00:00 2001
From: Ramin Yaghoubzadeh <ryaghoub@techfak.uni-bielefeld.de>
Date: Tue, 24 Jul 2012 12:32:47 +0200
Subject: [PATCH] Working on CMake build for ipaaca-cpp

---
 cpp/CMakeLists.txt            |  74 ++++
 cpp/build.properties          |   2 +-
 cpp/build.xml                 |   2 +-
 cpp/include/ipaaca.h          | 658 ++++++++++++++++++++++++++++++++++
 cpp/ivy.xml                   |   4 +-
 cpp/test/src/rsb.conf         |   5 +
 python/test/src/ipaacaspam.py |  21 ++
 7 files changed, 763 insertions(+), 3 deletions(-)
 create mode 100644 cpp/CMakeLists.txt
 create mode 100644 cpp/include/ipaaca.h
 create mode 100644 cpp/test/src/rsb.conf

diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
new file mode 100644
index 0000000..147cc81
--- /dev/null
+++ b/cpp/CMakeLists.txt
@@ -0,0 +1,74 @@
+cmake_minimum_required (VERSION 2.6)
+
+# project name
+project (ipaaca)
+
+## use the following line to enable console debug messages in ipaaca
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DIPAACA_DEBUG_MESSAGES")
+
+# find cmake modules locally too
+set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
+
+set(BOOSTLIBS boost_regex-mt boost_date_time-mt boost_program_options-mt boost_thread-mt boost_filesystem-mt boost_signals-mt boost_system-mt)
+set(PROTOLIBS protobuf)
+set(RSBLIBS rsc rsbcore)
+
+set(LIBS ${LIBS} ${BOOSTLIBS} ${PROTOLIBS} ${RSBLIBS})
+
+# enhance the default search paths (headers, libs ...)
+set(CMAKE_PREFIX_PATH ${PROJECT_SOURCE_DIR}:/opt/local:${CMAKE_PREFIX_PATH})
+
+## Ace2 uses deprecated style (non-template friend functions and non-const char*s)
+##  We just hide the warnings here
+#set(CXX_OLD_CODE_CONVENIENCE_FLAGS "-Wno-non-template-friend -Wno-write-strings")
+
+# Compiler defines copied from the old build system
+set(CXX_DEFINES "-D_BSD_SOURCE -DUSE_AV -DMGC_USE_DOUBLE -DLEDA_PREFIX -D__NO_CAST_TO_LOCAL_TYPE__ -DDBGLVL=0")
+if (DEFINED APPLE)
+	message(STATUS "Adding extra options for building on Mac OS X")
+	set(CXX_DEFINES "${CXX_DEFINES} -D__MACOSX__")
+	link_directories( /opt/local/lib )
+	include_directories( /opt/local/include )
+endif(DEFINED APPLE)
+
+# Combine the extra compiler flags
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_OLD_CODE_CONVENIENCE_FLAGS} ${CXX_DEFINES}")
+
+# add include dir for auto-generated headers placed in build/
+include_directories( ${PROJECT_SOURCE_DIR}/build )
+
+# add local include directory
+include_directories( ${PROJECT_SOURCE_DIR}/include )
+# add lib and include directory from pulled dependencies
+include_directories( ${PROJECT_SOURCE_DIR}/lib/include )
+link_directories( ${PROJECT_SOURCE_DIR}/lib )
+
+# specify source files for ipaaca (auto-generated ones are in build/ )
+set (SOURCE
+	src/ipaaca.cc
+	build/ipaaca.pb.cc
+	)
+
+# compile all files to "ipaaca" shared library
+add_library(ipaaca SHARED ${SOURCE})
+# and link all the required external libs (found above using find_package etc.)
+target_link_libraries(ipaaca ${LIBS})
+
+set(DEFAULT_BIN_SUBDIR bin)
+set(DEFAULT_LIB_SUBDIR lib)
+set(DEFAULT_DATA_SUBDIR share/data)
+set(DEFAULT_INCLUDE_SUBDIR include)
+set(CMAKE_INSTALL_PREFIX "")
+install (
+	TARGETS ipaaca
+	RUNTIME DESTINATION bin
+	LIBRARY DESTINATION lib
+	ARCHIVE DESTINATION lib
+	)
+install(
+	DIRECTORY include
+	DESTINATION /
+	FILES_MATCHING PATTERN "*.h" PATTERN "*.hh" PATTERN "*.hpp" PATTERN "*.inl"
+	)
+
+
diff --git a/cpp/build.properties b/cpp/build.properties
index f7adac0..8ac22e8 100644
--- a/cpp/build.properties
+++ b/cpp/build.properties
@@ -1,5 +1,5 @@
 language=cpp
 resolve.status=beta
-resource.path=${shared.resources}/Shared3DModels/resource;${shared.resources}/DefaultShaders/resource;${shared.resources}/LogbackConfigs/resource;${shared.resources}/HmiHumanoidBodyControl/resource;${shared.resources}/HmiHumanoidEmbodiments/resource;
+resource.path=${shared.resources}/;
 rebuild.list=
 
diff --git a/cpp/build.xml b/cpp/build.xml
index e18401e..07ad555 100644
--- a/cpp/build.xml
+++ b/cpp/build.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project name="IpaacaCpp"  default="run">
+<project name="IpaacaCpp"  default="dist">
    <import file="../../soashared/ant/build.xml" />
    <target name="-pre-compilation">
      <echo message="Compiling protobuf file" />
diff --git a/cpp/include/ipaaca.h b/cpp/include/ipaaca.h
new file mode 100644
index 0000000..d08732d
--- /dev/null
+++ b/cpp/include/ipaaca.h
@@ -0,0 +1,658 @@
+#ifndef __IPAACA_H__
+#define __IPAACA_H_
+
+/// ipaaca/IU/RSB protocol major version number
+#define IPAACA_PROTOCOL_VERSION_MAJOR         1
+/// ipaaca/IU/RSB protocol minor version number
+#define IPAACA_PROTOCOL_VERSION_MINOR         0
+
+/// running release number of ipaaca-c++
+#define IPAACA_CPP_RELEASE_NUMBER             1
+/// date of last release number increment
+#define IPAACA_CPP_RELEASE_DATE     "2012-04-13"
+
+
+#ifdef IPAACA_DEBUG_MESSAGES
+#define IPAACA_INFO(i) std::cout << __FILE__ << ":" << __LINE__ << ": " << __func__ << "() -- " << i << std::endl;
+#define IPAACA_WARNING(i) std::cout << __FILE__ << ":" << __LINE__ << ": " << __func__ << "() -- WARNING: " << i << std::endl;
+#define IPAACA_IMPLEMENT_ME std::cout << __FILE__ << ":" << __LINE__ << ": " << __func__ << "() -- IMPLEMENT ME" << std::endl;
+#define IPAACA_TODO(i) std::cout << __FILE__ << ":" << __LINE__ << ": " << __func__ << "() -- TODO: " << i << std::endl;
+#else
+#define IPAACA_INFO(i) ;
+#define IPAACA_WARNING(i) ;
+#define IPAACA_IMPLEMENT_ME ;
+#define IPAACA_TODO(i) ;
+#endif
+
+/// marking pure virtual functions for extra readability
+#define _IPAACA_ABSTRACT_
+
+/// value to return when reading nonexistant payload keys
+#define IPAACA_PAYLOAD_DEFAULT_STRING_VALUE ""
+
+#include <iostream>
+
+#include <boost/thread.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/pointer_cast.hpp>
+
+#include <rsc/runtime/TypeStringTools.h>
+#include <rsb/Factory.h>
+#include <rsb/Handler.h>
+#include <rsb/Event.h>
+#include <rsb/converter/Repository.h>
+#include <rsb/converter/ProtocolBufferConverter.h>
+#include <rsb/converter/Converter.h>
+#include <rsb/rsbexports.h>
+
+#include <ipaaca.pb.h>
+
+#include <pthread.h>
+#include <uuid/uuid.h>
+
+//using namespace boost;
+using namespace rsb;
+using namespace rsb::filter;
+using namespace rsb::converter;
+using namespace rsb::patterns;
+
+namespace ipaaca {
+
+typedef uint32_t revision_t;
+
+/// Type of the IU event. Realized as an integer to enable bit masks for filters.
+typedef uint32_t IUEventType;
+#define IU_ADDED         1
+#define IU_COMMITTED     2
+#define IU_DELETED       4
+#define IU_RETRACTED     8
+#define IU_UPDATED      16
+#define IU_LINKSUPDATED 32
+/// Bit mask for receiving all events
+#define IU_ALL_EVENTS   63
+
+/// Convert an int event type to a human-readable string
+inline std::string iu_event_type_to_str(IUEventType type)
+{
+	switch(type) {
+		case IU_ADDED: return "ADDED";
+		case IU_COMMITTED: return "COMMITTED";
+		case IU_DELETED: return "DELETED";
+		case IU_RETRACTED: return "RETRACTED";
+		case IU_UPDATED: return "UPDATED";
+		case IU_LINKSUPDATED: return "LINKSUPDATED";
+		default: return "(NOT A KNOWN SINGLE IU EVENT TYPE)";
+	}
+}
+
+/// IU access mode: PUSH means that updates are broadcast; REMOTE means that reads are RPC calls; MESSAGE means a fire-and-forget message
+enum IUAccessMode {
+	IU_ACCESS_PUSH,
+	IU_ACCESS_REMOTE,
+	IU_ACCESS_MESSAGE
+};
+
+class PayloadEntryProxy;
+class Payload;
+class IUInterface;
+class IU;
+class RemotePushIU;
+class IULinkUpdate;
+class IULinkUpdateConverter;
+class IUPayloadUpdate;
+class IUPayloadUpdateConverter;
+class IUStore;
+class FrozenIUStore;
+class Buffer;
+class InputBuffer;
+class OutputBuffer;
+
+/// generate a UUID as an ASCII string
+std::string generate_uuid_string();
+
+/// store for (local) IUs. TODO Stores need to be unified more
+class IUStore: public std::map<std::string, boost::shared_ptr<IU> >
+{
+};
+/// store for RemotePushIUs. TODO Stores need to be unified more
+class RemotePushIUStore: public std::map<std::string, boost::shared_ptr<RemotePushIU> > // TODO genericize to all remote IU types
+{
+};
+
+/// a reentrant lock/mutex
+class Lock
+{
+	protected:
+		pthread_mutexattr_t _attrs;
+		pthread_mutex_t _mutex;
+	public:
+		inline Lock() {
+			pthread_mutexattr_init(&_attrs);
+			pthread_mutexattr_settype(&_attrs, PTHREAD_MUTEX_RECURSIVE);
+			pthread_mutex_init(&_mutex, &_attrs);
+		}
+		inline ~Lock() {
+			pthread_mutex_destroy(&_mutex);
+			pthread_mutexattr_destroy(&_attrs);
+		}
+		inline void lock() {
+			pthread_mutex_lock(&_mutex);
+		}
+		inline void unlock() {
+			pthread_mutex_unlock(&_mutex);
+		}
+};
+
+typedef std::set<std::string> LinkSet;
+typedef std::map<std::string, LinkSet> LinkMap;
+class SmartLinkMap {
+	friend std::ostream& operator<<(std::ostream& os, const SmartLinkMap& obj);
+	friend class IUInterface;
+	friend class IU;
+	friend class IUConverter;
+	public:
+		const LinkSet& get_links(const std::string& key);
+		const LinkMap& get_all_links();
+	
+	protected:
+		LinkMap _links;
+		static LinkSet empty_link_set;
+		void _add_and_remove_links(const LinkMap& add, const LinkMap& remove);
+		void _replace_links(const LinkMap& links);
+};
+
+const LinkSet EMPTY_LINK_SET;
+//const std::set<std::string> EMPTY_LINK_SET;
+
+//typedef boost::function<void (const std::string&, bool, IUEventType, const std::string&)> IUEventHandlerFunction;
+typedef boost::function<void (boost::shared_ptr<IUInterface>, IUEventType, bool)> IUEventHandlerFunction;
+
+class IUEventHandler {
+	protected:
+		IUEventHandlerFunction _function;
+		IUEventType _event_mask;
+		bool _for_all_categories;
+		std::set<std::string> _categories;
+	protected:
+		inline bool _condition_met(IUEventType event_type, const std::string& category)
+		{
+			return ((_event_mask&event_type)!=0) && (_for_all_categories || (_categories.count(category)>0));
+		}
+	public:
+		IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category);
+		IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories);
+		//void call(Buffer* buffer, const std::string& uid, bool local, IUEventType event_type, const std::string& category);
+		void call(Buffer* buffer, boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category);
+	typedef boost::shared_ptr<IUEventHandler> ptr;
+};
+
+class Buffer { //: public boost::enable_shared_from_this<Buffer> {//{{{
+	friend class IU;
+	friend class RemotePushIU;
+	friend class CallbackIUPayloadUpdate;
+	friend class CallbackIULinkUpdate;
+	friend class CallbackIUCommission;
+	protected:
+		std::string _uuid;
+		std::string _basename;
+		std::string _unique_name;
+		std::string _id_prefix;
+		std::vector<IUEventHandler::ptr> _event_handlers;
+	protected:
+		_IPAACA_ABSTRACT_ virtual void _send_iu_link_update(IUInterface* iu, bool is_delta, revision_t revision, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name="undef") = 0;
+		_IPAACA_ABSTRACT_ virtual void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef") = 0;
+		_IPAACA_ABSTRACT_ virtual void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name="undef") = 0;
+		void _allocate_unique_name(const std::string& basename, const std::string& function);
+		inline Buffer(const std::string& basename, const std::string& function) {
+			_allocate_unique_name(basename, function);
+		}
+		void call_iu_event_handlers(boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category);
+	public:
+		virtual inline ~Buffer() { }
+		inline const std::string& unique_name() { return _unique_name; }
+		void register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories);
+		void register_handler(IUEventHandlerFunction function, IUEventType event_mask = IU_ALL_EVENTS, const std::string& category="");
+		//_IPAACA_ABSTRACT_ virtual void add(boost::shared_ptr<IUInterface> iu) = 0;
+		_IPAACA_ABSTRACT_ virtual boost::shared_ptr<IUInterface> get(const std::string& iu_uid) = 0;
+		_IPAACA_ABSTRACT_ virtual std::set<boost::shared_ptr<IUInterface> > get_ius() = 0;
+};
+//}}}
+
+class CallbackIUPayloadUpdate: public Server::Callback<IUPayloadUpdate, int> {
+	protected:
+		Buffer* _buffer;
+	public:
+		CallbackIUPayloadUpdate(Buffer* buffer);
+		boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<IUPayloadUpdate> update);
+};
+class CallbackIULinkUpdate: public Server::Callback<IULinkUpdate, int> {
+	protected:
+		Buffer* _buffer;
+	public:
+		CallbackIULinkUpdate(Buffer* buffer);
+	public:
+		boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<IULinkUpdate> update);
+};
+class CallbackIUCommission: public Server::Callback<protobuf::IUCommission, int> {
+	protected:
+		Buffer* _buffer;
+	public:
+		CallbackIUCommission(Buffer* buffer);
+	public:
+		boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<protobuf::IUCommission> update);
+};
+
+class OutputBuffer: public Buffer { //, public boost::enable_shared_from_this<OutputBuffer>  {//{{{
+	friend class IU;
+	friend class RemotePushIU;
+	protected:
+	protected:
+		std::map<std::string, Informer<AnyType>::Ptr> _informer_store;
+		IUStore _iu_store;
+		Lock _iu_id_counter_lock;
+		ServerPtr _server;
+	protected:
+		// informing functions
+		void _send_iu_link_update(IUInterface* iu, bool is_delta, revision_t revision, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name="undef");
+		void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef");
+		void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name);
+		// remote access functions
+		// _remote_update_links(IULinkUpdate)
+		// _remote_update_payload(IUPayloadUpdate)
+		// _remote_commit(protobuf::IUCommission)
+	protected:
+		void _publish_iu(boost::shared_ptr<IU> iu);
+		void _retract_iu(boost::shared_ptr<IU> iu);
+		Informer<AnyType>::Ptr _get_informer(const std::string& category);
+	protected:
+		OutputBuffer(const std::string& basename);
+		void _initialize_server();
+	public:
+		static boost::shared_ptr<OutputBuffer> create(const std::string& basename);
+		~OutputBuffer() {
+			IPAACA_IMPLEMENT_ME
+		}
+		void add(boost::shared_ptr<IU> iu);
+		boost::shared_ptr<IU> remove(const std::string& iu_uid);
+		boost::shared_ptr<IU> remove(boost::shared_ptr<IU> iu);
+		boost::shared_ptr<IUInterface> get(const std::string& iu_uid);
+		std::set<boost::shared_ptr<IUInterface> > get_ius();
+	typedef boost::shared_ptr<OutputBuffer> ptr;
+};
+//}}}
+
+class InputBuffer: public Buffer { //, public boost::enable_shared_from_this<InputBuffer>  {//{{{
+	friend class IU;
+	friend class RemotePushIU;
+	protected:
+		std::map<std::string, ListenerPtr> _listener_store;
+		std::map<std::string, RemoteServerPtr> _remote_server_store;
+		RemotePushIUStore _iu_store;  // TODO genericize
+	protected:
+		inline void _send_iu_link_update(IUInterface* iu, bool is_delta, revision_t revision, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name="undef")
+		{
+			IPAACA_WARNING("(ERROR) InputBuffer::_send_iu_link_update() should never be invoked")
+		}
+		inline void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef")
+		{
+			IPAACA_WARNING("(ERROR) InputBuffer::_send_iu_payload_update() should never be invoked")
+		}
+		inline void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name="undef")
+		{
+			IPAACA_WARNING("(ERROR) InputBuffer::_send_iu_commission() should never be invoked")
+		}
+	protected:
+		RemoteServerPtr _get_remote_server(const std::string& unique_server_name);
+		ListenerPtr _create_category_listener_if_needed(const std::string& category);
+		void _handle_iu_events(EventPtr event);
+	protected:
+		InputBuffer(const std::string& basename, const std::vector<std::string>& category_interests);
+		InputBuffer(const std::string& basename, const std::string& category_interest1);
+		InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2);
+		InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3);
+		InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4);
+	public:
+		static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::vector<std::string>& category_interests);
+		static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1);
+		static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2);
+		static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3);
+		static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4);
+		~InputBuffer() {
+			IPAACA_IMPLEMENT_ME
+		}
+		boost::shared_ptr<IUInterface> get(const std::string& iu_uid);
+		std::set<boost::shared_ptr<IUInterface> > get_ius();
+	typedef boost::shared_ptr<InputBuffer> ptr;
+};
+//}}}
+
+class IUConverter: public rsb::converter::Converter<std::string> {//{{{
+	public:
+		IUConverter();
+		std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
+		rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
+};//}}}
+
+class IUPayloadUpdate {//{{{
+	public:
+		std::string uid;
+		revision_t revision;
+		std::string writer_name;
+		bool is_delta;
+		std::map<std::string, std::string> new_items;
+		std::vector<std::string> keys_to_remove;
+	friend std::ostream& operator<<(std::ostream& os, const IUPayloadUpdate& obj);
+	typedef boost::shared_ptr<IUPayloadUpdate> ptr;
+};//}}}
+class IUPayloadUpdateConverter: public rsb::converter::Converter<std::string> {//{{{
+	public:
+		IUPayloadUpdateConverter();
+		std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
+		rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
+};//}}}
+
+class IULinkUpdate {//{{{
+	public:
+		std::string uid;
+		revision_t revision;
+		std::string writer_name;
+		bool is_delta;
+		std::map<std::string, std::set<std::string> > new_links;
+		std::map<std::string, std::set<std::string> > links_to_remove;
+	friend std::ostream& operator<<(std::ostream& os, const IULinkUpdate& obj);
+	typedef boost::shared_ptr<IULinkUpdate> ptr;
+};//}}}
+class IULinkUpdateConverter: public rsb::converter::Converter<std::string> {//{{{
+	public:
+		IULinkUpdateConverter();
+		std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
+		rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
+};//}}}
+
+
+class IntConverter: public rsb::converter::Converter<std::string> {//{{{
+	public:
+		IntConverter();
+		std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
+		rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
+};//}}}
+
+class Initializer
+{
+	public:
+		static void initialize_ipaaca_rsb_if_needed();
+		static bool initialized();
+	protected:
+		static bool _initialized;
+};
+
+class PayloadEntryProxy//{{{
+{
+	protected:
+		Payload* _payload;
+		std::string _key;
+	public:
+		PayloadEntryProxy(Payload* payload, const std::string& key);
+		PayloadEntryProxy& operator=(const std::string& value);
+		operator std::string();
+		operator long();
+		operator double();
+		inline std::string to_str() { return operator std::string(); }
+		inline long to_int() { return operator long(); }
+		inline double to_float() { return operator double(); }
+};//}}}
+
+class Payload//{{{
+{
+	friend std::ostream& operator<<(std::ostream& os, const Payload& obj);
+	friend class IUInterface;
+	friend class IU;
+	friend class RemotePushIU;
+	friend class IUConverter;
+	friend class CallbackIUPayloadUpdate;
+	protected:
+		std::string _owner_name;
+		std::map<std::string, std::string> _store;
+		boost::shared_ptr<IUInterface> _iu;
+	protected:
+		void initialize(boost::shared_ptr<IUInterface> iu);
+		inline void _set_owner_name(const std::string& name) { _owner_name = name; }
+		void _remotely_enforced_wipe();
+		void _remotely_enforced_delitem(const std::string& k);
+		void _remotely_enforced_setitem(const std::string& k, const std::string& v);
+		void _internal_replace_all(const std::map<std::string, std::string>& new_contents, const std::string& writer_name="");
+		void _internal_set(const std::string& k, const std::string& v, const std::string& writer_name="");
+		void _internal_remove(const std::string& k, const std::string& writer_name="");
+	public:
+		inline const std::string& owner_name() { return _owner_name; }
+		// access
+		PayloadEntryProxy operator[](const std::string& key);
+		inline void set(const std::string& k, const std::string& v) { _internal_set(k, v); }
+		inline void remove(const std::string& k) { _internal_remove(k); }
+		std::string get(const std::string& k);
+	typedef boost::shared_ptr<Payload> ptr;
+};//}}}
+
+class IUInterface {//{{{
+	friend class IUConverter;
+	friend std::ostream& operator<<(std::ostream& os, const IUInterface& obj);
+	protected:
+		IUInterface();
+	public:
+		inline virtual ~IUInterface() { }
+	protected:
+		std::string _uid;
+		revision_t _revision;
+		std::string _category;
+		std::string _payload_type; // default is "MAP"
+		std::string _owner_name;
+		bool _committed;
+		IUAccessMode _access_mode;
+		bool _read_only;
+		//boost::shared_ptr<Buffer> _buffer;
+		Buffer* _buffer;
+		SmartLinkMap _links;
+	protected:
+		friend class Payload;
+		// Internal functions that perform the update logic,
+		//  e.g. sending a notification across the network
+		_IPAACA_ABSTRACT_ virtual void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name) = 0;
+		_IPAACA_ABSTRACT_ virtual void _modify_payload(bool is_delta, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name) = 0;
+		//void _set_buffer(boost::shared_ptr<Buffer> buffer);
+		void _associate_with_buffer(Buffer* buffer);
+		void _set_buffer(Buffer* buffer);
+		void _set_uid(const std::string& uid);
+		void _set_owner_name(const std::string& owner_name);
+	protected:
+		// internal functions that do not emit update events
+		inline void _add_and_remove_links(const LinkMap& add, const LinkMap& remove) { _links._add_and_remove_links(add, remove); }
+		inline void _replace_links(const LinkMap& links) { _links._replace_links(links); }
+	public:
+		inline bool is_published() { return (_buffer != 0); }
+		inline const std::string& uid() const { return _uid; }
+		inline revision_t revision() const { return _revision; }
+		inline const std::string& category() const { return _category; }
+		inline const std::string& payload_type() const { return _payload_type; }
+		inline const std::string& owner_name() const { return _owner_name; }
+		inline bool committed() const { return _committed; }
+		inline IUAccessMode access_mode() const { return _access_mode; }
+		inline bool read_only() const { return _read_only; }
+		//inline boost::shared_ptr<Buffer> buffer() { return _buffer; }
+		inline Buffer* buffer() const { return _buffer; }
+		inline const LinkSet& get_links(std::string type) { return _links.get_links(type); }
+		inline const LinkMap& get_all_links() { return _links.get_all_links(); }
+		// Payload
+		_IPAACA_ABSTRACT_ virtual Payload& payload() = 0;
+		_IPAACA_ABSTRACT_ virtual const Payload& const_payload() const = 0;
+		// setters
+		_IPAACA_ABSTRACT_ virtual void commit() = 0;
+		// functions to modify and update links:
+		void add_links(const std::string& type, const LinkSet& targets, const std::string& writer_name = "");
+		void remove_links(const std::string& type, const LinkSet& targets, const std::string& writer_name = "");
+		void modify_links(const LinkMap& add, const LinkMap& remove, const std::string& writer_name = "");
+		void set_links(const LinkMap& links, const std::string& writer_name = "");
+		//    (with cpp specific convenience functions:)
+		void add_link(const std::string& type, const std::string& target, const std::string& writer_name = "");
+		void remove_link(const std::string& type, const std::string& target, const std::string& writer_name = "");
+	typedef boost::shared_ptr<IUInterface> ptr;
+};//}}}
+
+class IU: public IUInterface {//{{{
+	friend class Buffer;
+	friend class InputBuffer;
+	friend class OutputBuffer;
+	friend class CallbackIUPayloadUpdate;
+	friend class CallbackIULinkUpdate;
+	friend class CallbackIUCommission;
+	public:
+		Payload _payload;
+	protected:
+		Lock _revision_lock;
+	protected:
+		inline void _increase_revision_number() { _revision++; }
+		IU(const std::string& category, IUAccessMode access_mode=IU_ACCESS_PUSH, bool read_only=false, const std::string& payload_type="MAP" );
+	public:
+		inline ~IU() {
+			IPAACA_IMPLEMENT_ME
+		}
+		static boost::shared_ptr<IU> create(const std::string& category, IUAccessMode access_mode=IU_ACCESS_PUSH, bool read_only=false, const std::string& payload_type="MAP" );
+		inline Payload& payload() { return _payload; }
+		inline const Payload& const_payload() const { return _payload; }
+		void commit();
+	protected:
+		void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "");
+		void _modify_payload(bool is_delta, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name = "");
+	protected:
+		void _internal_commit(const std::string& writer_name = "");
+	public:
+	typedef boost::shared_ptr<IU> ptr;
+};//}}}
+
+class RemotePushIU: public IUInterface {//{{{
+	friend class Buffer;
+	friend class InputBuffer;
+	friend class OutputBuffer;
+	friend class IUConverter;
+	public:
+		Payload _payload;
+	protected:
+		RemotePushIU();
+		static boost::shared_ptr<RemotePushIU> create();
+	public:
+		inline ~RemotePushIU() {
+			IPAACA_IMPLEMENT_ME
+		}
+		inline Payload& payload() { return _payload; }
+		inline const Payload& const_payload() const { return _payload; }
+		void commit();
+	protected:
+		void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "");
+		void _modify_payload(bool is_delta, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name = "");
+	protected:
+		void _apply_update(IUPayloadUpdate::ptr update);
+		void _apply_link_update(IULinkUpdate::ptr update);
+		void _apply_commission();
+	typedef boost::shared_ptr<RemotePushIU> ptr;
+};//}}}
+
+class Exception: public std::exception//{{{
+{
+	protected:
+		std::string _description;
+		inline Exception(const std::string& description=""): _description(description) { }
+	public:
+		inline ~Exception() throw() { }
+		const char* what() const throw() {
+			return _description.c_str();
+		}
+};//}}}
+class IUNotFoundError: public Exception//{{{
+{
+	public:
+		inline ~IUNotFoundError() throw() { }
+		inline IUNotFoundError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUNotFoundError";
+		}
+};//}}}
+class IUPublishedError: public Exception//{{{
+{
+	public:
+		inline ~IUPublishedError() throw() { }
+		inline IUPublishedError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUPublishedError";
+		}
+};//}}}
+class IUCommittedError: public Exception//{{{
+{
+	public:
+		inline ~IUCommittedError() throw() { }
+		inline IUCommittedError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUCommittedError";
+		}
+};//}}}
+class IUUpdateFailedError: public Exception//{{{
+{
+	public:
+		inline ~IUUpdateFailedError() throw() { }
+		inline IUUpdateFailedError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUUpdateFailedError";
+		}
+};//}}}
+class IUReadOnlyError: public Exception//{{{
+{
+	public:
+		inline ~IUReadOnlyError() throw() { }
+		inline IUReadOnlyError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUReadOnlyError";
+		}
+};//}}}
+class IUAlreadyInABufferError: public Exception//{{{
+{
+	public:
+		inline ~IUAlreadyInABufferError() throw() { }
+		inline IUAlreadyInABufferError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUAlreadyInABufferError";
+		}
+};//}}}
+class IUAlreadyHasAnUIDError: public Exception//{{{
+{
+	public:
+		inline ~IUAlreadyHasAnUIDError() throw() { }
+		inline IUAlreadyHasAnUIDError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUAlreadyHasAnUIDError";
+		}
+};//}}}
+class IUAlreadyHasAnOwnerNameError: public Exception//{{{
+{
+	public:
+		inline ~IUAlreadyHasAnOwnerNameError() throw() { }
+		inline IUAlreadyHasAnOwnerNameError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUAlreadyHasAnOwnerNameError";
+		}
+};//}}}
+class NotImplementedError: public Exception//{{{
+{
+	public:
+		inline ~NotImplementedError() throw() { }
+		inline NotImplementedError() { //boost::shared_ptr<IU> iu) {
+			_description = "NotImplementedError";
+		}
+};//}}}
+
+// (snippets) //{{{
+/*
+class IUEventFunctionHandler: public rsb::EventFunctionHandler {
+	protected:
+		Buffer* _buffer;
+	public:
+		inline IUEventFunctionHandler(Buffer* buffer, const EventFunction& function, const std::string& method="")
+			: EventFunctionHandler(function, method), _buffer(buffer) { }
+};
+*/
+//}}}
+
+} // of namespace ipaaca
+
+#endif
+
+
diff --git a/cpp/ivy.xml b/cpp/ivy.xml
index 3c822f4..2d44e20 100644
--- a/cpp/ivy.xml
+++ b/cpp/ivy.xml
@@ -1,5 +1,7 @@
 <ivy-module version="2.0">
-   <info organisation="HMI" module="IpaacaCpp" />
+   <info organisation="ipaaca" module="IpaacaCpp" />
    <dependencies>
+      <dependency org="google" name="protobuf" rev="latest.release"/>
+      <dependency org="rsb" name="rsb" rev="latest.release"/>
    </dependencies>
 </ivy-module>
diff --git a/cpp/test/src/rsb.conf b/cpp/test/src/rsb.conf
new file mode 100644
index 0000000..3fb0a68
--- /dev/null
+++ b/cpp/test/src/rsb.conf
@@ -0,0 +1,5 @@
+[transport.spread]
+host = localhost
+port = 4803
+enabled = 1
+
diff --git a/python/test/src/ipaacaspam.py b/python/test/src/ipaacaspam.py
index 69722ad..32d3923 100755
--- a/python/test/src/ipaacaspam.py
+++ b/python/test/src/ipaacaspam.py
@@ -97,6 +97,24 @@ class Sender(object):
 				self.counter = 0
 				#print ".",
 				#sys.stdout.flush()
+
+class TestAcker(object):
+	def __init__(self):
+		self.ib = ipaaca.InputBuffer('TestIn', ['testcategory'])
+		self.ib.register_handler(self.handle_iu_event)
+	
+	def handle_iu_event(self, iu, event_type, local):
+		print "Received a testcategory event ", event_type
+		if event_type=='ADDED':
+			try:
+				iu.payload['ack'] = 'ack'
+			except ipaaca.IUUpdateFailedError, e:
+				print "== tried to send an initial update, but someone else was quicker."
+	
+	def run(self):
+		while True:
+			time.sleep(1)
+
 	
 if __name__ == '__main__':
 	if len(sys.argv)<2:
@@ -125,6 +143,9 @@ if __name__ == '__main__':
 			sys.exit(1)
 		s = Sender(send_frequency=freq)
 		s.run()
+	elif sys.argv[1] == 'testacker':
+		r = TestAcker()
+		r.run()
 	else:
 		print "specify either 'sender', 'receiver', 'ping' or 'pong' as an argument"
 		sys.exit(1)
-- 
GitLab