[runtime] rts serialization additions

1. Increment rts-pingpong model to include more complex data.
2. Add UMLRTInMessage
3. Debug UMLRTObject_class encode/decode/fprintf.
4. Add fields to UMLRTObject_class and UMLRTObject_field
5. Resolve Bug 467789 - missing RTType for long double.
6. Resolve Bug 467787 - segfault when incarnating a capsule with no ports

Change-Id: I1a06221ffc6eb87cbcd7037c972d59964bfc25b5
Signed-off-by: Barry Maher <bmaher@gpinc.ca>
diff --git a/.gitignore b/.gitignore
index a291f7e..b848b16 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,4 @@
 rts/build
 rts/lib
 rts/test/rts-pingpong/main
-rts/test/rts-pingpong/*.o
+*.o
diff --git a/rts/Makefile b/rts/Makefile
index 1efb7d4..b862691 100644
--- a/rts/Makefile
+++ b/rts/Makefile
@@ -182,6 +182,7 @@
     $(BUILDROOT)/umlrt/umlrtframeprotocol.o \
     $(BUILDROOT)/umlrt/umlrtframeservice.o \
     $(BUILDROOT)/umlrt/umlrthashmap.o \
+    $(BUILDROOT)/umlrt/umlrtinmessage.o \
     $(BUILDROOT)/umlrt/umlrtinsignal.o \
     $(BUILDROOT)/umlrt/umlrtlogprotocol.o \
     $(BUILDROOT)/umlrt/umlrtmain.o \
diff --git a/rts/include/umlrtcapsule.hh b/rts/include/umlrtcapsule.hh
index 8812ff5..7b2dd0a 100644
--- a/rts/include/umlrtcapsule.hh
+++ b/rts/include/umlrtcapsule.hh
@@ -25,7 +25,7 @@
 // Sub-classes define the model's capsules and contain user-defined and methods.
 
 struct UMLRTSlot;
-struct UMLRTMessage;
+struct UMLRTInMessage;
 struct UMLRTController;
 struct UMLRTCapsuleClass;
 class UMLRTRtsInterface;
@@ -34,8 +34,8 @@
 {
 public:
     virtual ~UMLRTCapsule ( );
-    virtual void initialize ( const UMLRTMessage & msg ) = 0;
-    virtual void inject ( const UMLRTMessage & msg ) = 0;
+    virtual void initialize ( const UMLRTInMessage & msg ) = 0;
+    virtual void inject ( const UMLRTInMessage & msg ) = 0;
     virtual void unbindPort ( bool isBorder, int portIndex, int farEndIndex );
     virtual void bindPort ( bool isBorder, int portIndex, int farEndIndex );
 
diff --git a/rts/include/umlrtinmessage.hh b/rts/include/umlrtinmessage.hh
new file mode 100644
index 0000000..3c45ed7
--- /dev/null
+++ b/rts/include/umlrtinmessage.hh
@@ -0,0 +1,30 @@
+// umlrtinmessage.hh
+
+/*******************************************************************************
+* Copyright (c) 2015 Zeligsoft (2009) Limited  and others.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*******************************************************************************/
+
+#ifndef UMLRTINMESSAGE_HH
+#define UMLRTINMESSAGE_HH
+
+#include <stdint.h>
+#include "umlrtmessage.hh"
+
+class UMLRTInMessage : public UMLRTMessage
+{
+public:
+
+    UMLRTInMessage ( ) : UMLRTMessage() {};
+
+    int getSignalId ( ) const { return signal.getId(); }
+
+    void decodeInit ( const UMLRTObject_class * desc ) const;
+    void decode ( void * data, int arraySize = 1 ) const;
+    void decode ( int ptrIndirection, void * data, int arraySize = 1 ) const;
+};
+
+#endif // UMLRTMESSAGE_HH
diff --git a/rts/include/umlrtinsignal.hh b/rts/include/umlrtinsignal.hh
index f1b6b78..6bfe421 100644
--- a/rts/include/umlrtinsignal.hh
+++ b/rts/include/umlrtinsignal.hh
@@ -27,11 +27,8 @@
     // for the FIRST call to the #decode methods, after which is it modified
     // during decoding (i.e. is an input/output parameter to #decode methods).
 
-    // Bug 101 tracks buffer-overrun detection.
-    // Initial version will have FATAL called if decoding fails (e.g. runs out of payload).
-    // Other behaviour can be specified later.
-    void decode( void * * decodeInfo, void * data, const UMLRTObject_class * desc, int arraySize = 1 ) const;
-    void decode( void * * decodeInfo, int ptrIndirection, void * data, const UMLRTObject_class * desc, int arraySize = 1 ) const;
+    void decode( const void * * decodeInfo, const UMLRTObject_class * desc, void * data, int arraySize = 1 ) const;
+    void decode( const void * * decodeInfo, const UMLRTObject_class * desc, int ptrIndirection, void * data, int arraySize = 1 ) const;
 
    // Delete all deferred signals of this type on all port instances. Returns the number of deleted messages.
     int purge();
diff --git a/rts/include/umlrtlogprotocol.hh b/rts/include/umlrtlogprotocol.hh
index 4d48b13..1f0b1cf 100644
--- a/rts/include/umlrtlogprotocol.hh
+++ b/rts/include/umlrtlogprotocol.hh
@@ -40,7 +40,7 @@
     int log ( unsigned long long ull ) const;
     int log ( float f ) const;
     int log ( double d ) const;
-    int log ( const void * userData, const UMLRTObject_class * type ) const;
+    int log ( const void * userData, const UMLRTObject_class * type, int arraySize = 1 ) const;
     int log ( const UMLRTTypedValue & value ) const;
 
     // Output data with NO new-line appended.
@@ -57,7 +57,7 @@
     int show ( unsigned long long ull ) const;
     int show ( float f ) const;
     int show ( double d ) const;
-    int show ( const void * userData, const UMLRTObject_class * type ) const;
+    int show ( const void * userData, const UMLRTObject_class * type, int arraySize = 1 ) const;
     int show ( const UMLRTTypedValue & value ) const;
 
     // Output newline(s).
diff --git a/rts/include/umlrtmessage.hh b/rts/include/umlrtmessage.hh
index 2e2f7fe..028c515 100644
--- a/rts/include/umlrtmessage.hh
+++ b/rts/include/umlrtmessage.hh
@@ -35,7 +35,7 @@
 {
 public:
 
-    UMLRTMessage() : srcPortIndex(0), sapIndex0(0), destPort(NULL), destSlot(NULL), isCommand(false) {};
+    UMLRTMessage() : srcPortIndex(0), sapIndex0(0), destPort(NULL), destSlot(NULL), desc(NULL), decodeInfo(NULL), isCommand(false), allocated(false) {};
 
     size_t srcPortIndex; // The associated srcPort of the message is contained within the signal.
     size_t sapIndex0; // The port index on the receive side.
@@ -45,6 +45,9 @@
 
     UMLRTSignal signal;
 
+    mutable const UMLRTObject_class * desc;
+    mutable const void * decodeInfo;
+
     unsigned isCommand : 1;   // true when it's a command and not a signal.
     unsigned allocated : 1;   // For sanity checking of message allocation.
 
diff --git a/rts/include/umlrtobjectclass.hh b/rts/include/umlrtobjectclass.hh
index 17cd28a..5a86b78 100644
--- a/rts/include/umlrtobjectclass.hh
+++ b/rts/include/umlrtobjectclass.hh
@@ -44,13 +44,9 @@
     const char * name;
     const UMLRTObject_class * desc;
     int offset;
-    int ptrIndirection;
-};
-
-// Fields types which are arrays have the (additional) array size as part of the type descriptor.
-struct UMLRTObject_arrayField : public UMLRTObject_field
-{
+    int sizeDecoded;
     int arraySize;
+    int ptrIndirection;
 };
 
 // All types are described by a 'data descriptor', namely a UMLRTObject_class.
@@ -69,18 +65,21 @@
 {
     const char * const name;
 
-    void * ( * initialize )( const UMLRTObject_class * desc, void * data );
-    void * ( * copy )( const UMLRTObject_class * desc, const void * src, void * dst );
-    void * ( * decode )( const UMLRTObject_class * desc, const void * src, void * dst );
-    void * ( * encode )( const UMLRTObject_class * desc, const void * src, void * dst );
-    void * ( * destroy )( const UMLRTObject_class * desc, void * data );
-    size_t ( * getSize )( const UMLRTObject_class * desc );
-    int ( * fprintf )( FILE * ostream, const UMLRTObject_class * desc, const void * data ); // returns number of chars output.
+    void * ( * initialize ) ( const UMLRTObject_class * desc, void * data );
+    void * ( * copy ) ( const UMLRTObject_class * desc, const void * src, void * dst );
+    // decode returns pointer to next byte in decoded bytes.
+    const void * ( * decode ) ( const UMLRTObject_class * desc, const void * src, void * dst, int nest );
+    // encode returns pointer to next byte in encoded bytes.
+    void * ( * encode ) ( const UMLRTObject_class * desc, const void * src, void * dst, int nest );
+    void * ( * destroy ) ( const UMLRTObject_class * desc, void * data );
+    size_t ( * getSize ) ( const UMLRTObject_class * desc );
+    int ( * fprintf ) ( FILE * ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize ); // returns number of chars output.
 
     const UMLRTObject_class * const super; // Base type
     const uint16_t version;
     const uint16_t backwards;
-    const size_t size; // Is either size of type (fields NULL) or number of fields (fields non-NULL)
+    const int sizeDecoded; // Size of a decoded element of this type.
+    const int size; // Is either encoded size of basic type (fields NULL) or number of fields (fields non-NULL)
     const UMLRTObject_field * fields;
 };
 
@@ -92,14 +91,15 @@
 };
 
 // A set of default functions for basic data-descriptions (types) are pre-defined.
-extern void * UMLRTObject_initialize( const UMLRTObject_class * desc, void * data );
-extern void * UMLRTObject_copy( const UMLRTObject_class * desc, const void * src, void * dst );
-extern void * UMLRTObject_decode( const UMLRTObject_class * desc, const void * src, void * dst );
-extern void * UMLRTObject_encode( const UMLRTObject_class * desc, const void * src, void * dst );
-extern void * UMLRTObject_destroy( const UMLRTObject_class * desc, void * data );
-extern size_t UMLRTObject_getSize( const UMLRTObject_class * desc );
-// Returns the number of characters that were printed.
-extern int UMLRTObject_fprintf( FILE *ostream, const UMLRTObject_class * desc, const void * data );
+extern void * UMLRTObject_initialize ( const UMLRTObject_class * desc, void * data );
+extern void * UMLRTObject_copy ( const UMLRTObject_class * desc, const void * src, void * dst );
+extern const void * UMLRTObject_decode ( const UMLRTObject_class * desc, const void * src, void * dst, int nest );
+extern void * UMLRTObject_encode ( const UMLRTObject_class * desc, const void * src, void * dst, int nest );
+extern void * UMLRTObject_destroy ( const UMLRTObject_class * desc, void * data );
+extern size_t UMLRTObject_getSize ( const UMLRTObject_class * desc );
+
+// The following returns the number of characters that were printed.
+extern int UMLRTObject_fprintf( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize );
 
 // These are the primitive data-types with pre-defined data descriptors.
 extern const UMLRTObject_class * const UMLRTType_bool;
