From bb66c0de98b275d99bf99b3ccea557d816f5311a Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Tue, 25 Jun 2013 17:13:44 +0200
Subject: [PATCH] Changed memory handling to a pluggable architecture.

---
 compiler/C_CodeGen.jrag                       |  10 +-
 examples/simple/example_decoder.c             |   4 +-
 examples/simple/example_encoder.c             |   4 +-
 examples/twoway/Makefile                      |   2 +-
 examples/twoway/client.c                      |  29 +++--
 examples/twoway/decimating.c                  |  19 ++-
 examples/twoway/decimating.h                  |   3 +-
 examples/twoway/introspecting.c               | 121 +++++++++++++----
 examples/twoway/introspecting.h               |   3 +-
 examples/twoway/server.c                      |  38 +++---
 lib/c/Makefile                                |   1 +
 lib/c/labcomm.c                               | 123 +++++++++++-------
 lib/c/labcomm.h                               |  34 ++++-
 lib/c/labcomm_default_memory.c                |  49 +++++++
 lib/c/labcomm_dynamic_buffer_writer.c         |  19 +--
 lib/c/labcomm_dynamic_buffer_writer.h         |  24 ++++
 lib/c/labcomm_fd_reader.c                     |  57 +++-----
 lib/c/labcomm_fd_reader.h                     |  24 +++-
 lib/c/labcomm_fd_writer.c                     |  30 ++---
 lib/c/labcomm_fd_writer.h                     |  24 +++-
 lib/c/labcomm_memory.c                        |  40 ++++++
 lib/c/labcomm_private.h                       |  48 +++++--
 lib/c/labcomm_pthread_mutex_lock.c            |  14 +-
 lib/c/labcomm_pthread_mutex_lock.h            |  24 +++-
 lib/c/test/test_labcomm_basic_type_encoding.c |   1 +
 lib/c/test/test_labcomm_generated_encoding.c  |   5 +-
 test/nested.lc                                |   2 +
 test/relay_gen_c.py                           |   8 +-
 28 files changed, 549 insertions(+), 211 deletions(-)
 create mode 100644 lib/c/labcomm_default_memory.c
 create mode 100644 lib/c/labcomm_memory.c

