Mercurial > hg > Members > Moririn
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