diff --git a/rts/include/umlrtoutsignal.hh b/rts/include/umlrtoutsignal.hh
index 944b5cf..acb9365 100644
--- a/rts/include/umlrtoutsignal.hh
+++ b/rts/include/umlrtoutsignal.hh
@@ -27,11 +27,8 @@
     // The encoding keeps track of where in the payload the next data-item should be
     // serialized. The 'initialize' function initializes the encoding and each call
     // to the encoding functions moves the encoding-location forward.
-
-    // Currently, FATAL is called if encoding fails (e.g. runs out of payload).
-    // Other behaviour can be specified later.
-    void encode( const void * data, const UMLRTObject_class * desc, int arraySize = 1 );
-    void encode( int ptrIndirection, void * data, const UMLRTObject_class * desc, int arraySize = 1 );
+    void encode( const UMLRTObject_class * desc, const void * data, int arraySize = 1 );
+    void encode( const UMLRTObject_class * desc, int ptrIndirection, void * data, int arraySize = 1 );
 
     // Synchronous send out all port instances. Returns the number of replies (0 if fail).
     int invoke( UMLRTMessage * replyMsgs );
diff --git a/rts/include/umlrtprioritymessagequeue.hh b/rts/include/umlrtprioritymessagequeue.hh
index 570266d..b233c6d 100644
--- a/rts/include/umlrtprioritymessagequeue.hh
+++ b/rts/include/umlrtprioritymessagequeue.hh
@@ -11,7 +11,7 @@
 #ifndef UMLRTPRIORITYMESSAGEQUEUE_HH
 #define UMLRTPRIORITYMESSAGEQUEUE_HH
 
-#include "umlrtmessage.hh"
+#include "umlrtinmessage.hh"
 #include "umlrtmessagequeue.hh"
 #include "umlrtsemaphore.hh"
 #include "umlrtsignal.hh"
@@ -43,7 +43,7 @@
     void queueTimerMessages( UMLRTTimerQueue * timerQueue );
 
     // Get the highest priority message from the collection of queues.
-    UMLRTMessage * dequeueHighestPriority();
+    UMLRTInMessage * dequeueHighestPriority();
 
     // Put the message into its appropriate priority-queue.
     void enqueue( UMLRTMessage * msg, bool front = false );
diff --git a/rts/include/umlrtsignalelement.hh b/rts/include/umlrtsignalelement.hh
index ecf0312..6f10fe4 100644
--- a/rts/include/umlrtsignalelement.hh
+++ b/rts/include/umlrtsignalelement.hh
@@ -80,13 +80,13 @@
     Priority getPriority() const { return priority; }
     void setPriority( Priority priority_) { priority = priority_; }
 
-    // See documentation in UMLRTSignal.
+    // Encode 'data' buffer into payload.
     void encode( const UMLRTObject_class * desc, const void * data, int arraySize = 1 );
     void encode( const UMLRTObject_class * desc, int ptrIndirection, const void * data, int arraySize = 1 );
 
-    // See documentation in UMLRTSignal.
-    void decode( void * * decodeInfo, const UMLRTObject_class * desc, void * data, int arraySize = 1 );
-    void decode( void * * decodeInfo, const UMLRTObject_class * desc, int ptrIndirection, void * data, int arraySize = 1 );
+    // Decode payload into 'data' buffer.
+    void decode( const void * * decodeInfo, const UMLRTObject_class * desc, void * data, int arraySize = 1 );
+    void decode( const void * * decodeInfo, const UMLRTObject_class * desc, int ptrIndirection, void * data, int arraySize = 1 );
 
     // Pool allocation sanity check.
     void setAllocated( bool allocated_ );
diff --git a/rts/test/rts-pingpong/DataType1.cc b/rts/test/rts-pingpong/DataType1.cc
index 3e5f119..fef44b1 100644
--- a/rts/test/rts-pingpong/DataType1.cc
+++ b/rts/test/rts-pingpong/DataType1.cc
@@ -4,31 +4,91 @@
 #include "umlrtobjectclass.hh"
 #include <cstddef>
 
+static const UMLRTObject_field sst1fields[] =
+{
+    {
+        "name",
+        UMLRTType_char,
+        offsetof( SubStructType1, name ),
+        sizeof(((struct SubStructType1 *)0)->name[0]),
+        8,
+        0
+    },
+    {
+        "character",
+        UMLRTType_char,
+        offsetof( SubStructType1, character),
+        sizeof(((struct SubStructType1 *)0)->character),
+        1,
+        0
+    },
+    {
+        "integer",
+        UMLRTType_int,
+        offsetof( SubStructType1, integer ),
+        sizeof(((struct SubStructType1 *)0)->integer),
+        1,
+        0
+    },
+};
 
+static const UMLRTObject_class sst1desc =
+{
+    "SubStructType1",
+    UMLRTObject_initialize,
+    UMLRTObject_copy,
+    UMLRTObject_decode,
+    UMLRTObject_encode,
+    UMLRTObject_destroy,
+    UMLRTObject_getSize,
+    UMLRTObject_fprintf,
+    NULL,
+    UMLRTOBJECTCLASS_DEFAULT_VERSION,
+    UMLRTOBJECTCLASS_DEFAULT_BACKWARDS,
+    sizeof(SubStructType1),
+    3,
+    sst1fields
+};
 
+const UMLRTObject_class * const RTType_SubStruct1 = &sst1desc;
 
-static const UMLRTObject_field fields[] = 
+static const UMLRTObject_field dt1fields[] =
 {
     {
         "field1_int",
         UMLRTType_int,
         offsetof( DataType1, field1_int ),
+        sizeof(((struct DataType1 *)0)->field1_int[0]),
+        2,
         0
     },
     {
         "field2_bool",
         UMLRTType_bool,
         offsetof( DataType1, field2_bool ),
+        sizeof(((struct DataType1 *)0)->field2_bool),
+        1,
         0
     },
     {
         "field3_double",
         UMLRTType_double,
         offsetof( DataType1, field3_double ),
+        sizeof(((struct DataType1 *)0)->field3_double),
+        1,
         0
-    }
+    },
+    {
+        "field4_sst1",
+        RTType_SubStruct1,
+        offsetof( DataType1, field4_sst1 ),
+        sizeof(((struct DataType1 *)0)->field4_sst1[0]),
+        3,
+        0
+    },
+
 };
-static const UMLRTObject_class desc = 
+static const UMLRTObject_class dt1desc =
 {
     "DataType1",
     UMLRTObject_initialize,
@@ -41,7 +101,9 @@
     NULL,
     UMLRTOBJECTCLASS_DEFAULT_VERSION,
     UMLRTOBJECTCLASS_DEFAULT_BACKWARDS,
-    3,
-    fields
+    sizeof(DataType1),
+    4,
+    dt1fields
 };
-const UMLRTObject_class * const RTType_DataType1 = &desc;
+
+const UMLRTObject_class * const RTType_DataType1 = &dt1desc;
diff --git a/rts/test/rts-pingpong/DataType1.hh b/rts/test/rts-pingpong/DataType1.hh
index e6b3af8..ce1c122 100644
--- a/rts/test/rts-pingpong/DataType1.hh
+++ b/rts/test/rts-pingpong/DataType1.hh
@@ -4,12 +4,21 @@
 
 struct UMLRTObject_class;
 
+struct SubStructType1
+{
+    char name[8];
+    char character; // Force alignment to insert padding.
+    int integer;
+};
+
 struct DataType1
 {
-    int field1_int;
+    int field1_int[2];
     bool field2_bool;
     double field3_double;
+    SubStructType1 field4_sst1[3];
 };
+extern const UMLRTObject_class * const RTType_SubStructType1;
 extern const UMLRTObject_class * const RTType_DataType1;
 
 #endif
diff --git a/rts/test/rts-pingpong/Makefile b/rts/test/rts-pingpong/Makefile
index 17b57ce..c9f3905 100644
--- a/rts/test/rts-pingpong/Makefile
+++ b/rts/test/rts-pingpong/Makefile
@@ -3,7 +3,7 @@
 ################################################
 
 # Location of RTS root.
-UMLRTS_ROOT ?= /home/barrymintzs/org.eclipse2/org.eclipse.papyrus-rt/rts
+UMLRTS_ROOT ?= ../../../rts
 
 # Compiler
 # This can be overridden while invoking make with CC=xxx.
diff --git a/rts/test/rts-pingpong/PingPongProtocol.cc b/rts/test/rts-pingpong/PingPongProtocol.cc
index 082777d..06ba27d 100644
--- a/rts/test/rts-pingpong/PingPongProtocol.cc
+++ b/rts/test/rts-pingpong/PingPongProtocol.cc
@@ -7,42 +7,71 @@
 struct UMLRTCommsPort;
 
 
-UMLRTOutSignal PingPongProtocol::OutSignals::ping( const UMLRTCommsPort * sourcePort, const DataType1 & param ) const
+UMLRTOutSignal PingPongProtocol::OutSignals::ping ( const UMLRTCommsPort * sourcePort, const DataType1 (& param)[2] ) const
 {
     UMLRTOutSignal signal;
-    signal.initialize( signal_ping, sourcePort, sizeof( param ) );
-    memcpy( signal.getPayload(), &param, sizeof( param ) );
+    if (signal.initialize( signal_ping, sourcePort, RTType_DataType1->getSize(RTType_DataType1)*2))
+    {
+        signal.encode(RTType_DataType1, &param, 2);
+    }
+    return signal;
+}
+
+UMLRTInSignal PingPongProtocol::OutSignals::pong ( const UMLRTCommsPort * sourcePort ) const
+{
+    UMLRTInSignal signal;
+    signal.initialize( signal_pong, sourcePort );
     return signal;
 }
 
 
-UMLRTOutSignal PingPongProtocol::InSignals::pong( const UMLRTCommsPort * sourcePort ) const
+UMLRTOutSignal PingPongProtocol::InSignals::pong ( const UMLRTCommsPort * sourcePort, const DataType1 (& param)[2] ) const
 {
     UMLRTOutSignal signal;
-    signal.initialize( signal_pong, sourcePort, 0 );
+    if (signal.initialize( signal_pong, sourcePort, RTType_DataType1->getSize(RTType_DataType1)*2))
+    {
+        signal.encode(RTType_DataType1, &param, 2);
+    }
+    return signal;
+}
+
+UMLRTInSignal PingPongProtocol::InSignals::ping ( const UMLRTCommsPort * sourcePort ) const
+{
+    UMLRTInSignal signal;
+    signal.initialize( signal_ping, sourcePort );
     return signal;
 }
 
 
 
 
