make LIST walking race/lock free
authorChristian Thaeter <ct@pipapo.org>
Fri, 9 Nov 2007 09:36:52 +0000 (10:36 +0100)
committerChristian Thaeter <ct@pipapo.org>
Fri, 9 Nov 2007 09:36:52 +0000 (10:36 +0100)
src/rxpd_connection_cmd.c

index 8c206bf..d1b1a25 100644 (file)
@@ -412,6 +412,15 @@ rxpd_connection_cmd_DUMP (struct rxpd_connection* self)
 }
 
 
+/*
+  build a temporary list to make psplay walking lockfree under pth
+*/
+struct list_record
+{
+  llist node;
+  char* name;
+};
+
 static psplay_delete_t
 walk_LIST (PSplay node, const enum psplay_order_e which, int level, void* data)
 {
@@ -420,8 +429,12 @@ walk_LIST (PSplay node, const enum psplay_order_e which, int level, void* data)
   struct rxpd_connection* conn = (struct rxpd_connection*) data;
 
   if (which == PSPLAY_INORDER)
-    rxpd_buffer_printf (&conn->out, "%s\n", file->node.key);
-
+    {
+      struct list_record* rec = rxpd_malloc (sizeof (struct list_record));
+      rec->name = rxpd_strdup (file->node.key);
+      llist_init (&rec->node);
+      llist_insert_tail (&conn->tmp_list, &rec->node);
+    }
   return PSPLAY_CONT;
 }
 
@@ -434,7 +447,18 @@ rxpd_connection_cmd_LIST (struct rxpd_connection* self)
   if (psplay_isempty_root (&base->files))
     rxpd_buffer_printf (&self->out, "#OK:\n");
   else
-    psplay_walk (&base->files, NULL, walk_LIST, 0, self);
+    {
+      psplay_walk (&base->files, NULL, walk_LIST, 0, self);
+
+      LLIST_WHILE_HEAD (&self->tmp_list, n)
+        {
+          struct list_record* rec = (struct list_record*)n;
+          rxpd_buffer_printf (&self->out, "%s\n", rec->name);
+          llist_unlink (n);
+          free (rec->name);
+          free (n);
+        }
+    }
 }
 
 void