diff --git a/compiler/C_CodeGen.jrag b/compiler/C_CodeGen.jrag
index 786f5cc..551e14d 100644
--- a/compiler/C_CodeGen.jrag
+++ b/compiler/C_CodeGen.jrag
@@ -538,7 +538,9 @@ aspect C_Decoder {
   }
 
   public void VariableArrayType.C_emitDecoderArrayAllocate(C_env env) {
-    env.print(env.qualid + ".a = malloc(sizeof(" + env.qualid + ".a[0])");
+    env.print(env.qualid + 
+              ".a = labcomm_memory_alloc(r->memory, 1, sizeof(" + 
+	      env.qualid + ".a[0])");
     for (int i = 0 ; i < getNumExp() ; i++) {
       env.print(" * " + getExp(i).C_getLimit(env, i));
     }
@@ -555,7 +557,8 @@ aspect C_Decoder {
 
   public void PrimType.C_emitDecoderDeallocation(C_env env) {
     if (C_isDynamic()) {
-      env.println("free(" + env.qualid + ");");
+      env.println("labcomm_memory_free(r->memory, 1, " + 
+                  env.qualid + ");");
     }
   }
 
@@ -600,7 +603,8 @@ aspect C_Decoder {
 
   public void VariableArrayType.C_emitDecoderDeallocation(C_env env) {
     super.C_emitDecoderDeallocation(env);
-    env.println("free(" + env.qualid + ".a);");
+    env.println("labcomm_memory_free(r->memory, 1, " + 
+                env.qualid + ".a);");
   }
 
   public void Field.C_emitDecoderDeallocation(C_env env) {
diff --git a/examples/simple/example_decoder.c b/examples/simple/example_decoder.c
index d79bc7a..2b1f746 100644
--- a/examples/simple/example_decoder.c
+++ b/examples/simple/example_decoder.c
@@ -56,7 +56,9 @@ int main(int argc, char *argv[]) {
   char *filename = argv[1];
   printf("C decoder reading from %s\n", filename);
   fd = open(filename, O_RDONLY);
-  decoder = labcomm_decoder_new(labcomm_fd_reader_new(fd, 1), NULL);
+  decoder = labcomm_decoder_new(labcomm_fd_reader_new(
+				  labcomm_default_memory, fd, 1), 
+				NULL, labcomm_default_memory);
   if (!decoder) { 
     printf("Failed to allocate decoder %s:%d\n", __FUNCTION__, __LINE__);
     return 1;
diff --git a/examples/simple/example_encoder.c b/examples/simple/example_encoder.c
index b4f3921..67beb4c 100644
--- a/examples/simple/example_encoder.c
+++ b/examples/simple/example_encoder.c
@@ -12,7 +12,9 @@ int main(int argc, char *argv[]) {
   char *filename = argv[1];
   printf("C encoder writing to %s\n", filename);
   fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
-  encoder = labcomm_encoder_new(labcomm_fd_writer_new(fd, 1), NULL);
+  encoder = labcomm_encoder_new(labcomm_fd_writer_new(
+				  labcomm_default_memory, fd, 1), 
+				NULL, labcomm_default_memory);
   labcomm_encoder_register_simple_theTwoInts(encoder);
   labcomm_encoder_register_simple_anotherTwoInts(encoder);
   labcomm_encoder_register_simple_IntString(encoder);
diff --git a/examples/twoway/Makefile b/examples/twoway/Makefile
index 5689df1..76da45e 100644
--- a/examples/twoway/Makefile
+++ b/examples/twoway/Makefile
@@ -42,11 +42,11 @@ gen/introspecting.o: introspecting.h
 gen/introspecting.o: gen/introspecting_messages.h
 gen/client.o: decimating.h
 gen/client.o: gen/types.h
-gen/client: gen/types.o
 gen/client: gen/decimating.o 
 gen/client: gen/decimating_messages.o
 gen/client: gen/introspecting.o
 gen/client: gen/introspecting_messages.o
+gen/client: gen/types.o
 gen/server: gen/types.o
 gen/server: gen/decimating.o
 gen/server: gen/decimating_messages.o
diff --git a/examples/twoway/client.c b/examples/twoway/client.c
index ec373b1..401a7a5 100644
--- a/examples/twoway/client.c
+++ b/examples/twoway/client.c
@@ -53,6 +53,8 @@ static void *run_decoder(void *context)
   struct labcomm_decoder *decoder = context;
   int result;
 
+  labcomm_decoder_register_types_Sum(decoder, handle_Sum, NULL);
+  labcomm_decoder_register_types_Diff(decoder, handle_Diff, NULL);
   do {
     result = labcomm_decoder_decode_one(decoder);
   } while (result >= 0);
@@ -112,34 +114,35 @@ int main(int argc, char *argv[])
   
   nodelay = 1;
   setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));
-  lock = labcomm_pthread_mutex_lock_new();
-  decimating = decimating_new(labcomm_fd_reader_new(fd, 1),
-			      labcomm_fd_writer_new(fd, 0),
-			      lock);
+  lock = labcomm_pthread_mutex_lock_new(labcomm_default_memory);
+  decimating = decimating_new(labcomm_fd_reader_new(labcomm_default_memory, 
+						    fd, 1),
+			      labcomm_fd_writer_new(labcomm_default_memory, 
+						    fd, 0),
+			      lock,
+			      labcomm_default_memory);
   if (decimating == NULL) {
     /* Warning: might leak reader and writer at this point */
     goto out;
   }
   introspecting = introspecting_new(decimating->reader,
 				    decimating->writer,
-				    lock);
+				    lock,
+				    labcomm_default_memory);
   if (introspecting == NULL) {
     /* Warning: might leak reader and writer at this point */
     goto out;
   }
-  decoder = labcomm_decoder_new(introspecting->reader, lock);
-  encoder = labcomm_encoder_new(introspecting->writer, lock);
+  decoder = labcomm_decoder_new(introspecting->reader, lock,
+				labcomm_default_memory);
+  encoder = labcomm_encoder_new(introspecting->writer, lock,
+				labcomm_default_memory);
   pthread_t rdt;
-  
-  labcomm_decoder_register_types_Sum(decoder, handle_Sum, NULL);
-  labcomm_decoder_register_types_Diff(decoder, handle_Diff, NULL);
   pthread_create(&rdt, NULL, run_decoder, decoder);  
   labcomm_encoder_register_types_A(encoder);
   labcomm_encoder_register_types_B(encoder);
   labcomm_encoder_register_types_Terminate(encoder);
 
-  usleep(100000);
-
   err = labcomm_decoder_ioctl_types_Sum(decoder, SET_DECIMATION, 2);
   err = labcomm_decoder_ioctl_types_Diff(decoder, SET_DECIMATION, 4);
 
@@ -151,7 +154,7 @@ int main(int argc, char *argv[])
       sleep(1);
     }
   }
-  labcomm_encode_types_Terminate(encoder, NULL);
+  labcomm_encode_types_Terminate(encoder, LABCOMM_VOID);
 out:
   return 0;
   
diff --git a/examples/twoway/decimating.c b/examples/twoway/decimating.c
index 9ce2b34..52b2329 100644
--- a/examples/twoway/decimating.c
+++ b/examples/twoway/decimating.c
@@ -29,8 +29,8 @@
 
 struct decimating_private {
   struct decimating decimating;
+  struct labcomm_memory *memory;
   struct labcomm_lock *lock;
-  struct labcomm_encoder *encoder;
   int encoder_initialized;
   struct labcomm_reader_action_context reader_action_context;
   struct labcomm_writer_action_context writer_action_context;
@@ -48,7 +48,8 @@ static void set_decimation(
   struct decimating_private *decimating = context;
   struct decimation *decimation;
 
-  decimation = LABCOMM_SIGNATURE_ARRAY_REF(decimating->decimation, 
+  decimation = LABCOMM_SIGNATURE_ARRAY_REF(decimating->memory,
+					   decimating->decimation, 
 					   struct decimation, 
 					   value->signature_index);
   decimation->n = value->decimation;
@@ -92,7 +93,7 @@ static int wrap_reader_ioctl(
     decimation.signature_index = signature_index;
     va_end(va);
     return labcomm_encode_decimating_messages_set_decimation(
-      decimating->encoder, &decimation);
+      decimating->decimating.writer->encoder, &decimation);
   } else {
     return labcomm_reader_ioctl(r, action_context->next,
 				signature_index, signature, action, args);
@@ -123,11 +124,8 @@ static int wrap_writer_alloc(
   labcomm_encoder_enqueue enqueue)
 {
   int result;
-  struct decimating_private *decimating = action_context->context;
 
   fprintf(stderr, "%s %s\n", __FILE__, __FUNCTION__);
-  /* Stash away encoder for later use */
-  decimating->encoder = encoder;
   result = labcomm_writer_alloc(w, action_context->next,
 				encoder, labcomm_version, enqueue);
   enqueue(encoder, register_signatures, NULL);
@@ -144,7 +142,8 @@ static int wrap_writer_start(
   struct decimating_private *decimating = action_context->context;
   struct decimation *decimation;
 
-  decimation = LABCOMM_SIGNATURE_ARRAY_REF(decimating->decimation, 
+  decimation = LABCOMM_SIGNATURE_ARRAY_REF(decimating->memory, 
+					   decimating->decimation, 
 					   struct decimation, index);
   decimation->current++;
   if (decimation->current < decimation->n) {
@@ -168,7 +167,8 @@ struct labcomm_writer_action decimating_writer_action = {
 extern struct decimating *decimating_new(
   struct labcomm_reader *reader,
   struct labcomm_writer *writer,
-  struct labcomm_lock *lock)
+  struct labcomm_lock *lock,
+  struct labcomm_memory *memory)
 {
   struct decimating_private *result;
 
@@ -194,8 +194,7 @@ extern struct decimating *decimating_new(
 
   /* Init other fields */
   result->lock = lock;
-  result->encoder = NULL;
-  result->encoder_initialized = 0;
+  result->memory = memory;
   LABCOMM_SIGNATURE_ARRAY_INIT(result->decimation, struct decimation);
 
   goto out_ok;
diff --git a/examples/twoway/decimating.h b/examples/twoway/decimating.h
index ca539c0..df926ef 100644
--- a/examples/twoway/decimating.h
+++ b/examples/twoway/decimating.h
@@ -12,7 +12,8 @@ struct decimating {
 extern struct decimating *decimating_new(
   struct labcomm_reader *reader,
   struct labcomm_writer *writer,
-  struct labcomm_lock *lock);
+  struct labcomm_lock *lock,
+  struct labcomm_memory *memory);
 
 #define SET_DECIMATION LABCOMM_IOSW('d',0,int)
 
diff --git a/examples/twoway/introspecting.c b/examples/twoway/introspecting.c
index 85c2919..8123988 100644
--- a/examples/twoway/introspecting.c
+++ b/examples/twoway/introspecting.c
@@ -27,19 +27,28 @@
 #include "introspecting.h"
 #include "gen/introspecting_messages.h"
 
+enum status {unknown, unhandled, unregistered, registered};
 struct introspecting_private {
   struct introspecting introspecting;
+  struct labcomm_lock *lock;
+  struct labcomm_memory *memory;
+
   struct labcomm_encoder *encoder;
   int encoder_initialized;
   struct labcomm_decoder *decoder;
   int decoder_initialized;
-  struct labcomm_lock *lock;
   struct labcomm_reader_action_context reader_action_context;
   struct labcomm_writer_action_context writer_action_context;
-  LABCOMM_SIGNATURE_ARRAY_DEF(introspection, 
-			      struct introspection {
-				int has_got_response;
-				int has_handler;
+  LABCOMM_SIGNATURE_ARRAY_DEF(remote, 
+			      struct remote {
+				char *name;
+				int size;
+				uint8_t *signature;
+			      });
+  LABCOMM_SIGNATURE_ARRAY_DEF(local, 
+			      struct local {
+				enum status status;
+				struct labcomm_signature *signature;
 			      });
 };
 
@@ -48,16 +57,37 @@ static void handles_signature(
   void * context)
 {
   fprintf(stderr, "### %s %x %s\n", __FUNCTION__, value->index, value->name);
-/*
   struct introspecting_private *introspecting = context;
-  struct introspection *introspection;
-
-  introspection = LABCOMM_SIGNATURE_ARRAY_REF(introspecting->introspection, 
-					      struct introspection, 
-					      value->index);
-
-  introspection->has_handler = value->has_handler;
-*/
+  struct remote *remote;
+
+  remote = LABCOMM_SIGNATURE_ARRAY_REF(introspecting->memory,
+				       introspecting->remote, 
+				       struct remote, 
+				       value->index);
+  remote->name = strdup(value->name);
+  remote->signature = malloc(value->signature.n_0);
+  if (remote->signature) {
+    int i;
+
+    memcpy(remote->signature, value->signature.a, value->signature.n_0);
+    remote->size = value->signature.n_0;
+    LABCOMM_SIGNATURE_ARRAY_FOREACH(introspecting->local, struct local, i) {
+      struct local *l;
+      
+      l = LABCOMM_SIGNATURE_ARRAY_REF(introspecting->memory,
+				      introspecting->local, struct local, i);
+      if (l->signature && 
+	  l->status == unhandled &&
+	  l->signature->name && 
+	  strcmp(remote->name, l->signature->name) == 0 &&
+	  remote->size == l->signature->size &&
+	  memcmp(l->signature->signature, remote->signature, 
+		 l->signature->size) == 0) {
+	fprintf(stderr, "OK %s %x %x\n", __FUNCTION__, value->index, i);
+	l->status = unregistered;
+      }
+    }
+  }
 }
 
 static int wrap_reader_alloc(
@@ -87,10 +117,19 @@ static int wrap_reader_start(
   void *value)
 {
   struct introspecting_private *introspecting = action_context->context;
-
-  if (value == NULL && introspecting->decoder_initialized) {
+  int result;
+  
+  result = labcomm_reader_start(r, action_context->next, index,
+				signature, value);  
+  if (value == NULL) {
     introspecting_messages_handles_signature handles_signature;
 
+    labcomm_lock_acquire(introspecting->lock);
+    while (introspecting->encoder == NULL) {
+      /* Wait for the encoder to become functional */
+      labcomm_lock_wait(introspecting->lock, 1000000);
+    }
+    labcomm_lock_release(introspecting->lock);
     handles_signature.index = index;
     handles_signature.name = signature->name;
     handles_signature.signature.n_0 = signature->size;
@@ -98,7 +137,7 @@ static int wrap_reader_start(
     labcomm_encode_introspecting_messages_handles_signature(
       introspecting->encoder, &handles_signature);
   }
-  return labcomm_reader_start(r, action_context->next, index, signature, value);
+  return result;
 }
 
  void encode_handles_signature(
@@ -146,7 +185,10 @@ static int wrap_writer_alloc(
 
   fprintf(stderr, "%s %s\n", __FILE__, __FUNCTION__);
   /* Stash away encoder for later use */
+  labcomm_lock_acquire(introspecting->lock);
   introspecting->encoder = encoder;
+  labcomm_lock_notify(introspecting->lock);
+  labcomm_lock_release(introspecting->lock);
   result = labcomm_writer_alloc(w, action_context->next,
 				encoder, labcomm_version, enqueue);
   enqueue(encoder, register_signatures, NULL);
@@ -159,9 +201,39 @@ static int wrap_writer_start(
   int index, struct labcomm_signature *signature,
   void *value)
 {
-//  struct introspecting_private *introspecting = action_context->context;
-
-  fprintf(stderr, "%s %p\n", __FUNCTION__, value);
+  struct introspecting_private *introspecting = action_context->context;
+  struct local *local;
+
+  fprintf(stderr, "%s %x %s\n", __FUNCTION__, index, signature->name);
+  local = LABCOMM_SIGNATURE_ARRAY_REF(introspecting->memory,
+				      introspecting->local, 
+				      struct local, 
+				      index);
+  if (local->signature == NULL) {
+    local->signature = signature;
+  }
+  if (local->status == unknown) {
+    int i;
+    int found = 0;
+
+    LABCOMM_SIGNATURE_ARRAY_FOREACH(introspecting->remote, struct remote, i) {
+      struct remote *r;
+      
+      r = LABCOMM_SIGNATURE_ARRAY_REF(introspecting->memory,
+				      introspecting->remote, struct remote, i);
+      if (r->name && 
+	  strcmp(signature->name, r->name) == 0 &&
+	  r->size == signature->size &&
+	  memcmp(signature->signature, r->signature, signature->size) == 0) {
+	fprintf(stderr, "OK %s %x %x\n", __FUNCTION__, index, i);
+	found = i;
+      }
+    }
+    if (found == 0) {
+      local->status = unhandled;
+    }
+    fprintf(stderr, "Found: %d\n", found);
+  }
   return labcomm_writer_start(w, action_context->next, index, signature, value);
 }
 
@@ -177,7 +249,8 @@ struct labcomm_writer_action introspecting_writer_action = {
 extern struct introspecting *introspecting_new(
   struct labcomm_reader *reader,
   struct labcomm_writer *writer,
-  struct labcomm_lock *lock)
+  struct labcomm_lock *lock,
+  struct labcomm_memory *memory)
 {
   struct introspecting_private *result;
 
@@ -202,12 +275,14 @@ extern struct introspecting *introspecting_new(
   result->introspecting.writer = writer;
 
   /* Init other fields */
+  result->lock = lock;
+  result->memory = memory;
   result->encoder = NULL;
   result->encoder_initialized = 0;
   result->decoder = NULL;
   result->decoder_initialized = 0;
-  result->lock = lock;
-  LABCOMM_SIGNATURE_ARRAY_INIT(result->introspection, struct introspection);
+  LABCOMM_SIGNATURE_ARRAY_INIT(result->remote, struct remote);
+  LABCOMM_SIGNATURE_ARRAY_INIT(result->local, struct local);
 
   goto out_ok;
 
diff --git a/examples/twoway/introspecting.h b/examples/twoway/introspecting.h
index 9c16827..7eea00e 100644
--- a/examples/twoway/introspecting.h
+++ b/examples/twoway/introspecting.h
@@ -36,7 +36,8 @@ struct introspecting {
 extern struct introspecting *introspecting_new(
   struct labcomm_reader *reader,
   struct labcomm_writer *writer,
-  struct labcomm_lock *lock);
+  struct labcomm_lock *lock,
+  struct labcomm_memory *memory);
 
 #define HAS_SIGNATURE LABCOMM_IOS('i',2)
 
diff --git a/examples/twoway/server.c b/examples/twoway/server.c
index 9a980cb..58a8ae0 100644
--- a/examples/twoway/server.c
+++ b/examples/twoway/server.c
@@ -68,13 +68,18 @@ static void handle_Terminate(types_Terminate *value, void *context)
   exit(0);
 }
 
-static void *run_decoder(void *context)
+static void *run_decoder(void *arg)
 {
-  struct labcomm_decoder *decoder = context;
+  struct client *client = arg;
   int result;
 
+  
+  labcomm_decoder_register_types_A(client->decoder, handle_A, client);
+  labcomm_decoder_register_types_B(client->decoder, handle_B, client);
+  labcomm_decoder_register_types_Terminate(client->decoder, handle_Terminate, 
+					   NULL);
   do {
-    result = labcomm_decoder_decode_one(decoder);
+    result = labcomm_decoder_decode_one(client->decoder);
   } while (result >= 0);
   return NULL;
 }
@@ -89,30 +94,31 @@ static void *run_client(void *arg)
   printf("Client start\n");
   client->A = 0;
   client->B = 0;
-  lock = labcomm_pthread_mutex_lock_new();
-  decimating = decimating_new(labcomm_fd_reader_new(client->fd, 1),
-			      labcomm_fd_writer_new(client->fd, 0),
-			      lock);
+  lock = labcomm_pthread_mutex_lock_new(labcomm_default_memory);
+  decimating = decimating_new(labcomm_fd_reader_new(labcomm_default_memory,
+						    client->fd, 1),
+			      labcomm_fd_writer_new(labcomm_default_memory,
+						    client->fd, 0),
+			      lock,
+			      labcomm_default_memory);
   if (decimating == NULL) {
     /* Warning: might leak reader and writer at this point */
     goto out;
   }
   introspecting = introspecting_new(decimating->reader,
 				    decimating->writer,
-				    lock);
+				    lock,
+				    labcomm_default_memory);
   if (introspecting == NULL) {
     /* Warning: might leak reader and writer at this point */
     goto out;
   }
-  client->decoder = labcomm_decoder_new(introspecting->reader, lock);
-  client->encoder = labcomm_encoder_new(introspecting->writer, lock);
+  client->decoder = labcomm_decoder_new(introspecting->reader, lock,
+					labcomm_default_memory);
+  client->encoder = labcomm_encoder_new(introspecting->writer, lock,
+					labcomm_default_memory);
   pthread_t rdt;
-  
-  labcomm_decoder_register_types_A(client->decoder, handle_A, client);
-  labcomm_decoder_register_types_B(client->decoder, handle_B, client);
-  labcomm_decoder_register_types_Terminate(client->decoder, handle_Terminate, 
-					   NULL);
-  pthread_create(&rdt, NULL, run_decoder, client->decoder);  
+  pthread_create(&rdt, NULL, run_decoder, client);  
   labcomm_encoder_register_types_Sum(client->encoder);
   labcomm_encoder_register_types_Diff(client->encoder);
   pthread_join(rdt, NULL);
diff --git a/lib/c/Makefile b/lib/c/Makefile
index bb68b64..348e8c3 100644
--- a/lib/c/Makefile
+++ b/lib/c/Makefile
@@ -8,6 +8,7 @@ LDFLAGS=-L.
 LDLIBS_TEST=-lcunit -llabcomm -Tlabcomm.linkscript
 
 OBJS= labcomm.o \
+      labcomm_memory.o labcomm_default_memory.o \
       labcomm_dynamic_buffer_writer.o labcomm_fd_reader.o labcomm_fd_writer.o \
       labcomm_pthread_mutex_lock.o
 
diff --git a/lib/c/labcomm.c b/lib/c/labcomm.c
index c5e7bfb..582d5aa 100644
--- a/lib/c/labcomm.c
+++ b/lib/c/labcomm.c
@@ -43,6 +43,7 @@ struct labcomm_decoder {
   void *context;
   struct labcomm_reader *reader;
   struct labcomm_lock *lock;
+  struct labcomm_memory *memory;
   labcomm_error_handler_callback on_error;
   labcomm_handle_new_datatype_callback on_new_datatype;
   LABCOMM_SIGNATURE_ARRAY_DEF(local_to_remote, int);
@@ -53,6 +54,7 @@ struct labcomm_encoder {
   void *context;
   struct labcomm_writer *writer;
   struct labcomm_lock *lock;
+  struct labcomm_memory *memory;
   struct labcomm_encoder *is_deferred;
   int busy;
   int waiting;
@@ -347,13 +349,16 @@ static int get_encoder_index(
 
 struct labcomm_encoder *labcomm_encoder_new(
   struct labcomm_writer *writer,
-  struct labcomm_lock *lock)
+  struct labcomm_lock *lock,
+  struct labcomm_memory *memory)
 {
-  struct labcomm_encoder *result = malloc(sizeof(*result));
+  struct labcomm_encoder *result;
+
+  result = labcomm_memory_alloc(memory, 0, sizeof(*result));
   if (result) {
     struct labcomm_encoder_context *context;
 
-    context = malloc(sizeof(*context));
+    context = labcomm_memory_alloc(memory, 0, sizeof(*context));
 #ifdef LABCOMM_ENCODER_LINEAR_SEARCH
     context->sample = NULL;
     context->index = LABCOMM_USER;
@@ -362,12 +367,14 @@ struct labcomm_encoder *labcomm_encoder_new(
 #endif
     result->context = context;
     result->writer = writer;
+    result->writer->encoder = result;
     result->writer->data = NULL;
     result->writer->data_size = 0;
     result->writer->count = 0;
     result->writer->pos = 0;
     result->writer->error = 0;
     result->lock = lock;
+    result->memory = memory;
     result->is_deferred = NULL;
     result->busy = 0;
     result->waiting = 0;
@@ -386,8 +393,7 @@ static int encoder_enqueue_action(
   int result;
   struct encoder_alloc_action *element, **next;
 
-  fprintf(stderr, "%s %p\n", __FUNCTION__, action);
-  element = malloc(sizeof(*action));
+  element = labcomm_memory_alloc(encoder->memory, 0, sizeof(*action));
   if (element == NULL) {
     result = -ENOMEM;
     goto out;
@@ -427,11 +433,10 @@ static struct labcomm_encoder *enter_encoder(struct labcomm_encoder *e)
 	while (p) {
 	  struct encoder_alloc_action *tmp;
 
-	  fprintf(stderr, "RUN %p", p->action);
 	  p->action(&deferred, p->context);
 	  tmp = p;
 	  p = p->next;
-	  free(tmp);
+	  labcomm_memory_free(e->memory, 1, tmp);
 	}
       }
     }
@@ -464,7 +469,8 @@ int labcomm_internal_encoder_register(
   index = get_encoder_index(e, signature);
   if (signature->type == LABCOMM_SAMPLE) {
     if (index > 0) {
-      int *registered = LABCOMM_SIGNATURE_ARRAY_REF(e->registered, int, index);
+      int *registered = LABCOMM_SIGNATURE_ARRAY_REF(e->memory, e->registered, 
+						    int, index);
       if (! *registered) {
 	int err;
 	
@@ -473,6 +479,8 @@ int labcomm_internal_encoder_register(
 				   index, signature, NULL);
 	if (err == -EALREADY) {
 	  result = 0;
+	} else if (err != 0) {
+	  result = err;
 	} else if (err == 0) {
 	  int i;
 
@@ -525,24 +533,25 @@ no_end:
 void labcomm_encoder_free(struct labcomm_encoder* e)
 {
   struct labcomm_encoder_context *context;
+  struct labcomm_memory * memory = e->memory;
 
   context = (struct labcomm_encoder_context *) e->context;
   labcomm_writer_free(e->writer, e->writer->action_context);
-  LABCOMM_SIGNATURE_ARRAY_FREE(e->registered, int);
+  LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, e->registered, int);
 
 #ifdef LABCOMM_ENCODER_LINEAR_SEARCH
   struct labcomm_sample_entry *entry = context->sample;
   struct labcomm_sample_entry *entry_next;
   while (entry != NULL) {
     entry_next = entry->next;
-    free(entry);
+    labcomm_memory_free(memory, 0, entry);
     entry = entry_next;
   }
 #else
-  free(context->by_section);
+  labcomm_memory_free(memory, 0, context->by_section);
 #endif
-  free(e->context);
-  free(e);
+  labcomm_memory_free(memory, 0, e->context);
+  labcomm_memory_free(memory, 0, e);
 }
 
 int labcomm_encoder_ioctl(struct labcomm_encoder *encoder, 
@@ -629,7 +638,7 @@ static void collect_flat_signature(
 	for (i = 0 ; i < fields ; i++) {
 	  char *name = labcomm_read_string(decoder->reader);
 	  labcomm_write_string(writer, name);
-	  free(name);
+	  labcomm_memory_free(decoder->memory, 1, name);
 	  collect_flat_signature(decoder, writer);
 	}
       } break;
@@ -652,21 +661,27 @@ static void collect_flat_signature(
 
 struct labcomm_decoder *labcomm_decoder_new(
   struct labcomm_reader *reader,
-  struct labcomm_lock *lock)
+  struct labcomm_lock *lock,
+  struct labcomm_memory *memory)
 {
-  struct labcomm_decoder *result = malloc(sizeof(*result));
+  struct labcomm_decoder *result;
+
+  result = labcomm_memory_alloc(memory, 0, sizeof(*result));
   if (result) {
-    struct labcomm_decoder_context *context =
-      (struct labcomm_decoder_context *)malloc(sizeof(*context));
+    struct labcomm_decoder_context *context;
+
+    context = labcomm_memory_alloc(memory, 0, sizeof(*context));
     context->sample = 0;
     result->context = context;
     result->reader = reader;
+    result->reader->decoder = result;
     result->reader->data = 0;
     result->reader->data_size = 0;
     result->reader->count = 0;
     result->reader->pos = 0;
     result->reader->error = 0;
     result->lock = lock;
+    result->memory = memory;
     result->on_error = on_error_fprintf;
     result->on_new_datatype = on_new_datatype;
     LABCOMM_SIGNATURE_ARRAY_INIT(result->local_to_remote, int);
@@ -683,20 +698,29 @@ int labcomm_internal_decoder_register(
   void *handler_context)
 {
   struct labcomm_decoder_context *context = d->context;
-  struct labcomm_sample_entry *sample;
-  sample = get_sample_by_signature_address(context->sample,
-					   signature);
-  if (!sample) {
-    sample = (struct labcomm_sample_entry *)malloc(sizeof(*sample));
-    sample->next = context->sample;
-    context->sample = sample;
-    sample->index = 0;
-    sample->signature = signature;
-  }
-  sample->decoder = type_decoder;
-  sample->handler = handler;
-  sample->context = handler_context;
+  int index;
+  
+  index = get_local_index(signature);
+  if (index >= 0) {
+    struct labcomm_sample_entry *sample;
 
+    labcomm_reader_start(d->reader, d->reader->action_context,
+			 index, signature,
+			 NULL);
+    labcomm_reader_end(d->reader, d->reader->action_context);
+    sample = get_sample_by_signature_address(context->sample,
+					     signature);
+    if (!sample) {
+      sample = labcomm_memory_alloc(d->memory, 0, sizeof(*sample));
+      sample->next = context->sample;
+      context->sample = sample;
+      sample->index = 0;
+      sample->signature = signature;
+    }
+    sample->decoder = type_decoder;
+    sample->handler = handler;
+    sample->context = handler_context;
+  }
   return 0;
 }
 
@@ -714,6 +738,7 @@ static int decode_typedef_or_sample(struct labcomm_decoder *d, int kind)
   };
   struct labcomm_writer writer = {
     .action_context = &action_context,
+    .memory = d->memory,
     .data = NULL,
     .data_size = 0,
     .count = 0,
@@ -749,7 +774,6 @@ static int decode_typedef_or_sample(struct labcomm_decoder *d, int kind)
   }
   entry = get_sample_by_signature_value(context->sample, &signature);
   if (! entry) {
-    fprintf(stderr, "%d %s\n", remote_index, signature.name);
     /* Unknown datatype, bail out */
     d->on_new_datatype(d, &signature);
     result = -ENOENT;
@@ -764,20 +788,18 @@ static int decode_typedef_or_sample(struct labcomm_decoder *d, int kind)
     // TODO unnessesary, since entry->index == index in above if statement
     entry->index = remote_index;
     local_index = get_local_index(entry->signature);
-    local_to_remote = LABCOMM_SIGNATURE_ARRAY_REF(d->local_to_remote, int,
+    local_to_remote = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+						  d->local_to_remote, int,
 						  local_index);
     *local_to_remote = remote_index;
-    remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->remote_to_local, int,
+    remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+						  d->remote_to_local, int,
 						  remote_index);
     *remote_to_local = local_index;
     result = remote_index;
-    labcomm_reader_start(d->reader, d->reader->action_context,
-			 entry->index, entry->signature,
-			 NULL);
-    labcomm_reader_end(d->reader, d->reader->action_context);
   }
 free_signature_name:
-  free(signature.name);
+  labcomm_memory_free(d->memory, 0, signature.name);
   labcomm_writer_free(&writer, writer.action_context);
   if (!entry) {
     // No handler for found type, bail out (after cleanup)
@@ -856,18 +878,19 @@ void labcomm_decoder_free(struct labcomm_decoder* d)
   struct labcomm_decoder_context *context = (struct labcomm_decoder_context *) d->context;
   struct labcomm_sample_entry *entry = context->sample;
   struct labcomm_sample_entry *entry_next;
+  struct labcomm_memory *memory = d->memory;
 
   labcomm_reader_free(d->reader, d->reader->action_context);
-  LABCOMM_SIGNATURE_ARRAY_FREE(d->local_to_remote, int);
-  LABCOMM_SIGNATURE_ARRAY_FREE(d->remote_to_local, int);
+  LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->local_to_remote, int);
+  LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local, int);
   while (entry != NULL) {
     entry_next = entry->next;
-    free(entry);
+    labcomm_memory_free(memory, 0, entry);
     entry = entry_next;
   }
 
-  free(d->context);
-  free(d);
+  labcomm_memory_free(memory, 0, d->context);
+  labcomm_memory_free(memory, 0, d);
 }
 
 int labcomm_decoder_ioctl(struct labcomm_decoder *decoder, 
@@ -893,7 +916,8 @@ int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder,
   int local_index, *remote_index;
 
   local_index = get_local_index(signature);
-  remote_index = LABCOMM_SIGNATURE_ARRAY_REF(decoder->local_to_remote, int,
+  remote_index = LABCOMM_SIGNATURE_ARRAY_REF(decoder->memory,
+					     decoder->local_to_remote, int,
 					     local_index);
   if (*remote_index == 0) {
     result = -EAGAIN;
@@ -922,13 +946,14 @@ static void dump(void *p, int size, int first, int last)
 }
 #endif
 
-void *labcomm_signature_array_ref(int *first, int *last, void **data,
+void *labcomm_signature_array_ref(struct labcomm_memory *memory,
+				  int *first, int *last, void **data,
 				  int size, int index)
 {
   if (*first == 0 && *last == 0) {
     *first = index;
     *last = index + 1;
-    *data = malloc(size);
+    *data = labcomm_memory_alloc(memory, 0, size);
     if (*data) { 
       memset(*data, 0, size); 
     }
@@ -940,7 +965,7 @@ void *labcomm_signature_array_ref(int *first, int *last, void **data,
     *first = (index<old_first)?index:old_first;
     *last = (old_last<=index)?index+1:old_last;
     n = (*last - *first);
-    *data = malloc(n * size);
+    *data = labcomm_memory_alloc(memory, 0, n * size);
     if (*data) {
       memset(*data, 0, n * size);
       memcpy(*data + (old_first - *first) * size, 
@@ -948,7 +973,7 @@ void *labcomm_signature_array_ref(int *first, int *last, void **data,
 	     (old_last - old_first) * size);
     }
 //    dump(old_data, size, old_first, old_last);
-    free(old_data);
+    labcomm_memory_free(memory, 0, old_data);
   }
   if (*data) {
 //    dump(*data, size, *first, *last);
diff --git a/lib/c/labcomm.h b/lib/c/labcomm.h
index 1e4f303..42bdbce 100644
--- a/lib/c/labcomm.h
+++ b/lib/c/labcomm.h
@@ -80,15 +80,33 @@ void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d,
 		labcomm_handle_new_datatype_callback on_new_datatype);
 
 /*
- * Locking support (optional)
+ * Locking support (optional), if not used only a single thread
+ * may access an encoder or decoder at the same time.
  */
 struct labcomm_lock;
 
 int labcomm_lock_free(struct labcomm_lock *lock);
-int labcomm_lock_lock(struct labcomm_lock *lock);
-int labcomm_lock_unlock(struct labcomm_lock *lock);
+int labcomm_lock_acquire(struct labcomm_lock *lock);
+int labcomm_lock_release(struct labcomm_lock *lock);
 int labcomm_lock_wait(struct labcomm_lock *lock, useconds_t usec);
-int labcomm_lock_notify_all(struct labcomm_lock *lock);
+int labcomm_lock_notify(struct labcomm_lock *lock);
+
+/*
+ * Dynamic memory handling
+ *   lifetime == 0     memory that will live for as long as the 
+ *                     encoder/decoder or that are allocated/deallocated 
+ *                     during the communication setup phase
+ *   otherwise         memory will live for approximately this number of
+ *                     sent/received samples
+ */
+struct labcomm_memory;
+
+void *labcomm_memory_alloc(struct labcomm_memory *m, int lifetime, size_t size);
+void *labcomm_memory_realloc(struct labcomm_memory *m, int lifetime, 
+			     void *ptr, size_t size);
+void labcomm_memory_free(struct labcomm_memory *m, int lifetime, void *ptr);
+
+extern struct labcomm_memory *labcomm_default_memory;
 
 /*
  * Decoder
@@ -97,7 +115,8 @@ struct labcomm_reader;
 
 struct labcomm_decoder *labcomm_decoder_new(
   struct labcomm_reader *reader,
-  struct labcomm_lock *lock);
+  struct labcomm_lock *lock,
+  struct labcomm_memory *memory);
 int labcomm_decoder_decode_one(
   struct labcomm_decoder *decoder);
 void labcomm_decoder_run(
@@ -117,7 +136,8 @@ struct labcomm_writer;
 
 struct labcomm_encoder *labcomm_encoder_new(
   struct labcomm_writer *writer,
-  struct labcomm_lock *lock);
+  struct labcomm_lock *lock,
+  struct labcomm_memory *memory);
 void labcomm_encoder_free(
   struct labcomm_encoder *encoder);
 
@@ -126,4 +146,6 @@ int labcomm_encoder_ioctl(struct labcomm_encoder *encoder,
 			  uint32_t ioctl_action,
 			  ...);
 
+#define LABCOMM_VOID ((void*)1)
+
 #endif
diff --git a/lib/c/labcomm_default_memory.c b/lib/c/labcomm_default_memory.c
new file mode 100644
index 0000000..d6b13c5
--- /dev/null
+++ b/lib/c/labcomm_default_memory.c
@@ -0,0 +1,49 @@
+/*
+  test_default_memory.c -- LabComm default memory allocator
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "labcomm.h"
+#include "labcomm_private.h"
+
+void *default_alloc(struct labcomm_memory *m, int lifetime, size_t size)
+{
+  return malloc(size);
+}
+
+void *default_realloc(struct labcomm_memory *m, int lifetime, 
+		      void *ptr, size_t size)
+{
+  return realloc(ptr, size);
+}
+
+void default_free(struct labcomm_memory *m, int lifetime, void *ptr)
+{
+  free(ptr);
+}
+
+struct labcomm_memory memory = {
+  .alloc = default_alloc,
+  .realloc = default_realloc,
+  .free = default_free,
+  .context = NULL
+};
+
+struct labcomm_memory *labcomm_default_memory = &memory;
diff --git a/lib/c/labcomm_dynamic_buffer_writer.c b/lib/c/labcomm_dynamic_buffer_writer.c
index f3619b0..fb61f23 100644
--- a/lib/c/labcomm_dynamic_buffer_writer.c
+++ b/lib/c/labcomm_dynamic_buffer_writer.c
@@ -35,7 +35,7 @@ static int dyn_alloc(struct labcomm_writer *w,
 {
   w->data_size = 1000;
   w->count = w->data_size;
-  w->data = malloc(w->data_size);
+  w->data = labcomm_memory_alloc(w->memory, 1, w->data_size);
   if (w->data == NULL) {
     w->error = -ENOMEM;
   }
@@ -47,14 +47,12 @@ static int dyn_alloc(struct labcomm_writer *w,
 static int dyn_free(struct labcomm_writer *w, 
 		    struct labcomm_writer_action_context *action_context)
 {
-  free(w->data);
+  labcomm_memory_free(w->memory, 1, w->data);
   w->data = 0;
   w->data_size = 0;
   w->count = 0;
   w->pos = 0;
-  if (action_context->context) {
-    free(action_context->context);
-  }
+  labcomm_memory_free(w->memory, 0, action_context->context);
   return 0;
 }
 
@@ -68,7 +66,7 @@ static int dyn_start(struct labcomm_writer *w,
 
   w->data_size = 1000;
   w->count = w->data_size;
-  tmp = realloc(w->data, w->data_size);
+  tmp = labcomm_memory_realloc(w->memory, 1, w->data, w->data_size);
   if (tmp != NULL) {
     w->data = tmp;
     w->error = 0;
@@ -93,11 +91,12 @@ static int dyn_flush(struct labcomm_writer *w,
 
   w->data_size += 1000;
   w->count = w->data_size;
-  tmp = realloc(w->data, w->data_size);
+  tmp = labcomm_memory_realloc(w->memory, 1, w->data, w->data_size);
   if (tmp != NULL) {
     w->data = tmp;
     w->error = 0;
   } else {
+    /* Old pointer in w->data still valid */
     w->error = -ENOMEM;
   }
 
@@ -137,19 +136,21 @@ static const struct labcomm_writer_action action = {
 const struct labcomm_writer_action *labcomm_dynamic_buffer_writer_action = 
   &action;
 
-struct labcomm_writer *labcomm_dynamic_buffer_writer_new()
+struct labcomm_writer *labcomm_dynamic_buffer_writer_new(
+  struct labcomm_memory *memory)
 {
   struct result {
     struct labcomm_writer writer;
     struct labcomm_writer_action_context action_context;
   } *result;
 
-  result = malloc(sizeof(*result));
+  result = labcomm_memory_alloc(memory, 0, sizeof(*result));
   if (result != NULL) {
     result->action_context.next = NULL;
     result->action_context.context = result;
     result->action_context.action = &action;
     result->writer.action_context = &result->action_context;
+    result->writer.memory = memory;
     return &result->writer;
   }
   return NULL;
diff --git a/lib/c/labcomm_dynamic_buffer_writer.h b/lib/c/labcomm_dynamic_buffer_writer.h
index 7f01a1d..53a65d4 100644
--- a/lib/c/labcomm_dynamic_buffer_writer.h
+++ b/lib/c/labcomm_dynamic_buffer_writer.h
@@ -1,3 +1,24 @@
+/*
+  labcomm_dynamic_buffer_writer.h -- LabComm dynamic memory writer.
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
 #ifndef _LABCOMM_DYNAMIC_BUFFER_READER_WRITER_H_
 #define _LABCOMM_DYNAMIC_BUFFER_READER_WRITER_H_
 
@@ -5,4 +26,7 @@
 
 extern const struct labcomm_writer_action *labcomm_dynamic_buffer_writer_action;
 
+struct labcomm_writer *labcomm_dynamic_buffer_writer_new(
+  struct labcomm_memory *memory);
+
 #endif
diff --git a/lib/c/labcomm_fd_reader.c b/lib/c/labcomm_fd_reader.c
index 70c1df9..6cae2ae 100644
--- a/lib/c/labcomm_fd_reader.c
+++ b/lib/c/labcomm_fd_reader.c
@@ -44,7 +44,7 @@ static int fd_alloc(struct labcomm_reader *r,
   
   r->count = 0;
   r->pos = 0;
-  r->data = malloc(BUFFER_SIZE);
+  r->data = labcomm_memory_alloc(r->memory, 0, BUFFER_SIZE);
   if (! r->data) {
     r->data_size = 0;
     result = -ENOMEM;
@@ -61,7 +61,7 @@ static int fd_alloc(struct labcomm_reader *r,
       } else {
 	result = r->data_size;
       }
-      free(tmp);
+      labcomm_memory_free(r->memory, 1, tmp);
     }
   }
   return result;
@@ -70,18 +70,19 @@ static int fd_alloc(struct labcomm_reader *r,
 static int fd_free(struct labcomm_reader *r, 
 		   struct labcomm_reader_action_context *action_context)
 {
-  struct labcomm_fd_reader *fd_context = action_context->context;
+  struct labcomm_fd_reader *fd_reader = action_context->context;
+  struct labcomm_memory *memory = r->memory;
 
-  free(r->data);
+  labcomm_memory_free(memory, 0, r->data);
   r->data = 0;
   r->data_size = 0;
   r->count = 0;
   r->pos = 0;
 
-  if (fd_context->close_fd_on_free) {
-    close(fd_context->fd);
+  if (fd_reader->close_fd_on_free) {
+    close(fd_reader->fd);
   }
-  free(fd_context);
+  labcomm_memory_free(memory, 0, fd_reader);
 
   return 0;
 }
@@ -90,7 +91,7 @@ static int fd_fill(struct labcomm_reader *r,
 		   struct labcomm_reader_action_context *action_context)
 {
   int result = 0;
-  struct labcomm_fd_reader *fd_context = action_context->context;
+  struct labcomm_fd_reader *fd_reader = action_context->context;
 
   if (r->pos < r->count) {
     result = r->count - r->pos;
@@ -98,7 +99,7 @@ static int fd_fill(struct labcomm_reader *r,
     int err;
     
     r->pos = 0;
-    err = read(fd_context->fd, r->data, r->data_size);
+    err = read(fd_reader->fd, r->data, r->data_size);
     if (err <= 0) {
       r->count = 0;
       r->error = -EPIPE;
@@ -111,51 +112,29 @@ static int fd_fill(struct labcomm_reader *r,
   return result;
 }
 
-static int fd_start(struct labcomm_reader *r,
-		    struct labcomm_reader_action_context *action_context,
-		    int index, struct labcomm_signature *signature,
-		    void *value)
-{
-  return 0;
-}
-
-static int fd_end(struct labcomm_reader *r, 
-		  struct labcomm_reader_action_context *action_context)
-{
-  return 0;
-}
-
-static int fd_ioctl(struct labcomm_reader *r, 
-		    struct labcomm_reader_action_context *action_context,
-		    int signature_index, 
-		    struct labcomm_signature *signature, 
-		    uint32_t action, va_list args)
-{
-  return -ENOTSUP;
-}
-
-
 static const struct labcomm_reader_action action = {
   .alloc = fd_alloc,
   .free = fd_free,
-  .start = fd_start,
+  .start = NULL,
   .fill = fd_fill,
-  .end = fd_end,
-  .ioctl = fd_ioctl
+  .end = NULL,
+  .ioctl = NULL
 };
 
-struct labcomm_reader *labcomm_fd_reader_new(int fd, int close_fd_on_free)
+struct labcomm_reader *labcomm_fd_reader_new(struct labcomm_memory *memory,
+					     int fd, int close_fd_on_free)
 {
   struct labcomm_fd_reader *result;
 
-  result = malloc(sizeof(*result));
+  result = labcomm_memory_alloc(memory, 0, sizeof(*result));
   if (result == NULL) {
     return NULL;
   } else {
-    result->reader.action_context = &result->action_context;
     result->action_context.next = NULL;
     result->action_context.action = &action;
     result->action_context.context = result;
+    result->reader.action_context = &result->action_context;
+    result->reader.memory = memory;
     result->fd = fd;
     result->close_fd_on_free = close_fd_on_free;
     return &result->reader;
diff --git a/lib/c/labcomm_fd_reader.h b/lib/c/labcomm_fd_reader.h
index 8f526fa..b04aa8e 100644
--- a/lib/c/labcomm_fd_reader.h
+++ b/lib/c/labcomm_fd_reader.h
@@ -1,9 +1,31 @@
+/*
+  labcomm_fd_reader.c -- a reader for unix style file-descriptors
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
 #ifndef _LABCOMM_FD_READER_H_
 #define _LABCOMM_FD_READER_H_
 
 #include "labcomm.h"
 
-struct labcomm_reader *labcomm_fd_reader_new(int fd, int close_fd_on_free);
+struct labcomm_reader *labcomm_fd_reader_new(struct labcomm_memory *memory,
+					     int fd, int close_fd_on_free);
 
 #endif
 
diff --git a/lib/c/labcomm_fd_writer.c b/lib/c/labcomm_fd_writer.c
index 476052c..d21e047 100644
--- a/lib/c/labcomm_fd_writer.c
+++ b/lib/c/labcomm_fd_writer.c
@@ -45,7 +45,7 @@ static int fd_alloc(struct labcomm_writer *w,
 		    char *version,
 		    labcomm_encoder_enqueue enqueue)
 {
-  w->data = malloc(BUFFER_SIZE);
+  w->data = labcomm_memory_alloc(w->memory, 0, BUFFER_SIZE);
   if (! w->data) {
     w->error = -ENOMEM;
     w->data_size = 0;
@@ -67,17 +67,19 @@ static int fd_alloc(struct labcomm_writer *w,
 static int fd_free(struct labcomm_writer *w, 
 		   struct labcomm_writer_action_context *action_context)
 {
-  struct labcomm_fd_writer *fd_context = action_context->context;
+  struct labcomm_fd_writer *fd_writer = action_context->context;
+  struct labcomm_memory *memory = w->memory;
 
-  free(w->data);
+  labcomm_memory_free(memory, 0, w->data);
   w->data = 0;
   w->data_size = 0;
   w->count = 0;
   w->pos = 0;
 
-  if (fd_context->close_fd_on_free) {
-    close(fd_context->fd);
+  if (fd_writer->close_fd_on_free) {
+    close(fd_writer->fd);
   }
+  labcomm_memory_free(memory, 0, fd_writer);
   return 0;
 }
 
@@ -117,35 +119,29 @@ static int fd_flush(struct labcomm_writer *w,
   return w->error;
 }
 
-static int fd_ioctl(struct labcomm_writer *w, 
-		    struct labcomm_writer_action_context *action_context, 
-		    int signature_index, struct labcomm_signature *signature, 
-		    uint32_t action, va_list args)
-{
-  return -ENOTSUP;
-}
-
 static const struct labcomm_writer_action action = {
   .alloc = fd_alloc,
   .free = fd_free,
   .start = fd_start,
   .end = fd_flush,
   .flush = fd_flush,
-  .ioctl = fd_ioctl
+  .ioctl = NULL
 };
 
-struct labcomm_writer *labcomm_fd_writer_new(int fd, int close_fd_on_free)
+struct labcomm_writer *labcomm_fd_writer_new(struct labcomm_memory *memory,
+					     int fd, int close_fd_on_free)
 {
   struct labcomm_fd_writer *result;
 
-  result = malloc(sizeof(*result));
+  result = labcomm_memory_alloc(memory, 0, sizeof(*result));
   if (result == NULL) {
     return NULL;
   } else {
-    result->writer.action_context = &result->action_context;
     result->action_context.next = NULL;
     result->action_context.action = &action;
     result->action_context.context = result;
+    result->writer.action_context = &result->action_context;
+    result->writer.memory = memory;
     result->fd = fd;
     result->close_fd_on_free = close_fd_on_free;
     return &result->writer;
diff --git a/lib/c/labcomm_fd_writer.h b/lib/c/labcomm_fd_writer.h
index e1c976a..e89b5e7 100644
--- a/lib/c/labcomm_fd_writer.h
+++ b/lib/c/labcomm_fd_writer.h
@@ -1,9 +1,31 @@
+/*
+  labcomm_fd_writer.c -- a writer for unix style file-descriptors
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
 #ifndef _LABCOMM_FD_WRITER_H_
 #define _LABCOMM_FD_WRITER_H_
 
 #include "labcomm.h"
 
-struct labcomm_writer *labcomm_fd_writer_new(int fd, int close_on_free);
+struct labcomm_writer *labcomm_fd_writer_new(struct labcomm_memory *memory,
+					     int fd, int close_on_free);
 
 #endif
 
diff --git a/lib/c/labcomm_memory.c b/lib/c/labcomm_memory.c
new file mode 100644
index 0000000..62bc9ac
--- /dev/null
+++ b/lib/c/labcomm_memory.c
@@ -0,0 +1,40 @@
+/*
+  labcomm_memory.c -- dynamic memory handlig dispatcher
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "labcomm_private.h"
+
+void *labcomm_memory_alloc(struct labcomm_memory *m, int lifetime, 
+			   size_t size) 
+{
+  return m->alloc(m, lifetime, size);
+}
+
+void *labcomm_memory_realloc(struct labcomm_memory *m, int lifetime, 
+			     void *ptr, size_t size) 
+{
+  return m->realloc(m, lifetime, ptr, size);
+}
+
+void labcomm_memory_free(struct labcomm_memory *m, int lifetime, 
+			 void *ptr)
+{
+  m->free(m, lifetime, ptr);
+}
diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h
index 8632dc0..a19ec2a 100644
--- a/lib/c/labcomm_private.h
+++ b/lib/c/labcomm_private.h
@@ -31,7 +31,7 @@
 #endif
 
 #include <stdint.h>
-#include <stdlib.h>
+//#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include "labcomm.h"
@@ -82,6 +82,19 @@ struct labcomm_lock_action {
 
 struct labcomm_lock {
   const struct labcomm_lock_action *action;
+  struct labcomm_memory *memory;
+  void *context;
+};
+
+/*
+ * Semi private dynamic memory declarations
+ */
+
+struct labcomm_memory {
+  void *(*alloc)(struct labcomm_memory *m, int lifetime, size_t size);
+  void *(*realloc)(struct labcomm_memory *m, int lifetime, 
+		   void *ptr, size_t size);
+  void (*free)(struct labcomm_memory *m, int lifetime, void *ptr);
   void *context;
 };
 
@@ -144,6 +157,9 @@ struct labcomm_reader_action_context {
 
 struct labcomm_reader {
   struct labcomm_reader_action_context *action_context;
+  struct labcomm_memory *memory;
+  /* The following fields are initialized by labcomm_decoder_new */
+  struct labcomm_decoder *decoder;
   unsigned char *data;
   int data_size;
   int count;
@@ -255,7 +271,7 @@ static inline char *labcomm_read_string(struct labcomm_reader *r)
   int length, i; 
   
   length = labcomm_read_packed32(r);
-  result = malloc(length + 1);
+  result = labcomm_memory_alloc(r->memory, 1, length + 1);
   for (i = 0 ; i < length ; i++) {
     if (r->pos >= r->count) {	
       labcomm_reader_fill(r, r->action_context);
@@ -318,6 +334,9 @@ struct labcomm_writer_action_context {
 
 struct labcomm_writer {
   struct labcomm_writer_action_context *action_context;
+  struct labcomm_memory *memory;
+  /* The following fields are initialized by labcomm_encoder_new */
+  struct labcomm_encoder *encoder;
   unsigned char *data;
   int data_size;
   int count;
@@ -461,18 +480,29 @@ static inline int labcomm_write_string(struct labcomm_writer *w, char *s)
   name.first = 0; name.last = 0; name.data = NULL;		\
   name.data = (kind *)name.data; /* typechecking no-op */
 
-#define LABCOMM_SIGNATURE_ARRAY_FREE(name, kind)		\
-  if (name.data) { free(name.data); }				\
+#define LABCOMM_SIGNATURE_ARRAY_FREE(memory, name, kind)	\
+  if (name.data) { labcomm_memory_free(memory, 0, name.data); }	\
   name.data = (kind *)NULL; /* typechecking */
 
-#define LABCOMM_SIGNATURE_ARRAY_REF(name, kind, index)			\
+void *labcomm_signature_array_ref(struct labcomm_memory * memory,
+				  int *first, int *last, void **data,
+				  int size, int index);
+/*
+ * NB: the pointer returned by LABCOMM_SIGNATURE_ARRAY_REF might be
+ *     rendered invalid by a subsequent call to LABCOMM_SIGNATURE_ARRAY_REF
+ *     on the same SIGNATURE_ARRAY, so make sure not to use the result if 
+ *     any other code might have made a call to LABCOMM_SIGNATURE_ARRAY_REF
+ *     on the same SIGNATURE_ARRAY.
+ */
+#define LABCOMM_SIGNATURE_ARRAY_REF(memory, name, kind, index)		\
   (name.data = (kind *)name.data, /* typechecking no-op */		\
-   (kind *)(labcomm_signature_array_ref(&name.first, &name.last,	\
+   (kind *)(labcomm_signature_array_ref(memory,				\
+					&name.first, &name.last,	\
 					(void **)&name.data,		\
 					sizeof(kind), index)))
 
-void *labcomm_signature_array_ref(int *first, int *last, void **data,
-				  int size, int index);
-
+#define LABCOMM_SIGNATURE_ARRAY_FOREACH(name, kind, var)		\
+  for (name.data = (kind *)name.data, /* typechecking no-op */		\
+       var = name.first ; var < name.last ; var++)
 
 #endif
diff --git a/lib/c/labcomm_pthread_mutex_lock.c b/lib/c/labcomm_pthread_mutex_lock.c
index 66c8ac3..548a3e6 100644
--- a/lib/c/labcomm_pthread_mutex_lock.c
+++ b/lib/c/labcomm_pthread_mutex_lock.c
@@ -5,6 +5,7 @@
 
 struct labcomm_pthread_mutex_lock {
   struct labcomm_lock lock;
+  
   pthread_mutex_t mutex;
   pthread_cond_t cond;
 };
@@ -12,10 +13,11 @@ struct labcomm_pthread_mutex_lock {
 int do_free(struct labcomm_lock *l)
 {
   struct labcomm_pthread_mutex_lock *lock = l->context;
-  
+  struct labcomm_memory *memory = l->memory; 
+ 
   pthread_cond_destroy(&lock->cond);
   pthread_mutex_destroy(&lock->mutex);
-  free(lock);
+  labcomm_memory_free(memory, 0, lock);
   return 0;
 }
 
@@ -80,12 +82,13 @@ static struct labcomm_lock_action action = {
   .notify = do_notify
 };
 
-struct labcomm_lock *labcomm_pthread_mutex_lock_new()
+struct labcomm_lock *labcomm_pthread_mutex_lock_new(
+  struct labcomm_memory *memory)
 {
   struct labcomm_lock *result = NULL;
   struct labcomm_pthread_mutex_lock *lock;
 
-  lock = malloc(sizeof(*lock));
+  lock = labcomm_memory_alloc(memory, 0, sizeof(*lock));
   if (lock == NULL) {
     goto out;
   }
@@ -95,6 +98,7 @@ struct labcomm_lock *labcomm_pthread_mutex_lock_new()
   if (pthread_cond_init(&lock->cond, NULL) != 0) {
     goto destroy_mutex;
   }
+  lock->lock.memory = memory;
   lock->lock.action = &action;
   lock->lock.context = lock;
   result = &lock->lock;
@@ -102,7 +106,7 @@ struct labcomm_lock *labcomm_pthread_mutex_lock_new()
 destroy_mutex:
   pthread_mutex_destroy(&lock->mutex);
 free_lock:
-  free(lock);
+  labcomm_memory_free(memory, 0, lock);
 out:
   return result;
 
diff --git a/lib/c/labcomm_pthread_mutex_lock.h b/lib/c/labcomm_pthread_mutex_lock.h
index d4ff9f7..e67b16a 100644
--- a/lib/c/labcomm_pthread_mutex_lock.h
+++ b/lib/c/labcomm_pthread_mutex_lock.h
@@ -1,8 +1,30 @@
+/*
+  labcomm_pthread_mutex_lock.h -- a labcomm_lock on top of pthread_mutex.
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
 #ifndef _LABCOMM_PTHREAD_MUTEX_LOCK_H_
 #define _LABCOMM_PTHREAD_MUTEX_LOCK_H_
 
 #include "labcomm.h"
 
-struct labcomm_lock *labcomm_pthread_mutex_lock_new();
+struct labcomm_lock *labcomm_pthread_mutex_lock_new(
+  struct labcomm_memory *memory);
 
 #endif
diff --git a/lib/c/test/test_labcomm_basic_type_encoding.c b/lib/c/test/test_labcomm_basic_type_encoding.c
index 9151b9b..b964c98 100644
--- a/lib/c/test/test_labcomm_basic_type_encoding.c
+++ b/lib/c/test/test_labcomm_basic_type_encoding.c
@@ -22,6 +22,7 @@
 #include <stdint.h>
 #include <inttypes.h>
 #include <string.h>
+#include <stdlib.h>
 #include "labcomm_private.h"
 
 static int line;
diff --git a/lib/c/test/test_labcomm_generated_encoding.c b/lib/c/test/test_labcomm_generated_encoding.c
index 32a5a99..bf81d0b 100644
--- a/lib/c/test/test_labcomm_generated_encoding.c
+++ b/lib/c/test/test_labcomm_generated_encoding.c
@@ -20,10 +20,10 @@
 */
 
 #include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include "labcomm_private.h"
-#include "labcomm_private.h"
 #include "test/gen/generated_encoding.h"
 
 #define IOCTL_WRITER_ASSERT_BYTES 4096
@@ -182,7 +182,8 @@ int main(void)
   generated_encoding_B B = 1;
 
   struct labcomm_encoder *encoder = labcomm_encoder_new(&buffer_writer, 
-							NULL);
+							NULL,
+							labcomm_default_memory);
 
   labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
   labcomm_encoder_register_generated_encoding_V(encoder);
diff --git a/test/nested.lc b/test/nested.lc
index 26f0ac8..58d45ee 100644
--- a/test/nested.lc
+++ b/test/nested.lc
@@ -21,3 +21,5 @@ sample struct_t struct_t_s;
 sample struct_array_t struct_array_t_s;
 sample struct_struct_t struct_struct_t_s;
 
+sample string string_array[_];
+sample struct { string s[_]; } string_struct_array;
diff --git a/test/relay_gen_c.py b/test/relay_gen_c.py
index 9e2a3a7..30a081a 100755
--- a/test/relay_gen_c.py
+++ b/test/relay_gen_c.py
@@ -50,8 +50,12 @@ if __name__ == '__main__':
       |  if (in < 0) { return 1; }
       |  out = open(argv[2], O_WRONLY);
       |  if (out < 0) { return 1; }
-      |  e = labcomm_encoder_new(labcomm_fd_writer_new(out, 1), NULL);
-      |  d = labcomm_decoder_new(labcomm_fd_reader_new(in, 1), NULL);
+      |  e = labcomm_encoder_new(labcomm_fd_writer_new(
+      |                              labcomm_default_memory, out, 1), 
+      |                           NULL, labcomm_default_memory);
+      |  d = labcomm_decoder_new(labcomm_fd_reader_new(
+      |                               labcomm_default_memory, in, 1), 
+      |                          NULL, labcomm_default_memory);
     """))
     for func,arg in sample:
         result.extend(split_match('^[^|]*\|(.*)$', """
-- 
GitLab