source: CIVL/examples/concurrency/dlqueue.cvl@ bb03188

main test-branch
Last change on this file since bb03188 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 2.4 KB
RevLine 
[9428054]1// https://www.cs.rochester.edu/research/synchronization/pseudocode/queues.html
2
[e6b02c8]3#include <civlc.cvh>
[b1f3eaf]4#include <stdbool.h>
5#include <stdlib.h>
6#include <assert.h>
7
8typedef int lock_t;
9#define FREE 0
10#define lock(l) $when (l==0) l=1;
11#define unlock(l) l=0;
12
13typedef struct node_t {
14 int value;
15 struct node_t *next;
16} node_t;
17
18typedef struct queue_t {
19 node_t *Head;
20 node_t *Tail;
21 lock_t H_lock;
22 lock_t T_lock;
23} queue_t;
24
25void initialize(queue_t *Q) {
26 node_t *node = (node_t*)malloc(sizeof(node_t));
27
28 node->next = NULL; // Make it the only node in the linked list
29 Q->Head = Q->Tail = node; // Both Head and Tail point to it
30 Q->H_lock = Q->T_lock = FREE; // Locks are initially free
31}
32
33void enqueue(queue_t *Q, int value) {
[88c4a13]34 node_t *node = (node_t*)malloc(sizeof(node_t)); // in root scope
[8a8290e]35
[b1f3eaf]36 node->value = value; // Copy enqueued value into node
37 node->next = NULL; // Set next pointer of node to NULL
38 lock(Q->T_lock); // Acquire T_lock in order to access Tail
39 Q->Tail->next = node; // Link node at the end of the linked list
40 Q->Tail = node; // Swing Tail to node
41 unlock(Q->T_lock); // Release T_lock
42}
43
44_Bool dequeue(queue_t *Q, int *pvalue) {
45 node_t *node, *new_head;
46
47 lock(Q->H_lock); // Acquire H_lock in order to access Head
48 node = Q->Head; // Read Head
49 new_head = node->next; // Read next pointer
50 if (new_head == NULL) { // Is queue empty?
51 unlock(Q->H_lock); // Release H_lock before return
52 return false; // Queue was empty
53 }
54 *pvalue = new_head->value; // Queue not empty. Read value before release
55 Q->Head = new_head; // Swing Head to next node
56 unlock(Q->H_lock); // Release H_lock
57 free(node); // Free node
58 return true; // Queue was not empty, dequeue succeeded
59}
60
61void test1() {
62 queue_t queue;
63 int x;
64
65 initialize(&queue);
66 enqueue(&queue, 99);
67 dequeue(&queue, &x);
[5425448]68 free(queue.Head);
[b1f3eaf]69 assert(x==99);
70}
71
72void test2() {
73 queue_t q;
74 $proc t0, t1;
75 void thread(int val) { enqueue(&q, val); }
76 int x, y;
77 _Bool result;
[79740cc]78
[b1f3eaf]79 initialize(&q);
80 t0 = $spawn thread(6);
81 t1 = $spawn thread(7);
82 $wait(t0);
83 $wait(t1);
84 result = dequeue(&q, &x);
[b51463d]85 assert(result);
[b1f3eaf]86 result = dequeue(&q, &y);
[8a8290e]87 assert(result);
[b1f3eaf]88 assert ((x==6 && y==7) || (x==7 && y==6));
[5425448]89 free(q.Head);
[b1f3eaf]90}
91
92void main() {
93 test2();
94}
Note: See TracBrowser for help on using the repository browser.