-PingPongProtocol_baserole::PingPongProtocol_baserole( const UMLRTCommsPort * srcPort )
+PingPongProtocol_baserole::PingPongProtocol_baserole ( const UMLRTCommsPort * srcPort )
 : UMLRTProtocol( srcPort )
 {
 }
 
-UMLRTOutSignal PingPongProtocol_baserole::ping( const DataType1 & param ) const
+UMLRTOutSignal PingPongProtocol_baserole::ping ( const DataType1 (& param)[2] ) const
 {
     return PingPongProtocol::Base::ping( srcPort, param );
 }
 
+UMLRTInSignal PingPongProtocol_baserole::pong ( ) const
+{
+    return PingPongProtocol::Base::pong( srcPort );
+}
+
 PingPongProtocol_conjrole::PingPongProtocol_conjrole( const UMLRTCommsPort * srcPort )
 : UMLRTProtocol( srcPort )
 {
 }
 
-UMLRTOutSignal PingPongProtocol_conjrole::pong() const
+UMLRTOutSignal PingPongProtocol_conjrole::pong( const DataType1 (& param)[2] ) const
 {
-    return PingPongProtocol::Conjugate::pong( srcPort );
+    return PingPongProtocol::Conjugate::pong( srcPort, param );
+}
+
+UMLRTInSignal PingPongProtocol_conjrole::ping ( ) const
+{
+    return PingPongProtocol::Conjugate::ping( srcPort );
 }
 
diff --git a/rts/test/rts-pingpong/PingPongProtocol.hh b/rts/test/rts-pingpong/PingPongProtocol.hh
index 325a79c..3c41f43 100644
--- a/rts/test/rts-pingpong/PingPongProtocol.hh
+++ b/rts/test/rts-pingpong/PingPongProtocol.hh
@@ -3,6 +3,7 @@
 #define PINGPONGPROTOCOL_HH
 
 #include "DataType1.hh"
+#include "umlrtinsignal.hh"
 #include "umlrtoutsignal.hh"
 #include "umlrtprotocol.hh"
 #include "umlrtsignal.hh"
@@ -19,12 +20,14 @@
     class OutSignals
     {
     public:
-        UMLRTOutSignal ping( const UMLRTCommsPort * sourcePort, const DataType1 & param ) const;
+        UMLRTOutSignal ping ( const UMLRTCommsPort * sourcePort, const DataType1 (& param)[2] ) const;
+        UMLRTInSignal pong ( const UMLRTCommsPort * sourcePort ) const;
     };
     class InSignals
     {
     public:
-        UMLRTOutSignal pong( const UMLRTCommsPort * sourcePort ) const;
+        UMLRTInSignal ping ( const UMLRTCommsPort * sourcePort ) const;
+        UMLRTOutSignal pong ( const UMLRTCommsPort * sourcePort, const DataType1 (& param)[2] ) const;
     };
     typedef OutSignals Base;
     typedef InSignals Conjugate;
@@ -32,14 +35,16 @@
 class PingPongProtocol_baserole : protected UMLRTProtocol, private PingPongProtocol::Base
 {
 public:
-    PingPongProtocol_baserole( const UMLRTCommsPort * srcPort );
-    UMLRTOutSignal ping( const DataType1 & param ) const;
+    PingPongProtocol_baserole ( const UMLRTCommsPort * srcPort );
+    UMLRTOutSignal ping ( const DataType1 (& param)[2] ) const;
+    UMLRTInSignal pong ( ) const;
 };
 class PingPongProtocol_conjrole : protected UMLRTProtocol, private PingPongProtocol::Conjugate
 {
 public:
-    PingPongProtocol_conjrole( const UMLRTCommsPort * srcPort );
-    UMLRTOutSignal pong() const;
+    PingPongProtocol_conjrole ( const UMLRTCommsPort * srcPort );
+    UMLRTOutSignal pong ( const DataType1 (& param)[2] ) const;
+    UMLRTInSignal ping ( ) const;
 };
 
 #endif
diff --git a/rts/test/rts-pingpong/Pinger.cc b/rts/test/rts-pingpong/Pinger.cc
index 6477137..0b7f501 100644
--- a/rts/test/rts-pingpong/Pinger.cc
+++ b/rts/test/rts-pingpong/Pinger.cc
@@ -7,16 +7,17 @@
 #include "umlrtcommsportfarend.hh"
 #include "umlrtcommsportrole.hh"
 #include "umlrtframeservice.hh"
-#include "umlrtmessage.hh"
+#include "umlrtinmessage.hh"
 #include "umlrtslot.hh"
 #include "umlrttimerprotocol.hh"
 #include <cstddef>
 class UMLRTRtsInterface;
 
 #include <iostream>
+#include <stdio.h>
 
 Capsule_Pinger::Capsule_Pinger( UMLRTSlot * st, const UMLRTCommsPort * * border, const UMLRTCommsPort * internal, bool isStat )
-: UMLRTCapsule( NULL, &Pinger, st, border, internal, isStat )
+: UMLRTCapsule( NULL, &Pinger, st, border, internal, isStat ), timeoutCount(0)
 {
 }
 
@@ -64,7 +65,7 @@
     }
 }
 
-void Capsule_Pinger::inject( const UMLRTMessage & msg )
+void Capsule_Pinger::inject( const UMLRTInMessage & msg )
 {
     switch( currentState )
     {
@@ -74,7 +75,7 @@
     }
 }
 
-void Capsule_Pinger::initialize( const UMLRTMessage & msg )
+void Capsule_Pinger::initialize( const UMLRTInMessage & msg )
 {
     actionchain_____top__initialise__ActionChain3( msg );
     currentState = top__Running;
@@ -82,55 +83,73 @@
 
 
 
-void Capsule_Pinger::entryaction_____top__initialise__ActionChain3__onEntry( const UMLRTMessage & msg )
+void Capsule_Pinger::entryaction_____top__initialise__ActionChain3__onEntry( const UMLRTInMessage & msg )
 {
     void * rtdata = *(void * *)msg.signal.getPayload();
 }
 
-void Capsule_Pinger::transitionaction_____top__initialise__ActionChain3__onInit( const UMLRTMessage & msg )
+void Capsule_Pinger::transitionaction_____top__initialise__ActionChain3__onInit( const UMLRTInMessage & msg )
 {
     void * rtdata = *(void * *)msg.signal.getPayload();
     std::cout << "Pinger initialised" << std::endl;
-    timerPort().informIn( UMLRTTimespec( 2, 0 ) );
+    timerPort().informEvery( UMLRTTimespec( 2, 0 ) );
 }
 
-void Capsule_Pinger::transitionaction_____top__onPong__ActionChain5__onPong( const UMLRTMessage & msg )
+void Capsule_Pinger::transitionaction_____top__onPong__ActionChain5__onPong( const UMLRTInMessage & msg )
+{
+    std::cout << getName() << ":received pong payload size " << msg.signal.getPayloadSize() << std::endl;
+    RTType_DataType1->fprintf(stdout, RTType_DataType1, msg.signal.getPayload(), 0/*nest*/, 2/*arraySize*/);
+    std::cout << std::endl;
+
+    DataType1 rtdata[2];
+    msg.decode(&rtdata, 2);
+    std::cout << getName() <<
+            " rtdata[2] size " << sizeof(rtdata) <<
+            " rtdata[0].field1_int[1] " << rtdata[0].field1_int[1] <<
+            " rtdata[1].sst1.[2].name " << rtdata[1].field4_sst1[2].name <<
+            " rtdata[1].sst1.[2].integer " << rtdata[1].field4_sst1[2].integer <<
+            std::endl;
+}
+
+void Capsule_Pinger::transitionaction_____top__onTimeout__ActionChain7__onTimeout( const UMLRTInMessage & msg )
 {
     void * rtdata = *(void * *)msg.signal.getPayload();
-    std::cout << "Pong received" << std::endl;
-    timerPort().informIn( UMLRTTimespec( 2, 0 ) );
+    DataType1 dt[2] = {
+            { {timeoutCount*10, timeoutCount*10 + 1}, (timeoutCount & 1) != 0, timeoutCount*10 + 3.,
+                    {{"start", 'a', timeoutCount*10 + 4}, {"middle", 'b', timeoutCount*10 + 5}, {"end", 'c', timeoutCount*10 + 6}}},
+            { {timeoutCount*10 + 7, timeoutCount*10 + 8}, (timeoutCount & 2) != 0, timeoutCount*10 + 9.,
+                {{"start2", 'd', timeoutCount*10 + 1}, {"middle2", 'e', timeoutCount*10 + 2}, {"end2", 'f', timeoutCount*10 + 3 }}},
+    };
+    std::cout << getName() << ":Sending ping from timeout transition action - timeoutCount " << timeoutCount << " " << std::endl;
+    UMLRTOutSignal s = PingPort().ping( dt );
+    std::cout << "Encoded parameter:" << std::endl;
+    RTType_DataType1->fprintf(stdout, RTType_DataType1, s.getPayload(), 0/*nest*/, 2/*arraySize*/);
+    s.send();
+    ++timeoutCount;
 }
 
-void Capsule_Pinger::transitionaction_____top__onTimeout__ActionChain7__onTimeout( const UMLRTMessage & msg )
-{
-    void * rtdata = *(void * *)msg.signal.getPayload();
-    std::cout << "Sending Ping from timeout transition action" << std::endl;
-    DataType1 dt = { 0, true, 3. };
-    PingPort().ping( dt ).send();
-}
-
-void Capsule_Pinger::actionchain_____top__initialise__ActionChain3( const UMLRTMessage & msg )
+void Capsule_Pinger::actionchain_____top__initialise__ActionChain3( const UMLRTInMessage & msg )
 {
     transitionaction_____top__initialise__ActionChain3__onInit( msg );
     entryaction_____top__initialise__ActionChain3__onEntry( msg );
 }
 
-void Capsule_Pinger::actionchain_____top__onPong__ActionChain5( const UMLRTMessage & msg )
+void Capsule_Pinger::actionchain_____top__onPong__ActionChain5( const UMLRTInMessage & msg )
 {
     transitionaction_____top__onPong__ActionChain5__onPong( msg );
 }
 
-void Capsule_Pinger::actionchain_____top__onTimeout__ActionChain7( const UMLRTMessage & msg )
+void Capsule_Pinger::actionchain_____top__onTimeout__ActionChain7( const UMLRTInMessage & msg )
 {
     transitionaction_____top__onTimeout__ActionChain7__onTimeout( msg );
 }
 
-Capsule_Pinger::State Capsule_Pinger::state_____top__Running( const UMLRTMessage & msg )
+Capsule_Pinger::State Capsule_Pinger::state_____top__Running( const UMLRTInMessage & msg )
 {
     switch( msg.destPort->role()->id )
     {
     case port_timerPort:
-        switch( msg.signal.getId() )
+        switch( msg.getSignalId() )
         {
         case UMLRTTimerProtocol::signal_timeout:
             actionchain_____top__onTimeout__ActionChain7( msg );
@@ -138,9 +157,10 @@
         }
         return currentState;
     case port_PingPort:
-        switch( msg.signal.getId() )
+        switch(  msg.getSignalId() )
         {
         case PingPongProtocol::signal_pong:
+            msg.decodeInit(RTType_DataType1); // Assume this is the place where parameter types are known.
             actionchain_____top__onPong__ActionChain5( msg );
             return top__Running;
         }
diff --git a/rts/test/rts-pingpong/Pinger.hh b/rts/test/rts-pingpong/Pinger.hh
index 98fcd44..2bebbf6 100644
--- a/rts/test/rts-pingpong/Pinger.hh
+++ b/rts/test/rts-pingpong/Pinger.hh
@@ -5,7 +5,7 @@
 #include "PingPongProtocol.hh"
 #include "umlrtcapsule.hh"
 #include "umlrtcapsuleclass.hh"
-#include "umlrtmessage.hh"
+#include "umlrtinmessage.hh"
 #include "umlrttimerprotocol.hh"
 struct UMLRTCommsPort;
 struct UMLRTSlot;
@@ -35,8 +35,8 @@
     };
     virtual void bindPort( bool isBorder, int portId, int index );
     virtual void unbindPort( bool isBorder, int portId, int index );
-    virtual void inject( const UMLRTMessage & msg );
-    virtual void initialize( const UMLRTMessage & msg );
+    virtual void inject( const UMLRTInMessage & msg );
+    virtual void initialize( const UMLRTInMessage & msg );
 private:
     enum State
     {
@@ -44,14 +44,16 @@
         SPECIAL_INTERNAL_STATE_UNVISITED
     };
     State currentState;
-    void entryaction_____top__initialise__ActionChain3__onEntry( const UMLRTMessage & msg );
-    void transitionaction_____top__initialise__ActionChain3__onInit( const UMLRTMessage & msg );
-    void transitionaction_____top__onPong__ActionChain5__onPong( const UMLRTMessage & msg );
-    void transitionaction_____top__onTimeout__ActionChain7__onTimeout( const UMLRTMessage & msg );
-    void actionchain_____top__initialise__ActionChain3( const UMLRTMessage & msg );
-    void actionchain_____top__onPong__ActionChain5( const UMLRTMessage & msg );
-    void actionchain_____top__onTimeout__ActionChain7( const UMLRTMessage & msg );
-    State state_____top__Running( const UMLRTMessage & msg );
+    void entryaction_____top__initialise__ActionChain3__onEntry( const UMLRTInMessage & msg );
+    void transitionaction_____top__initialise__ActionChain3__onInit( const UMLRTInMessage & msg );
+    void transitionaction_____top__onPong__ActionChain5__onPong( const UMLRTInMessage & msg );
+    void transitionaction_____top__onTimeout__ActionChain7__onTimeout( const UMLRTInMessage & msg );
+    void actionchain_____top__initialise__ActionChain3( const UMLRTInMessage & msg );
+    void actionchain_____top__onPong__ActionChain5( const UMLRTInMessage & msg );
+    void actionchain_____top__onTimeout__ActionChain7( const UMLRTInMessage & msg );
+    State state_____top__Running( const UMLRTInMessage & msg );
+
+    int timeoutCount;
 };
 extern const UMLRTCapsuleClass Pinger;
 
diff --git a/rts/test/rts-pingpong/Ponger.cc b/rts/test/rts-pingpong/Ponger.cc
index 7f68194..ba871db 100644
--- a/rts/test/rts-pingpong/Ponger.cc
+++ b/rts/test/rts-pingpong/Ponger.cc
@@ -8,13 +8,14 @@
 #include "umlrtcommsportfarend.hh"
 #include "umlrtcommsportrole.hh"
 #include "umlrtframeservice.hh"
-#include "umlrtmessage.hh"
+#include "umlrtinmessage.hh"
 #include "umlrtsignal.hh"
 #include "umlrtslot.hh"
 #include <cstddef>
 class UMLRTRtsInterface;
 
 #include <iostream>
+#include <stdio.h>
 
 Capsule_Ponger::Capsule_Ponger( UMLRTSlot * st, const UMLRTCommsPort * * border, const UMLRTCommsPort * internal, bool isStat )
 : UMLRTCapsule( NULL, &Ponger, st, border, internal, isStat )
@@ -69,7 +70,7 @@
     }
 }
 
