aboutsummaryrefslogtreecommitdiff
path: root/src/rt/sync/interrupt_transparent_queue.cpp
diff options
context:
space:
mode:
authorMichael Bebenita <[email protected]>2010-08-24 21:06:56 -0700
committerMichael Bebenita <[email protected]>2010-08-24 21:07:14 -0700
commit64ff82ecf98ceb4725f0f51c73e23d1efc2160bc (patch)
tree6a6ae7452066716947c4d262eb72041a6a11cb95 /src/rt/sync/interrupt_transparent_queue.cpp
parentComment on env var required for std.dbg to do any logging. (diff)
downloadrust-64ff82ecf98ceb4725f0f51c73e23d1efc2160bc.tar.xz
rust-64ff82ecf98ceb4725f0f51c73e23d1efc2160bc.zip
Implemented an lock free queue based on this paper http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf, the "lock free queue" we had before wasn't lock free at all.
Diffstat (limited to 'src/rt/sync/interrupt_transparent_queue.cpp')
-rw-r--r--src/rt/sync/interrupt_transparent_queue.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/src/rt/sync/interrupt_transparent_queue.cpp b/src/rt/sync/interrupt_transparent_queue.cpp
new file mode 100644
index 00000000..064b25f1
--- /dev/null
+++ b/src/rt/sync/interrupt_transparent_queue.cpp
@@ -0,0 +1,56 @@
+/*
+ * Interrupt transparent queue, Schoen et. al, "On Interrupt-Transparent
+ * Synchronization in an Embedded Object-Oriented Operating System", 2000.
+ * enqueue() is allowed to interrupt enqueue() and dequeue(), however,
+ * dequeue() is not allowed to interrupt itself.
+ */
+
+#include "../globals.h"
+#include "interrupt_transparent_queue.h"
+
+interrupt_transparent_queue_node::interrupt_transparent_queue_node() :
+ next(NULL) {
+
+}
+
+interrupt_transparent_queue::interrupt_transparent_queue() : _tail(this) {
+
+}
+
+void
+interrupt_transparent_queue::enqueue(interrupt_transparent_queue_node *item) {
+ lock.lock();
+ item->next = (interrupt_transparent_queue_node *) NULL;
+ interrupt_transparent_queue_node *last = _tail;
+ _tail = item;
+ while (last->next) {
+ last = last->next;
+ }
+ last->next = item;
+ lock.unlock();
+}
+
+interrupt_transparent_queue_node *
+interrupt_transparent_queue::dequeue() {
+ lock.lock();
+ interrupt_transparent_queue_node *item = next;
+ if (item && !(next = item->next)) {
+ _tail = (interrupt_transparent_queue_node *) this;
+ if (item->next) {
+ interrupt_transparent_queue_node *lost = item->next;
+ interrupt_transparent_queue_node *help;
+ do {
+ help = lost->next;
+ enqueue(lost);
+ } while ((lost = help) !=
+ (interrupt_transparent_queue_node *) NULL);
+ }
+ }
+ lock.unlock();
+ return item;
+}
+
+bool
+interrupt_transparent_queue::is_empty() {
+ return next == NULL;
+}