source: CIVL/examples/compare/queue/queue_non_blocking.c@ a389857

main test-branch
Last change on this file since a389857 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: 3.9 KB
RevLine 
[57732bb5]1#ifndef _QUEUE_NON_BLOCKING_
2#define _QUEUE_NON_BLOCKING_
3
4#include <stdbool.h>
5#include <stdlib.h>
6#include "queue.h"
7
8typedef struct pointer_t pointer_t;
[94df241]9//typedef struct queue_t queue_t;
10typedef struct node_t node_t;
11typedef struct freeList freeList;
[57732bb5]12
[94df241]13struct node_t;
[57732bb5]14
15struct pointer_t {
16 node_t* ptr;
17 int count;
18};
19
[94df241]20struct node_t {
21 int value;
22 pointer_t next;
23};
24
[57732bb5]25struct queue_t {
26 pointer_t Head;
27 pointer_t Tail;
28};
29
[94df241]30struct freeList{
31 node_t *node;
32 freeList *next;
33};
34
35freeList* list; //declare global list
[57732bb5]36
[94df241]37void initialize(queue_t *Q) {
38 node_t *node = (node_t*)malloc(sizeof(node_t)); // Allocate a free node
39
40 list=(freeList*)malloc(sizeof(freeList));
41 list->node = NULL; //initialize list
42 list->next = NULL;
43 node->next.ptr = NULL; // Make it the only node in the linked list
44 node->next.count = 0; // Initialize counter
45 Q->Head.ptr = Q->Tail.ptr = node; // Both Head and Tail point to it
[57732bb5]46}
47
[94df241]48void setFree(node_t* freeNode){ //put the node to a special-use free list and not the partner to malloc
[57732bb5]49 $atomic{
[94df241]50 freeList *temp = (freeList*)malloc(sizeof(freeList));
51
52 temp->node = freeNode;
53 temp->next = list->next;
54 list->next = temp;
55 }
56}
57
58void deallocate(freeList *list){ // partner to malloc
59 freeList *q;
60
61 while(list != NULL){
62 q = list->next;
63 free(list->node);
64 free(list);
65 list = q;
[57732bb5]66 }
67}
68
[94df241]69_Bool equal(pointer_t p1, pointer_t p2){ //define equal() method to compare two pointers
70 return (p1.ptr == p2.ptr) && (p1.count == p2.count);
71}
[57732bb5]72
[94df241]73_Bool CAS(pointer_t *dest, pointer_t oldval, pointer_t newval){ //define CAS() method
74 $atomic {
75 if (equal(*dest, oldval)) {
76 *dest = newval;
77 return true;
78 }
79 return false;
80 }
[57732bb5]81}
82
[94df241]83void enqueue(queue_t *Q, int value) {
[57732bb5]84 pointer_t tail, next;
[94df241]85 node_t *node = (node_t*)malloc(sizeof(node_t)); // Allocate a new node from the free list
86
87 node->value = value; // Copy enqueued value into node
88 node->next.ptr = NULL; // Set next pointer of node to NULL
89
90 while (true){ // Keep trying until Enqueue is done
91 tail = Q->Tail; // Read Tail.ptr and Tail.count together
92 next = tail.ptr->next; // Read next ptr and count fields together
93 if (equal(tail, Q->Tail)) // Are tail and next consistent?
[57732bb5]94 // Was Tail pointing to the last node?
[94df241]95 if (next.ptr == NULL){
[57732bb5]96 // Try to link node at the end of the linked list
[94df241]97 if (CAS(&tail.ptr->next, next, (pointer_t){ node, next.count + 1 }))
98 break; // **Enqueue is done. Exit loop
99 }
100 else{ // Tail was not pointing to the last node
[57732bb5]101 // Try to swing Tail to the next node
[94df241]102 CAS(&Q->Tail, tail, (pointer_t){ next.ptr, tail.count + 1 });
[57732bb5]103 }
104 }
105 // Enqueue is done. Try to swing Tail to the inserted node
[94df241]106 CAS(&Q->Tail, tail, (pointer_t){ node, tail.count + 1 });
[57732bb5]107}
108
[94df241]109_Bool dequeue(queue_t *Q, int *pvalue) { //boolean type
[57732bb5]110 pointer_t head, tail, next;
[94df241]111
112 while (true){ // Keep trying until Dequeue is done
113 head = Q->Head; // Read Head
114 tail = Q->Tail; // Read Tail
115 next = head.ptr->next; // Read Head.ptr->next
116 if (equal(head, Q->Head)) // Are head, tail, and next consistent?
117 if (head.ptr == tail.ptr){ // Is queue empty or Tail falling behind?
118 if (next.ptr == NULL) // Is queue empty?
119 return false; // Queue is empty, couldn't dequeue
[57732bb5]120 // Tail is falling behind. Try to advance it
[94df241]121 CAS(&Q->Tail, tail, (pointer_t){ next.ptr, tail.count + 1 });
122 }
123 else{
[57732bb5]124 // Read value before CAS
125 // Otherwise, another dequeue might free the next node
126 *pvalue = next.ptr->value;
[94df241]127 if (CAS(&Q->Head, head, (pointer_t){ next.ptr, head.count + 1 }))
128 break;// **Dequeue is done. Exit loop
[57732bb5]129 }
130 }
[94df241]131 setFree(head.ptr); // It is safe now to "free" the old node
132 return true; // Queue was not empty, dequeue succeeded
[57732bb5]133}
134
135void freequeue(queue_t q){
[94df241]136 deallocate(list);
137 free(q.Head.ptr);
[57732bb5]138}
139
140#endif
Note: See TracBrowser for help on using the repository browser.