-void Capsule_Ponger::inject( const UMLRTMessage & msg )
+void Capsule_Ponger::inject( const UMLRTInMessage & msg )
 {
     switch( currentState )
     {
@@ -79,7 +80,7 @@
     }
 }
 
-void Capsule_Ponger::initialize( const UMLRTMessage & msg )
+void Capsule_Ponger::initialize( const UMLRTInMessage & msg )
 {
     actionchain_____top__initial__ActionChain3( msg );
     currentState = top__Running;
@@ -87,46 +88,65 @@
 
 
 
-void Capsule_Ponger::transitionaction_____top__initial__ActionChain3__onInit( const UMLRTMessage & msg )
+void Capsule_Ponger::transitionaction_____top__initial__ActionChain3__onInit( const UMLRTInMessage & msg )
 {
     void * rtdata = *(void * *)msg.signal.getPayload();
     std::cout << "Ponger initialised" << std::endl;
 }
 
-void Capsule_Ponger::transitionaction_____top__onBound__ActionChain6__onBound( const UMLRTMessage & msg )
+void Capsule_Ponger::transitionaction_____top__onBound__ActionChain6__onBound( const UMLRTInMessage & msg )
 {
     void * rtdata = *(void * *)msg.signal.getPayload();
     printf( "%s onBound\n", getName() );
 }
 
-void Capsule_Ponger::transitionaction_____top__onPing__ActionChain5__onPing( const UMLRTMessage & msg )
+void Capsule_Ponger::transitionaction_____top__onPing__ActionChain5__onPing( const UMLRTInMessage & msg )
 {
-    const DataType1 & rtdata = *(DataType1 * )msg.signal.getPayload();
-    std::cout << "Ping received"
-    	<< " field1:" << rtdata.field1_int
-    	<< " field2:" << rtdata.field2_bool
-    	<< " field3:" << rtdata.field3_double
-    	<< std::endl;
-    std::cout << "Sending Pong" << std::endl;
-    PongPort().pong().send();
+    std::cout << getName() << ":received ping" << std::endl;
+    RTType_DataType1->fprintf(stdout, RTType_DataType1, msg.signal.getPayload(), 0/*nest*/, 2/*arraySize*/);
+
+    DataType1 rtdata[2];
+    msg.decode(&rtdata, 2);
+    std::cout << getName() <<
+            " rtdata[0].field1_int[1] " << rtdata[0].field1_int[1] <<
+            " rtdata[1].field1_int[1] " << rtdata[1].field1_int[1] <<
+            " rtdata[0].field3_double " << rtdata[0].field3_double <<
+            " rtdata[1].field3_double " << rtdata[1].field3_double <<
+            " rtdata[1].sst1.[2].name " << rtdata[1].field4_sst1[2].name <<
+            " rtdata[1].sst1.[2].integer " << rtdata[1].field4_sst1[2].integer <<
+            std::endl;
+    rtdata[0].field1_int[0]++;
+    rtdata[0].field1_int[1]++;
+    rtdata[1].field1_int[0]++;
+    rtdata[2].field1_int[1]++;
+    rtdata[0].field3_double += 1.;
+    rtdata[1].field3_double += 1.;
+    rtdata[0].field4_sst1[0].integer += 1;
+    rtdata[0].field4_sst1[1].integer += 1;
+    rtdata[0].field4_sst1[2].integer += 1;
+    rtdata[1].field4_sst1[0].integer += 1;
+    rtdata[1].field4_sst1[1].integer += 1;
+    rtdata[1].field4_sst1[2].integer += 1;
+    std::cout << "Sending pong" << std::endl;
+    PongPort().pong(rtdata).send();
 }
 
-void Capsule_Ponger::actionchain_____top__initial__ActionChain3( const UMLRTMessage & msg )
+void Capsule_Ponger::actionchain_____top__initial__ActionChain3( const UMLRTInMessage & msg )
 {
     transitionaction_____top__initial__ActionChain3__onInit( msg );
 }
 
-void Capsule_Ponger::actionchain_____top__onBound__ActionChain6( const UMLRTMessage & msg )
+void Capsule_Ponger::actionchain_____top__onBound__ActionChain6( const UMLRTInMessage & msg )
 {
     transitionaction_____top__onBound__ActionChain6__onBound( msg );
 }
 
-void Capsule_Ponger::actionchain_____top__onPing__ActionChain5( const UMLRTMessage & msg )
+void Capsule_Ponger::actionchain_____top__onPing__ActionChain5( const UMLRTInMessage & msg )
 {
     transitionaction_____top__onPing__ActionChain5__onPing( msg );
 }
 
-Capsule_Ponger::State Capsule_Ponger::state_____top__Running( const UMLRTMessage & msg )
+Capsule_Ponger::State Capsule_Ponger::state_____top__Running( const UMLRTInMessage & msg )
 {
     switch( msg.destPort->role()->id )
     {
@@ -137,6 +157,7 @@
             actionchain_____top__onBound__ActionChain6( msg );
             return top__Running;
         case PingPongProtocol::signal_ping:
+            msg.decodeInit(RTType_DataType1); // Assume this is the place where parameter types are known.
             actionchain_____top__onPing__ActionChain5( msg );
             return top__Running;
         }
diff --git a/rts/test/rts-pingpong/Ponger.hh b/rts/test/rts-pingpong/Ponger.hh
index 3d165d3..3d9f4a4 100644
--- a/rts/test/rts-pingpong/Ponger.hh
+++ b/rts/test/rts-pingpong/Ponger.hh
@@ -5,7 +5,7 @@
 #include "PingPongProtocol.hh"
 #include "umlrtcapsule.hh"
 #include "umlrtcapsuleclass.hh"
-#include "umlrtmessage.hh"
+#include "umlrtinmessage.hh"
 struct UMLRTCommsPort;
 struct UMLRTSlot;
 
@@ -31,8 +31,8 @@
     };
     virtual void bindPort( bool isBorder, int portId, int index );
     virtual void unbindPort( bool isBorder, int portId, int index );
-    virtual void inject( const UMLRTMessage & msg );
-    virtual void initialize( const UMLRTMessage & msg );
+    virtual void inject( const UMLRTInMessage & msg );
+    virtual void initialize( const UMLRTInMessage & msg );
 private:
     enum State
     {
@@ -40,13 +40,13 @@
         SPECIAL_INTERNAL_STATE_UNVISITED
     };
     State currentState;
-    void transitionaction_____top__initial__ActionChain3__onInit( const UMLRTMessage & msg );
-    void transitionaction_____top__onBound__ActionChain6__onBound( const UMLRTMessage & msg );
-    void transitionaction_____top__onPing__ActionChain5__onPing( const UMLRTMessage & msg );
-    void actionchain_____top__initial__ActionChain3( const UMLRTMessage & msg );
-    void actionchain_____top__onBound__ActionChain6( const UMLRTMessage & msg );
-    void actionchain_____top__onPing__ActionChain5( const UMLRTMessage & msg );
-    State state_____top__Running( const UMLRTMessage & msg );
+    void transitionaction_____top__initial__ActionChain3__onInit( const UMLRTInMessage & msg );
+    void transitionaction_____top__onBound__ActionChain6__onBound( const UMLRTInMessage & msg );
+    void transitionaction_____top__onPing__ActionChain5__onPing( const UMLRTInMessage & msg );
+    void actionchain_____top__initial__ActionChain3( const UMLRTInMessage & msg );
+    void actionchain_____top__onBound__ActionChain6( const UMLRTInMessage & msg );
+    void actionchain_____top__onPing__ActionChain5( const UMLRTInMessage & msg );
+    State state_____top__Running( const UMLRTInMessage & msg );
 };
 extern const UMLRTCapsuleClass Ponger;
 
