823603fe4a566abd1aa1d6bdf5fe40b881770729
[cdsspec-compiler.git] / benchmark / mpmc-queue / mpmc-queue.h
1 #include <stdatomic.h>
2 #include <unrelacy.h>
3 #include <common.h>
4
5 #include <spec_lib.h>
6 #include <stdlib.h>
7 #include <cdsannotate.h>
8 #include <specannotation.h>
9 #include <model_memory.h>
10 #include "common.h" 
11
12 /**
13         @Begin
14         @Class_begin
15         @End
16 */
17 template <typename t_element, size_t t_size>
18 struct mpmc_boundq_1_alt
19 {
20 private:
21
22         // elements should generally be cache-line-size padded :
23         t_element               m_array[t_size];
24
25         // rdwr counts the reads & writes that have started
26         atomic<unsigned int>    m_rdwr;
27         // "read" and "written" count the number completed
28         atomic<unsigned int>    m_read;
29         atomic<unsigned int>    m_written;
30
31 public:
32
33         mpmc_boundq_1_alt()
34         {
35         /**
36                 @Begin
37                         @Entry_point
38                         @End
39                 */
40                 m_rdwr = 0;
41                 m_read = 0;
42                 m_written = 0;
43         }
44         
45
46         /**
47                 @Begin
48                 @Options:
49                         LANG = CPP;
50                         CLASS = mpmc_boundq_1_alt;
51                 @Global_define:
52                 @DeclareVar:
53                         id_tag_t *tag;
54                 @InitVar:
55                         tag = NULL;
56         @Happens_before:
57                 Publish -> Fetch
58         @End
59         */
60
61         //-----------------------------------------------------
62
63         /**
64                 @Begin
65                 @Interface: Fetch
66                 @Commit_point_set: Fetch_Succ_Point | Fetch_Fail_Point
67                 @ID: (call_id_t) __RET__
68                 @End
69         */
70         t_element * read_fetch() {
71                 unsigned int rdwr = m_rdwr.load(mo_acquire);
72                 /**
73                         @Begin
74                         @Potential_commit_point_define: true
75                         @Label: Fetch_Potential_Point
76                         @End
77                 */
78                 unsigned int rd,wr;
79                 for(;;) {
80                         rd = (rdwr>>16) & 0xFFFF;
81                         wr = rdwr & 0xFFFF;
82
83                         if ( wr == rd ) { // empty
84                                 /**
85                                         @Begin
86                                         @Commit_point_define: true
87                                         @Potential_commit_point_label: Fetch_Potential_Point 
88                                         @Label: Fetch_Fail_Point
89                                         @End
90                                 */
91                                 return false;
92                         }
93                         
94                         bool succ = m_rdwr.compare_exchange_weak(rdwr,rdwr+(1<<16),mo_acq_rel);
95                         
96                         if (succ)
97                                 break;
98                         else
99                                 thrd_yield();
100                 }
101
102                 // (*1)
103                 rl::backoff bo;
104                 
105                 while ( true ) {
106                         if ((m_written.load(mo_acquire) & 0xFFFF) == wr) {
107                                 /**
108                                         @Begin
109                                         @Commit_point_define_check: true 
110                                         @Label: Fetch_Succ_Point
111                                         @End
112                                 */
113                                 break;
114                         }
115                         thrd_yield();
116                 }
117
118                 t_element * p = & ( m_array[ rd % t_size ] );
119                 
120                 return p;
121         }
122
123         void read_consume() {
124                 m_read.fetch_add(1,mo_release);
125         }
126
127         //-----------------------------------------------------
128
129         t_element * write_prepare() {
130                 unsigned int rdwr = m_rdwr.load(mo_acquire);
131                 unsigned int rd,wr;
132                 for(;;) {
133                         rd = (rdwr>>16) & 0xFFFF;
134                         wr = rdwr & 0xFFFF;
135
136                         if ( wr == ((rd + t_size)&0xFFFF) ) { // full
137                                 return NULL;
138                         }
139                         
140                         bool succ = m_rdwr.compare_exchange_weak(rdwr,(rd<<16) |
141                                 ((wr+1)&0xFFFF),mo_acq_rel);
142                         if (succ)
143                                 break;
144                         else
145                                 thrd_yield();
146                 }
147
148                 // (*1)
149                 rl::backoff bo;
150                 while ( (m_read.load(mo_acquire) & 0xFFFF) != rd ) {
151                         thrd_yield();
152                 }
153
154                 t_element * p = & ( m_array[ wr % t_size ] );
155
156                 return p;
157         }
158
159         /**
160                 @Begin
161                 @Interface: Publish 
162                 @Commit_point_set: Publish_Point
163                 @ID: (uint64_t) elem
164                 @End
165         */
166         void write_publish(t_element *elem)
167         {
168                 m_written.fetch_add(1,mo_release);
169                 /**
170                         @Begin
171                         @Commit_point_define_check: true
172                         @Label: Publish_Point
173                         @End
174                 */
175         }
176
177         //-----------------------------------------------------
178
179
180 };
181 /**
182         @Begin
183         @Class_end
184         @End
185 */