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

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since b1f3eaf was b1f3eaf, checked in by Stephen Siegel <siegel@…>, 12 years ago

Checking in new double-lock queue example which reveals some defects.

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

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