diff --git a/rts/test/rts-pingpong/Top.cc b/rts/test/rts-pingpong/Top.cc
index 4c24490..59161fe 100644
--- a/rts/test/rts-pingpong/Top.cc
+++ b/rts/test/rts-pingpong/Top.cc
@@ -10,7 +10,7 @@
 #include "umlrtcommsportfarend.hh"
 #include "umlrtcommsportrole.hh"
 #include "umlrtframeservice.hh"
-#include "umlrtmessage.hh"
+#include "umlrtinmessage.hh"
 #include "umlrtslot.hh"
 #include <cstddef>
 class UMLRTRtsInterface;
@@ -73,7 +73,7 @@
     }
 }
 
-void Capsule_Top::inject( const UMLRTMessage & msg )
+void Capsule_Top::inject( const UMLRTInMessage & msg )
 {
     switch( currentState )
     {
@@ -83,7 +83,7 @@
     }
 }
 
-void Capsule_Top::initialize( const UMLRTMessage & msg )
+void Capsule_Top::initialize( const UMLRTInMessage & msg )
 {
     actionchain_____top__Transition2__ActionChain3( msg );
     currentState = top__State1;
@@ -91,7 +91,7 @@
 
 
 
-void Capsule_Top::transitionaction_____top__Transition2__ActionChain3__onInit( const UMLRTMessage & msg )
+void Capsule_Top::transitionaction_____top__Transition2__ActionChain3__onInit( const UMLRTInMessage & msg )
 {
     void * rtdata = *(void * *)msg.signal.getPayload();
     std::cout << "Top initialised!\n";
@@ -99,16 +99,16 @@
     UMLRTCapsuleId pongerId = FramePort().incarnate( ponger(), Ponger );
     if( ! pongerId.isValid() )
         context()->perror("ponger incarnate failed.");
-    printf( "incarnated ponger valid:%d @%p\n",
-               pongerId.isValid(), pongerId.getCapsule() );
+    printf( "incarnated ponger valid:%d @%p %s\n",
+               pongerId.isValid(), pongerId.getCapsule(), pongerId.getCapsule()->getName());
 }
 
-void Capsule_Top::actionchain_____top__Transition2__ActionChain3( const UMLRTMessage & msg )
+void Capsule_Top::actionchain_____top__Transition2__ActionChain3( const UMLRTInMessage & msg )
 {
     transitionaction_____top__Transition2__ActionChain3__onInit( msg );
 }
 
-Capsule_Top::State Capsule_Top::state_____top__State1( const UMLRTMessage & msg )
+Capsule_Top::State Capsule_Top::state_____top__State1( const UMLRTInMessage & msg )
 {
     switch( msg.destPort->role()->id )
     {
diff --git a/rts/test/rts-pingpong/Top.hh b/rts/test/rts-pingpong/Top.hh
index 407f314..dc7cf75 100644
--- a/rts/test/rts-pingpong/Top.hh
+++ b/rts/test/rts-pingpong/Top.hh
@@ -5,7 +5,7 @@
 #include "umlrtcapsule.hh"
 #include "umlrtcapsuleclass.hh"
 #include "umlrtframeprotocol.hh"
-#include "umlrtmessage.hh"
+#include "umlrtinmessage.hh"
 struct UMLRTCapsulePart;
 struct UMLRTCommsPort;
 struct UMLRTSlot;
@@ -36,8 +36,8 @@
     };
     virtual void bindPort( bool isBorder, int portId, int index );
     virtual void unbindPort( bool isBorder, int portId, int index );
-    virtual void inject( const UMLRTMessage & msg );
-    virtual void initialize( const UMLRTMessage & msg );
+    virtual void inject( const UMLRTInMessage & msg );
+    virtual void initialize( const UMLRTInMessage & msg );
 private:
     enum State
     {
@@ -45,9 +45,9 @@
         SPECIAL_INTERNAL_STATE_UNVISITED
     };
     State currentState;
-    void transitionaction_____top__Transition2__ActionChain3__onInit( const UMLRTMessage & msg );
-    void actionchain_____top__Transition2__ActionChain3( const UMLRTMessage & msg );
-    State state_____top__State1( const UMLRTMessage & msg );
+    void transitionaction_____top__Transition2__ActionChain3__onInit( const UMLRTInMessage & msg );
+    void actionchain_____top__Transition2__ActionChain3( const UMLRTInMessage & msg );
+    State state_____top__State1( const UMLRTInMessage & msg );
 };
 extern const UMLRTCapsuleClass Top;
 
diff --git a/rts/umlrt/umlrtcontroller.cc b/rts/umlrt/umlrtcontroller.cc
index 55716d8..abc2a9e 100644
--- a/rts/umlrt/umlrtcontroller.cc
+++ b/rts/umlrt/umlrtcontroller.cc
@@ -24,7 +24,7 @@
 #include "umlrtcommsportrole.hh"
 #include "umlrtcontrollercommand.hh"
 #include "umlrtframeservice.hh"
-#include "umlrtmessage.hh"
+#include "umlrtinmessage.hh"
 #include "umlrtobjectclass.hh"
 #include "umlrtprotocol.hh"
 #include "umlrttimer.hh"
@@ -431,7 +431,7 @@
         capsuleQueue.moveAll(incomingQueue);
 
         // Inject all available messages, highest priority msgs first.
-        UMLRTMessage * msg;
+        UMLRTInMessage * msg;
         while (!abort && (msg = capsuleQueue.dequeueHighestPriority()) != NULL)
         {
             if (msg->isCommand)
@@ -460,7 +460,7 @@
                     base::debugLogData( BD_SIGNALDATA, msg->signal.getPayload(), msg->signal.getPayloadSize());
 
                     // Inject the signal into the capsule.
-                    msg->destPort->slot->capsule->inject((UMLRTMessage)*msg);
+                    msg->destPort->slot->capsule->inject((UMLRTInMessage)*msg);
                 }
             }
             // Put the message back in the pool (handles signal allocation also).
@@ -497,7 +497,7 @@
             FATAL("could not allocate memory for serialized data.");
         }
         // Encode the data.
-        type->encode(type, userData, (*serializedDataP));
+        type->encode(type, userData, (*serializedDataP), 0);
     }
     // The controller frees the serialized data buffer after it's been copied to the initialize message.
 }
@@ -701,7 +701,7 @@
         {
             const char * farEndSlotName = "(none)";
             const char * farEndPortName = "(none)";
-            const char * farEndSlotNoInstance = "(no instance)";
+            const char * farEndSlotClass = "(no instance)";
             size_t farEndIndex = 0;
             if (port->farEnds[j].port != NULL)
             {
@@ -710,11 +710,11 @@
                 farEndIndex = port->farEnds[j].farEndIndex;
                 if (port->farEnds[j].port->slot->capsule != NULL)
                 {
-                    farEndSlotNoInstance = "";
+                    farEndSlotClass = port->farEnds[j].port->slot->capsule->getClass()->name;
                 }
             }
             BDEBUG(BD_MODEL, "                    farEnd[%u] : -> { slot %s, port %s[%u] %s}\n",
-                    j, farEndSlotName, farEndPortName, farEndIndex, farEndSlotNoInstance );
+                    j, farEndSlotName, farEndPortName, farEndIndex, farEndSlotClass );
         }
         debugOutputModelPortDeferQueue(port);
     }
diff --git a/rts/umlrt/umlrtframeservice.cc b/rts/umlrt/umlrtframeservice.cc
index d43ef90..bc2009e 100644
--- a/rts/umlrt/umlrtframeservice.cc
+++ b/rts/umlrt/umlrtframeservice.cc
@@ -54,13 +54,18 @@
     size_t * slotBoundCount = new size_t[slotClass->numPortRolesBorder]; // Will hold the number of bound instances on each slot port.
 
     // Each of the bound slot ports have to be bound to a capsule border port.
-    for (size_t i = 0; i < slotClass->numPortRolesBorder; ++i)
+    size_t slotPortBoundCount = 0; // Number of ports on the slot that have a bind - need at least this many capsule border ports.
+    for (size_t slot_i = 0; slot_i < slotClass->numPortRolesBorder; ++slot_i)
     {
         // Set all slotToBorderMap entries to 'capsule border port not mapped to this slot'.
-        slotToBorderMap[i] = -1;
+        slotToBorderMap[slot_i] = -1;
 
-        // The number of bound instances on each slot port are remembered as each is visited.
-        slotBoundCount[i] = 0;
+        // Remember how many port instances were bound on the slot port.
+        if ((slotBoundCount[slot_i] = bindPortsCountBound( &slot->ports[slot_i])) > 0)
+        {
+            // Must have at least one capsule border port to accommodate every bound slot port. Checked below.
+            ++slotPortBoundCount;
+        }
     }
     // Initialize 'newBorderPorts' - the new border ports for the capsule if binding succeeds.
     for (size_t i = 0; i < requestedClass->numPortRolesBorder; ++i)
@@ -86,20 +91,24 @@
 
     size_t border_i = 0; // Port index on requesting class. We're searching the capsule's border ports for unbound ports to match bound slot ports.
 
+    // Go through each port on the slot. Quit if we fail to find a match for any bound slot port. Do the actual binding after we've proven the capsule fits.
     bool compatible = true; // Assume compatibility until we fail.
 
