diff --git a/src/shared/queue.c b/src/shared/queue.c
index 9efb665..a5155e7 100644
--- a/src/shared/queue.c
+++ b/src/shared/queue.c
#include "src/shared/queue.h"
struct queue_entry {
+ int ref_count;
void *data;
struct queue_entry *next;
};
queue_unref(queue);
}
+static struct queue_entry *queue_entry_ref(struct queue_entry *entry)
+{
+ if (!entry)
+ return NULL;
+
+ __sync_fetch_and_add(&entry->ref_count, 1);
+
+ return entry;
+}
+
+static void queue_entry_unref(struct queue_entry *entry)
+{
+ if (__sync_sub_and_fetch(&entry->ref_count, 1))
+ return;
+
+ free(entry);
+}
+
+static struct queue_entry *queue_entry_new(void *data)
+{
+ struct queue_entry *entry;
+
+ entry = new0(struct queue_entry, 1);
+ if (!entry)
+ return NULL;
+
+ entry->data = data;
+
+ return queue_entry_ref(entry);
+}
+
bool queue_push_tail(struct queue *queue, void *data)
{
struct queue_entry *entry;
if (!queue)
return false;
- entry = new0(struct queue_entry, 1);
+ entry = queue_entry_new(data);
if (!entry)
return false;
- entry->data = data;
- entry->next = NULL;
-
if (queue->tail)
queue->tail->next = entry;
if (!queue)
return false;
- entry = new0(struct queue_entry, 1);
+ entry = queue_entry_new(data);
if (!entry)
return false;
- entry->data = data;
entry->next = queue->head;
queue->head = entry;
if (!qentry)
return false;
- new_entry = new0(struct queue_entry, 1);
+ new_entry = queue_entry_new(data);
if (!new_entry)
return false;
- new_entry->data = data;
new_entry->next = qentry->next;
if (!qentry->next)
data = entry->data;
- free(entry);
+ queue_entry_unref(entry);
queue->entries--;
return data;
return queue->tail->data;
}
-static bool queue_find_entry(struct queue *queue, const void *data)
-{
- struct queue_entry *entry;
-
- for (entry = queue->head; entry; entry = entry->next)
- if (entry == data)
- return true;
-
- return false;
-}
-
void queue_foreach(struct queue *queue, queue_foreach_func_t function,
void *user_data)
{
return;
queue_ref(queue);
- while (entry && queue->ref_count > 1) {
- struct queue_entry *tmp = entry;
+ while (entry && queue->head && queue->ref_count > 1) {
+ struct queue_entry *next;
- entry = tmp->next;
+ queue_entry_ref(entry);
- function(tmp->data, user_data);
+ function(entry->data, user_data);
- if (!queue_find_entry(queue, entry))
- break;
+ next = entry->next;
+
+ queue_entry_unref(entry);
+
+ entry = next;
}
queue_unref(queue);
}
if (!entry->next)
queue->tail = prev;
- free(entry);
+ queue_entry_unref(entry);
queue->entries--;
return true;
data = entry->data;
- free(entry);
+ queue_entry_unref(entry);
queue->entries--;
return data;
if (destroy)
destroy(tmp->data);
- free(tmp);
+ queue_entry_unref(tmp);
count++;
}
}