BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / 7a0d3efda0953d2296a36652babef51441b5ef20

// Related

Nucleus

Barry Doubly-linked object lists and copying 7a0d3ef (3 years, 3 months ago)
diff --git a/include/nucleus/object.h b/include/nucleus/object.h
index 63ac2ac..7f9554c 100644
--- a/include/nucleus/object.h
+++ b/include/nucleus/object.h
@@ -10,9 +10,9 @@ typedef struct ObjectType ObjectType;
 typedef struct Object Object;
 typedef struct ObjectList ObjectList;
 
-typedef struct Task Task; /* Just a pointer, no need for full definition */
+typedef struct Task Task;
 
-typedef int (*callback_t)(void *object, void *data);
+typedef int (*iterate_callback_t)(void *object, void *data);
 
 /* Spinlock */
 struct Spinlock {
@@ -26,7 +26,6 @@ struct Spinlock {
 
 /* Object Type */
 struct ObjectType {
-	unsigned int count;
 	refcount_t usage;
 	size_t size;
 	ObjectList *objects;
@@ -34,6 +33,7 @@ struct ObjectType {
 	void (*free)(Object *);
 	void (*new)(Object *);
 	void (*delete)(Object *);
+	void (*copy)(Object *, Object *);
 };
 
 /* Object */
@@ -46,6 +46,7 @@ struct Object {
 void *get(void *addr);
 void put(void *addr);
 void *new(ObjectType *type);
+void *copy(void *addr);
 void lock(void *addr);
 void unlock(void *addr);
 
@@ -56,6 +57,7 @@ void remove(ObjectList *list, void *addr);
 void *pop_from_start(ObjectList *list);
 void *pop_from_end(ObjectList *list);
 size_t count(ObjectList *list);
-void iterate(ObjectList *list, callback_t callback, void *data);
+void iterate(ObjectList *list, iterate_callback_t callback, void *data);
+ObjectList *copy_list(ObjectList *list);
 
 #endif
diff --git a/object/list.c b/object/list.c
index 3e9b96b..8581330 100644
--- a/object/list.c
+++ b/object/list.c
@@ -11,7 +11,7 @@
 
 /* Structure for a List Entry */
 struct ListEntry {
-	struct ListEntry *next;
+	struct ListEntry *prev, *next;
 	Object *obj;
 };
 /* Structure for an Object List */
@@ -58,6 +58,7 @@ add(ObjectList *list, void *addr)
 		list->start = entry;
 	else
 		list->end->next = entry;
+	entry->prev = list->end;
 	list->end = entry;
 	entry->obj = get(obj);
 	list->entries++;
@@ -75,30 +76,32 @@ remove(ObjectList *list, void *addr)
 		return;
 	acquire(&list->lock);
 
-	/* Start of list */
-	struct ListEntry *entry, *prev = NULL;
-	if (list->start->obj == obj) {
-		entry = list->start;
-		list->start = entry->next;
-		goto found;
+	/* Search for object */
+	struct ListEntry *entry;
+	for (entry = list->start;
+	     entry && entry->obj != obj;
+	     entry = entry->next);
+	if (!entry) {
+		release(&list->lock);
+		return;
 	}
 
-	/* Search for object */
-	for (prev = list->start; prev->next; prev = prev->next)
-		if (prev->next->obj == obj)
-			break;
-	if (!prev->next)
-		goto end;
-	entry = prev->next;
-	prev->next = entry->next;
-
-found:
-	if (list->end->obj == obj)
-		list->end = prev;
+	/* Unlink list */
+	if (list->start == entry)
+		list->start = entry->next;
+	if (list->end == entry)
+		list->end == entry->prev;
+
+	/* Unlink neighbours */
+	if (entry->prev)
+		entry->prev->next = entry->next;
+	if (entry->next)
+		entry->next->prev = entry->prev;
+
+	/* Release resources */
 	put(obj);
 	list->entries--;
 	kfree(entry);
-end:
 	release(&list->lock);
 }
 
@@ -137,7 +140,7 @@ count(ObjectList *list)
 
 /* Iterate a List with a callback */
 void
-iterate(ObjectList *list, callback_t callback, void *data)
+iterate(ObjectList *list, iterate_callback_t callback, void *data)
 {
 	acquire(&list->lock);
 	struct ListEntry *entry;
@@ -146,3 +149,16 @@ iterate(ObjectList *list, callback_t callback, void *data)
 			break;
 	release(&list->lock);
 }
+
+/* Copy list */
+ObjectList *
+copy_list(ObjectList *list)
+{
+	ObjectList *newlist = create_list(list->type);
+	acquire(&list->lock);
+	struct ListEntry *entry;
+	for (entry = list->start; entry; entry = entry->next)
+		add(newlist, entry->obj);
+	release(&list->lock);
+	return newlist;
+}
diff --git a/object/manager.c b/object/manager.c
index c50d45d..74b833d 100644
--- a/object/manager.c
+++ b/object/manager.c
@@ -32,7 +32,6 @@ put(void *addr)
 	__atomic_sub_fetch(&obj->type->usage, 1, __ATOMIC_RELAXED);
 	if (__atomic_sub_fetch(&obj->usage, 1, __ATOMIC_RELAXED))
 		return;
-	__atomic_sub_fetch(&obj->type->count, 1, __ATOMIC_RELAXED);
 	if (obj->type->delete)
 		obj->type->delete(obj);
 	remove(obj->type->objects, obj);
@@ -47,19 +46,32 @@ void *
 new(ObjectType *type)
 {
 	Object *obj;
-	if (type->alloc)
+	if (type->alloc && type->free)
 		obj = type->alloc();
 	else
 		obj = kmalloc(type->size);
+	init_lock(&obj->lock);
+	obj->type = type;
 	if (type->new)
 		type->new(obj);
 	if (!type->objects)
 		type->objects = create_list(type);
 	add(type->objects, obj);
-	init_lock(&obj->lock);
-	obj->type = type;
-	__atomic_add_fetch(&type->count, 1, __ATOMIC_RELAXED);
-	return get(obj);
+	/* No need to get() since it's in the global list */
+	return obj;
+}
+
+/* Copy an instance of an object */
+void *
+copy(void *addr)
+{
+	Object *parent = addr;
+	Object *child = NULL;
+	if (parent->type->copy) {
+		child = new(parent->type);
+		parent->type->copy(parent, child);
+	}
+	return child;
 }
 
 /* Lock an object */