-    // Go through each port on the slot. Quit if we fail to find a match for any bound slot port. Do the actual binding after we've proven the capsule fits.
-    bool done = false;
-
-    for (size_t slot_i = 0; (slot_i < slotClass->numPortRolesBorder) && compatible && !done; ++slot_i)
+    // Before we start checking to see whether the capsule's border ports fit into the slot, we perform the trivial check
+    // of ensuring the capsule has at least as many border ports available as their are slot ports with bindings.
+    // The for-loop before is not entered if the requested class has no border ports, and we have to check this case.
+    // The trivial case of incarnating or importing into a slot with no ports will not enter the for-loop and allow compatibility.
+    if (requestedClass->numPortRolesBorder < slotPortBoundCount)
+    {
+        // Capsule doesn't have enough border ports to satisfy the slot.
+        compatible = false;
+    }
+    for (size_t slot_i = 0; (slot_i < slotClass->numPortRolesBorder) && compatible && (border_i < requestedClass->numPortRolesBorder); ++slot_i)
     {
         bool match = false;
 
-        // Remember how many port instances were bound on the slot port.
-        slotBoundCount[slot_i] = bindPortsCountBound( &slot->ports[slot_i]);
-
         // Loop through the remaining requesting capsule border ports looking for a match to slot port slot_i.
-        while (!done && !match)
+        while (compatible && !match)
         {
             // If port-name match.
             if (!strcmp(slotClass->portRolesBorder[slot_i].name, requestedClass->portRolesBorder[border_i].name))
@@ -110,21 +119,21 @@
                 if (strcmp(slotClass->portRolesBorder[slot_i].protocol, requestedClass->portRolesBorder[border_i].protocol))
                 {
                     // protocol mismatch.
-                    done = !0;
+                    compatible = false;
                     BDEBUG(BD_BINDFAIL, "BIND FAIL:%d %d:slot %s (class %s) port %s (protocol %s) has MISMATCHED PROTOCOL with capsule (class %s) (protocol %s).\n",
                             slot_i, border_i, slot->name, slot->capsuleClass, slotClass->portRolesBorder[slot_i].name, slotClass->portRolesBorder[slot_i].protocol, requestedClass->name, requestedClass->portRolesBorder[border_i].protocol);
                 }
                 else if (slotClass->portRolesBorder[slot_i].conjugated != requestedClass->portRolesBorder[border_i].conjugated)
                 {
                     // conjugation mismatch.
-                    done = !0;
+                    compatible = false;
                     BDEBUG(BD_BINDFAIL, "BIND FAIL:%d %d:slot %s port %s (protocol %s) has MISMATCHED CONJUGATION with capsule (class %s)\n",
                             slot_i, border_i, slot->name, slotClass->portRolesBorder[slot_i].name, slotClass->portRolesBorder[slot_i].protocol, requestedClass->name);
                 }
                 else if ((requestedClass->portRolesBorder[border_i].numFarEnd - borderBoundCount) < slotBoundCount[slot_i])
                 {
                     // capsule border port unbound instances insufficient for binding
-                    done = !0;
+                    compatible = false;
                     BDEBUG(BD_BINDFAIL, "BIND FAIL:%d %d:slot %s port %s (protocol %s) BOUND PORTS [%lu] EXCEEDS CAPSULE'S UNBOUND (class %s) port repl unbound instances [%lu].\n",
                             slot_i, border_i, slot->name, slotClass->portRolesBorder[slot_i].name, slotClass->portRolesBorder[slot_i].protocol, slotBoundCount[slot_i], requestedClass->name,
                             requestedClass->portRolesBorder[border_i].numFarEnd - borderBoundCount);
@@ -158,7 +167,7 @@
             // Advance to next capsule border port - and quit if we've exhausted them.
             if (++border_i >= requestedClass->numPortRolesBorder)
             {
-                done = !0;
+                compatible = false;
             }
         }
         if (!match)
@@ -1491,7 +1500,7 @@
 
     BDEBUG(BD_INSTANTIATE, "initialize capsule %s\n", capsule->getName());
 
-    UMLRTMessage initializeMsg;
+    UMLRTInMessage initializeMsg;
 
     initializeMsg.signal.initialize(sizeSerializedData);
 
diff --git a/rts/umlrt/umlrtinmessage.cc b/rts/umlrt/umlrtinmessage.cc
new file mode 100644
index 0000000..83fbce0
--- /dev/null
+++ b/rts/umlrt/umlrtinmessage.cc
@@ -0,0 +1,35 @@
+// umlrtinmessage.cc
+
+/*******************************************************************************
+* Copyright (c) 2015 Zeligsoft (2009) Limited  and others.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*******************************************************************************/
+
+#include "umlrtapi.hh"
+#include "umlrtcontroller.hh"
+#include "umlrtinmessage.hh"
+#include "umlrtinsignal.hh"
+#include "umlrtqueue.hh"
+#include "basefatal.hh"
+
+// See umlrtinmessage.hh for documentation.
+
+void UMLRTInMessage::decodeInit ( const UMLRTObject_class * desc_ ) const
+{
+    desc = desc_;
+    decodeInfo = NULL;
+}
+
+void UMLRTInMessage::decode ( void * data, int arraySize ) const
+{
+    ((UMLRTInSignal &)signal).decode(&decodeInfo, desc, data, arraySize);
+}
+
+void UMLRTInMessage::decode ( int ptrIndirection, void * data, int arraySize ) const
+{
+    FATAL("UMLRTInMessage::decode ptrIndirection not supported.");
+}
+
diff --git a/rts/umlrt/umlrtinsignal.cc b/rts/umlrt/umlrtinsignal.cc
index 5142eb3..7376ca3 100644
--- a/rts/umlrt/umlrtinsignal.cc
+++ b/rts/umlrt/umlrtinsignal.cc
@@ -16,7 +16,7 @@
 
 }
 
-UMLRTInSignal::UMLRTInSignal(const UMLRTInSignal &signal)
+UMLRTInSignal::UMLRTInSignal(const UMLRTInSignal &signal) : UMLRTSignal(signal)
 {
 
 }
@@ -33,7 +33,7 @@
 }
 
 // See documentation in UMLRTSignal.
-void UMLRTInSignal::decode( void * * decodeInfo, void * data, const UMLRTObject_class * desc, int arraySize ) const
+void UMLRTInSignal::decode( const void * * decodeInfo, const UMLRTObject_class * desc, void * data, int arraySize ) const
 {
     if (!element)
     {
@@ -43,7 +43,7 @@
 }
 
 // See documentation in UMLRTSignal.
-void UMLRTInSignal::decode( void * * decodeInfo, int ptrIndirection, void * data, const UMLRTObject_class * desc, int arraySize ) const
+void UMLRTInSignal::decode( const void * * decodeInfo, const UMLRTObject_class * desc, int ptrIndirection, void * data, int arraySize ) const
 {
     FATAL("encode ptr indirection not supported");
 }
diff --git a/rts/umlrt/umlrtlogprotocol.cc b/rts/umlrt/umlrtlogprotocol.cc
index dc9c738..2077372 100644
--- a/rts/umlrt/umlrtlogprotocol.cc
+++ b/rts/umlrt/umlrtlogprotocol.cc
@@ -218,11 +218,11 @@
     return nchar;
 }
 
-int UMLRTLogProtocol_baserole::log ( const void * userData, const UMLRTObject_class * type ) const
+int UMLRTLogProtocol_baserole::log ( const void * userData, const UMLRTObject_class * type, int arraySize ) const
 {
     int nchar;
 
-    nchar = show(userData, type);
+    nchar = show(userData, type, arraySize);
     nchar += log("");
 
     return nchar;
@@ -406,14 +406,14 @@
     return nchar;
 }
 
