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