1 //#ifdef _FORTIFY_SOURCE
2 //#undef _FORTIFY_SOURCE
3 //#endif
4 //#define _FORTIFY_SOURCE 0
5 
6 #include "../../relacy/pthread.h"
7 
8 class queue_t
9 {
10 public:
queue_t()11     queue_t()
12     {
13         VAR(head) = 0;
14         VAR(tail) = 0;
15         pthread_mutex_init(&mtx, 0);
16         pthread_cond_init(&cv, 0);
17     }
18 
~queue_t()19     ~queue_t()
20     {
21         pthread_mutex_destroy(&mtx);
22         pthread_cond_destroy(&cv);
23     }
24 
enqueue(void * data)25     void enqueue(void* data)
26     {
27         node_t* n = new node_t;
28         n->VAR(next) = 0;
29         n->VAR(data) = data;
30         bool was_empty = false;
31 
32         pthread_mutex_lock(&mtx);
33         if (VAR(head) == 0)
34         {
35             was_empty = true;
36             VAR(head) = n;
37             VAR(tail) = n;
38         }
39         else
40         {
41             VAR(tail)->VAR(next) = n;
42             VAR(tail) = n;
43         }
44         pthread_mutex_unlock(&mtx);
45 
46         if (was_empty)
47             pthread_cond_broadcast(&cv);
48     }
49 
dequeue()50     void* dequeue()
51     {
52         node_t* n = 0;
53 
54         pthread_mutex_lock(&mtx);
55         while (VAR(head) == 0)
56             pthread_cond_wait(&cv, &mtx);
57         n = VAR(head);
58         if (n->VAR(next) == 0)
59             VAR(tail) = 0;
60         VAR(head) = n->VAR(next);
61         pthread_mutex_unlock(&mtx);
62 
63         void* data = n->VAR(data);
64         delete n;
65         return data;
66     }
67 
68 private:
69     struct node_t
70     {
71         VAR_T(node_t*) next;
72         VAR_T(void*) data;
73     };
74 
75     VAR_T(node_t*) head;
76     VAR_T(node_t*) tail;
77 
78     pthread_mutex_t mtx;
79     pthread_cond_t cv;
80 };
81 
enqueue_thread(void * ctx)82 void* enqueue_thread(void* ctx)
83 {
84     queue_t* q = static_cast<queue_t*>(ctx);
85     for (size_t i = 0; i != 4; i += 1)
86         q->enqueue((void*)(i + 1));
87     return 0;
88 }
89 
dequeue_thread(void * ctx)90 void* dequeue_thread(void* ctx)
91 {
92     queue_t* q = static_cast<queue_t*>(ctx);
93     for (size_t i = 0; i != 4; i += 1)
94     {
95         void* data = q->dequeue();
96         assert((int)(uintptr_t)data >= 1 && (int)(uintptr_t)data <= 4);
97     }
98     return 0;
99 }
100 
queue_test()101 void queue_test()
102 {
103     queue_t q;
104 
105     pthread_t th [4];
106     for (size_t i = 0; i != 2; i += 1)
107         pthread_create(&th[i], 0, enqueue_thread, &q);
108     for (size_t i = 2; i != 4; i += 1)
109         pthread_create(&th[i], 0, dequeue_thread, &q);
110 
111     void* res = 0;
112     for (size_t i = 0; i != 4; i += 1)
113         pthread_join(th[i], &res);
114 }
115 
main()116 int main()
117 {
118     rl::test_params p;
119     p.iteration_count = 100000;
120     //p.search_type = rl::sched_full;
121     //p.context_bound = 5;
122     //p.execution_depth_limit = 200;
123     rl::execute<queue_test, 4>(p);
124 }
125