-int UMLRTLogProtocol_baserole::show ( const void * userData, const UMLRTObject_class * type ) const
+int UMLRTLogProtocol_baserole::show ( const void * userData, const UMLRTObject_class * type, int arraySize ) const
 {
     int nchar = 0;
 
     if (ostream != NULL)
     {
         UMLRTMutex * mutex = takeMutex();
-        nchar = UMLRTObject_fprintf(ostream, type, userData);
+        nchar = UMLRTObject_fprintf(ostream, type, userData, 0/*nest*/, arraySize);
         giveMutex(mutex);
     }
     return nchar;
diff --git a/rts/umlrt/umlrtobjectclass.cc b/rts/umlrt/umlrtobjectclass.cc
index 9ed4357..d9e4aa9 100644
--- a/rts/umlrt/umlrtobjectclass.cc
+++ b/rts/umlrt/umlrtobjectclass.cc
@@ -16,12 +16,16 @@
 // Type descriptor used for encoding/decoding data of a given type.
 // A number of UMLRTType_xxx descriptors are pre-defined by the library.
 
-// Default initializer - zeros the data and returns a pointer to next byte.
+// Default initializer - zeros the data and returns a pointer to the byte after the initialized data.
 
 void * UMLRTObject_initialize( const UMLRTObject_class * desc, void * data )
 {
     uint8_t * s = (uint8_t *)data;
 
+    if (desc->super != NULL)
+    {
+        s = (uint8_t *)desc->super->initialize(desc->super, data); // Moves 's' past base type data.
+    }
     if (desc->fields == NULL)
     {
         memset(s, 0, desc->size);
@@ -29,246 +33,373 @@
     }
     else
     {
-        for (size_t i = 0; i < desc->size; ++i)
+        for (int i = 0; i < desc->size; ++i)
         {
-            desc->fields[i].desc->initialize(desc->fields[i].desc, s + desc->fields[i].offset);
+            const UMLRTObject_class * fldDesc = desc->fields[i].desc;
+            for (int j = 0; j < desc->fields[i].arraySize; ++j)
+            {
+                s = (uint8_t *)fldDesc->initialize(fldDesc, s );
+            }
         }
     }
     return (void *)s;
 }
 
-// Default copy - copies the data and returns a pointer to the byte following the src data.
-// The return value is the byte following the last byte copied to the destination.
+// Default copy - currently is a memory copy of encoded data.
 void * UMLRTObject_copy( const UMLRTObject_class * desc, const void * src, void * dst )
 {
-    uint8_t * s = (uint8_t *)src;
-    uint8_t * end_p = (uint8_t *)dst;
-    uint8_t * d = (uint8_t *)dst;
-
-    if (desc->fields == NULL)
-    {
-        memcpy(d, s, desc->size);
-        end_p += desc->size;
-    }
-    else
-    {
-        for (size_t i = 0; i < desc->size; ++i)
-        {
-            // overwrite end_p here - the return value for the last field is the one that is relevant.
-            end_p = (uint8_t *)desc->fields[i].desc->copy(desc->fields[i].desc, s + desc->fields[i].offset, d + desc->fields[i].offset);
-        }
-    }
-    return (void *)end_p;
+    memcpy(dst, src, desc->getSize(desc));
+    return (void *)((uint8_t *)dst + desc->getSize(desc));
 }
 
-// Default decode is a copy (returns a pointer to the byte after the src data).
-// For now, we'll use the return value of the copy (a value relative to dst) to compute what the return value should be.
 size_t UMLRTObject_getSize( const UMLRTObject_class * desc )
 {
-    size_t size = desc->size;
+    int size = desc->size;
 
     if (desc->fields != NULL)
     {
-        size = desc->fields[desc->size - 1].offset +
-                desc->fields[desc->size - 1].desc->getSize(desc->fields[desc->size - 1].desc);
+        size = 0;
+        for (int i = 0; i < desc->size; ++i)
+        {
+            size += desc->fields[i].desc->getSize(desc->fields[i].desc) * desc->fields[i].arraySize;
+        }
     }
     return size;
 }
 
-void * UMLRTObject_decode( const UMLRTObject_class * desc, const void * src, void * dst )
+const void * UMLRTObject_decode( const UMLRTObject_class * desc, const void * src, void * dst, int nest )
 {
-    desc->copy(desc, src, dst); // ignore return value.
-
-    return (void *)((uint8_t *)src + UMLRTObject_getSize(desc));
+    if (desc->fields == NULL)
+    {
+        memcpy(dst, src, desc->size);
+        src = (void *)((uint8_t *)src + desc->size);
+    }
+    else
+    {
+        for (int i = 0; i < desc->size; ++i)
+        {
+            const UMLRTObject_class * fldDesc = desc->fields[i].desc;
+            uint8_t * d = (uint8_t *)dst + desc->fields[i].offset;
+            for (int j = 0; j < desc->fields[i].arraySize; ++j)
+            {
+                src = fldDesc->decode(fldDesc, src, d, nest+1);
+                d += desc->fields[i].sizeDecoded;
+            }
+        }
+    }
+    return src;
 }
 
+uint8_t * globalDst = 0; // For debugging - initialized in umlrtsignalelement.cc
+uint8_t * globalSrc = 0;
+
 // Default encode is a copy (returns a pointer to the byte after the dst data).
-void * UMLRTObject_encode(  const UMLRTObject_class * desc, const void * src, void * dst )
+void * UMLRTObject_encode(  const UMLRTObject_class * desc, const void * src, void * dst, int nest )
 {
-    return desc->copy(desc, src, dst);
+    if (desc->fields == NULL)
+    {
+        for (int n = 0; n < nest; ++n)
+        {
+            BDEBUG(BD_SERIALIZE, "    ");
+        }
+        BDEBUG(BD_SERIALIZE, "encode: desc(%s) size(%d) gs %ld gd %ld\n", desc->name, desc->size, (uint8_t *)src - globalSrc, (uint8_t *)dst - globalDst);
+        memcpy(dst, src, desc->size);
+        dst = (void *)((uint8_t *)dst + desc->size);
+    }
+    else
+    {
+        for (int n = 0; n < nest; ++n)
+        {
+            BDEBUG(BD_SERIALIZE, "    ");
+        }
+        BDEBUG(BD_SERIALIZE, "encode: desc(%s) nfields(%d)\n", desc->name, desc->size);
+        for (int i = 0; i < desc->size; ++i)
+        {
+            const UMLRTObject_field * fld = &desc->fields[i];
+            uint8_t * s = (uint8_t *)src + fld->offset;
+            for (int j = 0; j < fld->arraySize; ++j)
+            {
+                BDEBUG(BD_SERIALIZE, "  ");
+                for (int n = 0; n < nest; ++n)
+                {
+                    BDEBUG(BD_SERIALIZE, "    ");
+                }
+                BDEBUG(BD_SERIALIZE, "encode: fld[%d]<%s> offset(%d) sizeDecoded(%d) (elem[%d] elemoff %ld gs %ld gd %ld\n",
+                        i, fld->name, fld->offset, fld->sizeDecoded, j, s - (uint8_t *)src, s - globalSrc, (uint8_t *)dst - globalDst);
+                dst = fld->desc->encode(fld->desc, s, dst, nest+1);
+                s += fld->sizeDecoded;
+            }
+        }
+    }
+    return dst;
 }
 
 // Default destroy does nothing (but returns a pointer to the byte after the data).
 void * UMLRTObject_destroy(  const UMLRTObject_class * desc, void * data )
 {
-    uint8_t * s = (uint8_t *)data;
-    uint8_t * end_p = (uint8_t *)data;
-
-    if (desc->fields != NULL)
-    {
-        for (size_t i = 0; i < desc->size; ++i)
-        {
-            end_p = (uint8_t *)desc->fields[i].desc->destroy(desc->fields[i].desc, s + desc->fields[i].offset);
-        }
-    }
-    else
-    {
-        end_p += desc->size;
-    }
-    return (void *)end_p;
+    return (void *)((uint8_t *)data + desc->getSize(desc));
 }
 
-int UMLRTObject_fprintf( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+int UMLRTObject_fprintf( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
     uint8_t * s = (uint8_t *)data;
 
-    if (desc->fields != NULL)
+    // Debug
+    if (nest == 0)
     {
-        nchar += fprintf(ostream, "{%s:", desc->name);
-
-        for (size_t i = 0; i < desc->size; ++i)
+        globalSrc = s;
+    }
+    for (int ai = 0; ai < arraySize; ++ai)
+    {
+        if (desc->fields != NULL)
         {
-            nchar += fprintf(ostream, "{%s:", desc->fields[i].name);
-            nchar += UMLRTObject_fprintf(ostream, desc->fields[i].desc, s + desc->fields[i].offset);
-            nchar += fprintf(ostream, "}");
+            BDEBUG(BD_SERIALIZE, "\n");
+        }
+        for (int n = 0; n < nest; ++n)
+        {
+            BDEBUG(BD_SERIALIZE, "    ");
+        }
+        nchar += fprintf(ostream, "{%s", desc->name);
+        if (arraySize > 1)
+        {
+            nchar += fprintf(ostream, "[%d]", ai);
+        }
+        nchar += fprintf(ostream, ":");
+        BDEBUG(BD_SERIALIZE, "\n");
+        if (desc->fields != NULL)
+        {
+            for (int fi = 0; fi < desc->size; ++fi)
+            {
+                const UMLRTObject_field * fld = &desc->fields[fi];
+                BDEBUG(BD_SERIALIZE, "  ");
+                for (int n = 0; n < nest; ++n)
+                {
+                    BDEBUG(BD_SERIALIZE, "    ");
+                }
+                nchar += fprintf(ostream, "{%s:", fld->name);
+                BDEBUG(BD_SERIALIZE, "<desc(%s) arraySize %d elem %d field %d gs %ld>",
+                        desc->name, arraySize, ai, fi, s - globalSrc);
+                for (int n = 0; n < nest; ++n)
+                {
+                    BDEBUG(BD_SERIALIZE, "    ");
+                }
+                nchar += fld->desc->fprintf(ostream, fld->desc, s, nest+1, fld->arraySize);
+                BDEBUG(BD_SERIALIZE, "  ");
+                for (int n = 0; n < nest; ++n)
+                {
+                    BDEBUG(BD_SERIALIZE, "    ");
+                }
+                nchar += fprintf(ostream, "}");
+                BDEBUG(BD_SERIALIZE, "\n");
+                s += fld->desc->getSize(fld->desc) * fld->arraySize;
+            }
+        }
+        else if ((desc->fprintf != NULL) && (desc->fprintf != UMLRTObject_fprintf))
+        {
+            // Don't allow a recursive call with the same parameters.
+            nchar += desc->fprintf(ostream, desc, data, nest+1, arraySize);
+        }
+        else
+        {
+            nchar += fprintf(ostream, "(unable to print)"); // Either no fprintf defined or malformed descriptor.
+            BDEBUG(BD_SERIALIZE, "\n");
+        }
+        for (int n = 0; n < nest; ++n)
+        {
+            BDEBUG(BD_SERIALIZE, "    ");
         }
         nchar += fprintf(ostream, "}");
-    }
-    else if (desc->fprintf != 0)
-    {
-        nchar += desc->fprintf(ostream, desc, data);
-    }
-    else
-    {
-        nchar += fprintf(ostream, "{%s: (unable to print)}", desc->name);
+        BDEBUG(BD_SERIALIZE, "\n");
     }
     return nchar;
 }
 
-int UMLRTObject_fprintf_bool( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_bool( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
     bool b;
-    desc->copy(desc, data, &b);
-    nchar += fprintf(ostream, "{bool %s}", b ? "true" : "false");
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(b)), &b);
+        nchar += fprintf(ostream, "{bool %s}", b ? "true" : "false");
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_char( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_char( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
-    char c;
-    desc->copy(desc, data, &c);
-    nchar += fprintf(ostream, "{char %c}", c);
+    nchar += fprintf(ostream, "{char ");
+    for (int i = 0; i < arraySize; ++i)
+    {
+        nchar += fprintf(ostream, "0x%02X ", *((char*)data + i));
+    }
+    nchar += fprintf(ostream, " '");
+    for (int i = 0; i < arraySize; ++i)
+    {
+        char c = *((char*)data + i);
+        nchar += fprintf(ostream, "%c", (c > 0x1F) && (c < 0x7F) ? c : '.');
+    }
+    nchar += fprintf(ostream, "'}");
     return nchar;
 }
 
-int UMLRTObject_fprintf_double( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_double( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
     double d;
-    desc->copy(desc, data, &d);
-    nchar += fprintf(ostream, "{double %f}", d);
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(d)), &d);
+        nchar += fprintf(ostream, "{double %f}", d);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_float( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_float( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
     float f;
-    desc->copy(desc, data, &f);
-    nchar += fprintf(ostream, "{float %f}", f);
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(f)), &f);
+        nchar += fprintf(ostream, "{float %f}", f);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_int( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_int( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
-    int i;
-    desc->copy(desc, data, &i);
-    nchar += fprintf(ostream, "{int %d}", i);
+    int iv;
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(iv)), &iv);
+        nchar += fprintf(ostream, "{int %d}", iv);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_long( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_long( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
     long l;
-    desc->copy(desc, data, &l);
-    nchar += fprintf(ostream, "{long %ld}", l);
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(l)), &l);
+        nchar += fprintf(ostream, "{long %ld}", l);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_longdouble( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_longdouble( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
-    long double l;
-    desc->copy(desc, data, &l);
-    nchar += fprintf(ostream, "{longdouble %Lf}", l);
+    long double ld;
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(ld)), &ld);
+        nchar += fprintf(ostream, "{longdouble %Lf}", ld);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_longlong( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_longlong( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
     long long ll;
-    desc->copy(desc, data, &ll);
-    nchar += fprintf(ostream, "{longlong %lld}", ll);
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(ll)), &ll);
+        nchar += fprintf(ostream, "{longlong %lld}", ll);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_ptr( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_ptr( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
     void * p;
-    desc->copy(desc, data, &p);
-    // Pointer de-referencing tracked by Bug 97.
-    nchar += fprintf(ostream, "{ptr %p}", p);
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(p)), &p);
+        // Pointer de-referencing tracked by Bug 97.
+        nchar += fprintf(ostream, "{ptr %p}", p);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_short( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_short( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
     short sh;
-    desc->copy(desc, data, &sh);
-    nchar += fprintf(ostream, "{short %d}", sh);
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(sh)), &sh);
+        nchar += fprintf(ostream, "{short %d}", sh);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_uchar( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_uchar( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
-    unsigned char c;
-    desc->copy(desc, data, &c);
-    nchar += fprintf(ostream, "{char %u}", c);
+    unsigned char uc;
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i), &uc);
+        nchar += fprintf(ostream, "{uchar %u}", uc);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_uint( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_uint( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
-    unsigned int i;
-    desc->copy(desc, data, &i);
-    nchar += fprintf(ostream, "{uint %u}", i);
+    unsigned int ui;
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(ui)), &ui);
+        nchar += fprintf(ostream, "{uint %u}", ui);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_ulong( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_ulong( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
-    unsigned long l;
-    desc->copy(desc, data, &l);
-    nchar += fprintf(ostream, "{ulong %lu}", l);
+    unsigned long ul;
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(ul)), &ul);
+        nchar += fprintf(ostream, "{ulong %lu}", ul);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_ulonglong( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_ulonglong( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
     unsigned long long ll;
-    desc->copy(desc, data, &ll);
-    nchar += fprintf(ostream, "{ulonglong %llu}", ll);
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(ll)), &ll);
+        desc->copy(desc, data, &ll);
+        nchar += fprintf(ostream, "{ulonglong %llu}", ll);
+    }
     return nchar;
 }
 
-int UMLRTObject_fprintf_ushort( FILE *ostream, const UMLRTObject_class * desc, const void * data )
+static int UMLRTObject_fprintf_ushort( FILE *ostream, const UMLRTObject_class * desc, const void * data, int nest, int arraySize )
 {
     int nchar = 0;
-    unsigned short sh;
-    desc->copy(desc, data, &sh);
-    nchar += fprintf(ostream, "{ushort %u}", sh);
+    unsigned short ush;
+    for (int i = 0; i < arraySize; ++i)
+    {
+        desc->copy(desc, ((uint8_t*)data + i*sizeof(ush)), &ush);
+        nchar += fprintf(ostream, "{ushort %u}", ush);
+    }
     return nchar;
 }
 
@@ -286,6 +417,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(bool),
+        sizeof(bool),
         NULL // fields
 };
 
