changeset 361:a2c01ab30ea2

Add synchronized queue of paper
author Tatsuki IHA <innparusu@cr.ie.u-ryukyu.ac.jp>
date Wed, 28 Jun 2017 05:48:39 +0900
parents 45afe5d70956
children d93dceb84c75
files src/parallel_execution/SynchronizedQueue.cbc src/parallel_execution/context.h src/parallel_execution/generate_stub.pl
diffstat 3 files changed, 37 insertions(+), 120 deletions(-) [+]
line wrap: on
line diff
--- a/src/parallel_execution/SynchronizedQueue.cbc	Thu Jun 22 16:20:56 2017 +0900
+++ b/src/parallel_execution/SynchronizedQueue.cbc	Wed Jun 28 05:48:39 2017 +0900
@@ -2,12 +2,16 @@
 
 #include <stdio.h>
 
+/* 
+ * Nonnon-blocking queue of Paper: Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms(https://www.research.ibm.com/people/m/michael/podc-1996.pdf).
+ */
+
 Queue* createSynchronizedQueue(struct Context* context) {
     struct Queue* queue = new Queue();
     struct SynchronizedQueue* synchronizedQueue = new SynchronizedQueue();
-    synchronizedQueue->top  = NULL;
-    synchronizedQueue->last = NULL;
-    synchronizedQueue ->queueCount = createSemaphoreImpl(context, 0);
+    synchronizedQueue->top = new Element();
+    synchronizedQueue->top->next = NULL;
+    synchronizedQueue->last = synchronizedQueue->top;
     queue->queue = (union Data*)synchronizedQueue;
     queue->take  = C_takeSynchronizedQueue;
     queue->put  = C_putSynchronizedQueue;
@@ -27,45 +31,42 @@
 
 __code putSynchronizedQueue(struct SynchronizedQueue* queue, union Data* data, __code next(...)) {
     Element* element = new Element();
+    element->data = data;
     element->next = NULL;
-    element->data = data;
-    if (queue->top) {
-        Element* last = queue->last;
-        if (__sync_bool_compare_and_swap(&queue->last, last, element)) {
-            last->next = element;
-        } else {
-            goto meta(context, C_putSynchronizedQueue);
+    Element* last = queue->last;
+    Element* nextElement = last->next;
+    if (last != queue->last) {
+        goto meta(context, C_putSynchronizedQueue);
+    }
+    if (nextElement == NULL) {
+        if (__sync_bool_compare_and_swap(&last->next, nextElement, element)) {
+            __sync_bool_compare_and_swap(&queue->last, last, element);
+            goto next(...);
         }
     } else {
-        if (__sync_bool_compare_and_swap(&queue->top, NULL, element)) {
-            queue->last = element;
-        } else {
-            goto meta(context, C_putSynchronizedQueue);
-        }
+        __sync_bool_compare_and_swap(&queue->last, last, nextElement);
     }
-    goto meta(context, C_putSynchronizedQueue1);
+    goto meta(context, C_putSynchronizedQueue);
 }
 
-__code putSynchronizedQueue1(struct SynchronizedQueue* queue, struct Semaphore* semaphore, __code next(...)) {
-    semaphore->semaphore = (union Data*)queue->queueCount;
-    semaphore->next = next;
-    goto meta(context, queue->queueCount->v);
-}
-
-__code takeSynchronizedQueue(struct SynchronizedQueue* queue, struct Semaphore* semaphore) {
-    semaphore->semaphore = (union Data*)queue->queueCount;
-    semaphore->next = C_takeSynchronizedQueue1;
-    goto meta(context, queue->queueCount->p);
-}
-
-__code takeSynchronizedQueue1(struct SynchronizedQueue* queue, __code next(union Data* data, ...)) {
+__code takeSynchronizedQueue(struct SynchronizedQueue* queue, __code next(union Data* data, ...)) {
     struct Element* top = queue->top;
-    if (__sync_bool_compare_and_swap(&queue->top, top, top->next)) {
-        data = top->data;
-    } else {
+    struct Element* last = queue->last;
+    struct Element* nextElement = top->next;
+    if (top != queue->top) {
         goto meta(context, C_takeSynchronizedQueue);
     }
-    goto next(data, ...);
+    if (top == last) {
+        if (nextElement != NULL) {
+          __sync_bool_compare_and_swap(&queue->last, last, nextElement);
+        }
+    } else {
+        if (__sync_bool_compare_and_swap(&queue->top, top, nextElement)) {
+            data = nextElement->data;
+            goto next(data, ...);
+        }
+    }
+    goto meta(context, C_takeSynchronizedQueue);
 }
 
 __code isEmptySynchronizedQueue(struct SynchronizedQueue* queue, __code next(...), __code whenEmpty(...)) {
--- a/src/parallel_execution/context.h	Thu Jun 22 16:20:56 2017 +0900
+++ b/src/parallel_execution/context.h	Wed Jun 28 05:48:39 2017 +0900
@@ -194,7 +194,6 @@
     struct SynchronizedQueue {
         struct Element* top;
         struct Element* last;
-        struct Semaphore* queueCount;
     } SynchronizedQueue;
     // Stack Interface
     struct Stack {
--- a/src/parallel_execution/generate_stub.pl	Thu Jun 22 16:20:56 2017 +0900
+++ b/src/parallel_execution/generate_stub.pl	Wed Jun 28 05:48:39 2017 +0900
@@ -41,54 +41,18 @@
 my $implementation;
 my $interface;
 
-# interface definision
-#
-# typedef struct Stack<Type, Impl>{
-#         Type* stack;
-#         Type* data;
-#         Type* data1;
-#         __code whenEmpty(...);
-#         __code clear(Impl* stack,__code next(...));
-#         __code push(Impl* stack,Type* data, __code next(...));
-#         __code pop(Impl* stack, __code next(Type*, ...));
-#         __code pop2(Impl* stack, Type** data, Type** data1, __code next(Type**, Type**, ...));
-#         __code isEmpty(Impl* stack, __code next(...), __code whenEmpty(...));
-#         __code get(Impl* stack, Type** data, __code next(...));
-#         __code get2(Impl* stack,..., __code next(...));
-#         __code next(...);
-# } Stack;
-#
-# calling example
-#
-# goto nodeStack->push((union Data*)node, stackTest3);
-#
-# generated meta level code
-#
-# Gearef(context, Stack)->stack = nodeStack->stack;
-# Gearef(context, Stack)->data = (union Data*)node;
-# Gearef(context, Stack)->next = C_stackTest3;
-# goto meta(context, nodeStack->push);
-
 sub getDataGear {
     my ($filename) = @_;
     my ($codeGearName, $name, $inTypedef);
     open my $fd,"<",$filename or die("can't open $filename $!");
     while (<$fd>) {
         if (! $inTypedef) {
-            if (/^typedef struct (\w+)\s*<(.*)>/) {
+            if (/^typedef struct (\w+)/) {
                 $inTypedef = 1;
                 $name = $1;
                 $dataGear{$name} = $_;
                 $var{$name} = {};
                 $code{$name} = {};
-                $generic{$name} = \split(/,/,$2);
-            } elsif (/^typedef struct (\w+)/) {
-                $inTypedef = 1;
-                $name = $1;
-                $dataGear{$name} = $_;
-                $var{$name} = {};
-                $code{$name} = {};
-                $generic{$name} = [];
             } elsif (/^(\w+)(\*)+ create(\w+)\(/) {
                 if (defined $interface) {
                    die "duplicate interface $interface\n"; 
@@ -110,29 +74,8 @@
                 $ttype = $2;
             }
             $var{$name}->{$tname} = $ttype;
-        } elsif (/^\_\_code (\w+)\((.*)\)(.*)/) {
-            my $args = $2;
-            my $method = $1;
-            $code{$name}->{$method} = [];
-            while($args) {
-                if ($args =~ s/(^\s*,\s*)//) {
-                }
-                # continuation case
-                if ($args =~ s/^(\s)*\_\_code\s+(\w+)\(([^)]*)\)//) {
-                    my $next = $2;
-                    my @args = split(/,/,$3);
-                    push(@{$code{$name}->{$method}},$next); 
-                } elsif ($args =~ s/^(struct|union) (\w+)(\*)+\s(\w+)//) {
-                    my $structType = $1;
-                    my $typeName = $2;
-                    my $varName = $4;
-                    my $typeField = lcfirst($typeName);
-                    push(@{$code{$name}->{$method}},$varName); 
-                } elsif ($args =~ s/(.*,)//) {
-                } else {
-                    last;
-                }
-            }
+	} elsif (/\_\_code (\w+)\(/) {
+            $code{$name}->{$1} = 1;
         }
         if (/^}/) {
             $inTypedef = 0;
@@ -156,7 +99,6 @@
         return 0 if ( $n eq $varname1);
     }
     push @{$dataGearVar{$codeGearName}}, $varname1;
-    push @{$dataGearVarType{$codeGearName}}, $typeName;
     if ($typeName eq $implementation) {
         # get implementation
         $dataGearName{$codeGearName} .= "\t$typeName* $varName = ($typeName*)GearImpl(context, $interface, $varName);\n";
@@ -311,31 +253,6 @@
                     print $fd $outputVar{$codeGearName};
                 }
                 next;
-            } elsif (/^(.*)goto (\w+)\-\>(\w+)\((.*)\);/) {
-                # handling goto statement  
-                # convert it to the meta call form with two arugments, that is context and enum Code
-                my $prev = $1;
-                my $next = $2;
-                my $method = $3;
-                my @args = split(/,/,$4);
-                my @types = @$dataGearVarType;
-                my $ntype;
-                for my $v (@$dataGearVar) {
-                    my $t = shift @types;
-                    if ($v eq $next) {
-                        $ntype = $t;
-                    }
-                }
-                print $fd "\tGearef(context, $ntype)->$next = $next->$next;\n";
-                # Put interface argument 
-                my $prot = $code->{$method};
-                for my $arg (@args) {
-                    my $p = shift @$prot;
-                    next if ($p eq $arg);
-                    print $fd "\tGearef(context, $ntype)->$p = $arg;\n";
-                }
-                print $fd "${prev}goto meta(context, $next->$next->$ntype.$method);\n";
-                next;
             } elsif (/^(.*)goto (\w+)\((.*)\);/) {
                 # handling goto statement  
                 # convert it to the meta call form with two arugments, that is context and enum Code