@@ -304,6 +436,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(char),
+        sizeof(char),
         NULL, // fields
 };
 
@@ -321,6 +454,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(double),
+        sizeof(double),
         NULL, // fields
 };
 
@@ -338,6 +472,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(float),
+        sizeof(float),
         NULL, // fields
 };
 
@@ -355,6 +490,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(int),
+        sizeof(int),
         NULL, // fields
 };
 
@@ -372,6 +508,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(long),
+        sizeof(long),
         NULL, // fields
 };
 
@@ -389,6 +526,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(long double),
+        sizeof(long double),
         NULL, // fields
 };
 
@@ -406,6 +544,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(long long),
+        sizeof(long long),
         NULL, // fields
 };
 
@@ -423,6 +562,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(void *),
+        sizeof(void *),
         NULL // fields
 };
 
@@ -440,6 +580,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(short),
+        sizeof(short),
         NULL, // fields
 };
 
@@ -457,6 +598,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(unsigned char),
+        sizeof(unsigned char),
         NULL, // fields
 };
 
@@ -474,6 +616,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(unsigned int),
+        sizeof(unsigned int),
         NULL, // fields
 };
 
@@ -491,6 +634,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(unsigned long),
+        sizeof(unsigned long),
         NULL, // fields
 };
 
@@ -508,6 +652,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(unsigned long long),
+        sizeof(unsigned long long),
         NULL, // fields
 };
 
@@ -525,6 +670,7 @@
         UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
         UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
         sizeof(unsigned short),
+        sizeof(unsigned short),
         NULL, // fields
 };
 
diff --git a/rts/umlrt/umlrtoutsignal.cc b/rts/umlrt/umlrtoutsignal.cc
index 9a25c22..86f3afa 100644
--- a/rts/umlrt/umlrtoutsignal.cc
+++ b/rts/umlrt/umlrtoutsignal.cc
@@ -1,5 +1,13 @@
 // umlrtoutsignal.cc
 
+/*******************************************************************************
+* Copyright (c) 2015 Zeligsoft (2009) Limited  and others.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*******************************************************************************/
+
 #include "umlrtcommsport.hh"
 #include "umlrtcommsportfarend.hh"
 #include "umlrtcontroller.hh"
@@ -10,20 +18,12 @@
 #include "basedebugtype.hh"
 #include "basedebug.hh"
 
-/*******************************************************************************
-* Copyright (c) 2015 Zeligsoft (2009) Limited  and others.
-* All rights reserved. This program and the accompanying materials
-* are made available under the terms of the Eclipse Public License v1.0
-* which accompanies this distribution, and is available at
-* http://www.eclipse.org/legal/epl-v10.html
-*******************************************************************************/
-
 UMLRTOutSignal::UMLRTOutSignal()
 {
 
 }
 
-UMLRTOutSignal::UMLRTOutSignal(const UMLRTOutSignal &signal)
+UMLRTOutSignal::UMLRTOutSignal(const UMLRTOutSignal &signal) : UMLRTSignal(signal)
 {
 
 }
@@ -39,9 +39,7 @@
 
 }
 
-
-// See documentation in UMLRTSignal.
-void UMLRTOutSignal::encode( const void * data, const UMLRTObject_class * desc, int arraySize )
+void UMLRTOutSignal::encode( const UMLRTObject_class * desc, const void * data, int arraySize )
 {
     if (!element)
     {
@@ -50,8 +48,7 @@
     element->encode(desc, data, arraySize);
 }
 
-// See documentation in UMLRTSignal.
-void UMLRTOutSignal::encode( int ptrIndirection, void * data, const UMLRTObject_class * desc, int arraySize )
+void UMLRTOutSignal::encode( const UMLRTObject_class * desc, int ptrIndirection, void * data, int arraySize )
 {
     FATAL("encode ptr indirection not supported");
 }
diff --git a/rts/umlrt/umlrtprioritymessagequeue.cc b/rts/umlrt/umlrtprioritymessagequeue.cc
index f49ee11..f543281 100644
--- a/rts/umlrt/umlrtprioritymessagequeue.cc
+++ b/rts/umlrt/umlrtprioritymessagequeue.cc
@@ -116,14 +116,14 @@
 
 // Get the highest priority message from the collection of queues.
 
-UMLRTMessage * UMLRTPriorityMessageQueue::dequeueHighestPriority()
+UMLRTInMessage * UMLRTPriorityMessageQueue::dequeueHighestPriority()
 {
-    UMLRTMessage * msg = 0;
+    UMLRTInMessage * msg = 0;
 
     for (UMLRTSignalElement::Priority priority = (UMLRTSignalElement::PRIORITY_MAX-1);
             (priority >= UMLRTSignalElement::PRIORITY_BACKGROUND) && (priority < (UMLRTSignalElement::PRIORITY_MAX)) && !msg; --priority)
     {
-        msg = (UMLRTMessage *)queue[priority].dequeue();
+        msg = (UMLRTInMessage *)queue[priority].dequeue();
 
     }
     if (msg != NULL)
diff --git a/rts/umlrt/umlrtsignalelement.cc b/rts/umlrt/umlrtsignalelement.cc
index 3b4f879..96220bc 100644
--- a/rts/umlrt/umlrtsignalelement.cc
+++ b/rts/umlrt/umlrtsignalelement.cc
@@ -167,14 +167,21 @@
     }
 }
 
+extern uint8_t * globalSrc;
+extern uint8_t * globalDst;
+
 // See documentation in UMLRTSignal.
 void UMLRTSignalElement::encode( const UMLRTObject_class * desc, const void * data, int arraySize )
 {
     // encodeInfo is intitialized to be 'payload' when the signal is initialized.
     // It is moved forward during successive #encode calls.
+    globalSrc = (uint8_t *)data;
+    globalDst = (uint8_t *)encodeInfo;
+
     for (int i = 0; i < arraySize; ++i)
     {
-        encodeInfo = desc->encode(desc, data, encodeInfo);
+        encodeInfo = desc->encode(desc, data, encodeInfo, 0);
+        data = ((uint8_t*)data + desc->sizeDecoded);
     }
 }
 
@@ -184,25 +191,25 @@
     FATAL("encode ptr indirection not implemented.");
 }
 
-// See documentation in UMLRTSignal.
-void UMLRTSignalElement::decode( void * * decodeInfo, const UMLRTObject_class * desc, void * data, int arraySize )
+void UMLRTSignalElement::decode( const void * * decodeInfo, const UMLRTObject_class * desc, void * data, int arraySize )
 {
     // decodeInfo is initialized to be NULL by a decoder - it is owned by the decoder and not by
     // the signal (contrary to the encodeInfo, which can be owned by the signal, since there is always
     // only ever one encoder).
 
-    if (!(*decodeInfo))
+    if ((*decodeInfo) == NULL)
     {
         *decodeInfo = payload;
     }
     for (int i = 0; i < arraySize; ++i)
     {
-        *decodeInfo = desc->decode(desc, *decodeInfo, data);
+        *decodeInfo = desc->decode(desc, *decodeInfo, data, /*nest*/0);
+        data = (void *)((uint8_t*)data + desc->sizeDecoded);
     }
 }
 
 // See documentation in UMLRTSignal.
-void UMLRTSignalElement::decode( void * * decodeInfo, const UMLRTObject_class * desc, int ptrIndirection, void * data, int arraySize )
+void UMLRTSignalElement::decode( const void * * decodeInfo, const UMLRTObject_class * desc, int ptrIndirection, void * data, int arraySize )
 {
     FATAL("decode ptr indirection not implemented.");
 }
diff --git a/rts/umlrt/umlrttimerprotocol.cc b/rts/umlrt/umlrttimerprotocol.cc
index 6c7e293..f66df76 100644
--- a/rts/umlrt/umlrttimerprotocol.cc
+++ b/rts/umlrt/umlrttimerprotocol.cc
@@ -76,7 +76,7 @@
 
         if (userData)
         {
-            timer->signal.encode(userData, type);
+            timer->signal.encode(type, userData);
         }
     }
     return UMLRTTimerId(timer);