transaction_test.cpp
1 /*
2  * transaction_test.cpp
3  *
4  * Test code of software transactional memory, for simultaneous transaction on tree-structure objects.
5  */
6 
7 #include "support.h"
8 
9 #include <stdint.h>
10 #include <thread>
11 
12 #include "transaction.h"
13 
14 #include "xthread.cpp"
15 
16 atomic<int> objcnt = 0; //# of living objects.
17 atomic<long> total = 0; //The sum. of payloads.
18 
19 //#define TRANSACTIONAL_STRICT_assert
20 
21 class LongNode;
24 
25 class LongNode : public Transactional::Node<LongNode> {
26 public:
27  LongNode() : Transactional::Node<LongNode>() {
28  ++objcnt;
29  // trans(*this) = 0;
30  }
31  virtual ~LongNode() {
32  --objcnt;
33  }
34 
35  //! Data holder.
36  struct Payload : public Transactional::Node<LongNode>::Payload {
37  Payload() : Transactional::Node<LongNode>::Payload(), m_x(0) {}
38  Payload(const Payload &x) : Transactional::Node<LongNode>::Payload(x), m_x(x.m_x) {
39  total += m_x;
40  }
41  virtual ~Payload() {
42  total -= m_x;
43  }
44  operator long() const {return m_x;}
45  Payload &operator=(const long &x) {
46  total += x - m_x;
47  m_x = x;
48  return *this;
49  }
50  Payload &operator+=(const long &x) {
51  total += x;
52  m_x += x;
53  return *this;
54  }
55  private:
56  long m_x;
57  };
58 };
59 
60 #define trans(node) for(Transaction \
61  implicit_tr(node, false); !implicit_tr.isModified() || !implicit_tr.commitOrNext(); ) implicit_tr[node]
62 
63 template <class T>
64 typename std::enable_if<std::is_base_of<LongNode, T>::value,
65  const typename Transactional::SingleSnapshot<LongNode, T> >::type
66  operator*(T &node) {
68 }
69 
70 #include "transaction_impl.h"
71 template class Transactional::Node<LongNode>;
72 
73 //! Shared objects.
74 shared_ptr<LongNode> gn1, gn2, gn3, gn4;
75 
76 void
77 start_routine(void) {
78  printf("start\n");
79  for(int i = 0; i < 2500; i++) {
80 
81  gn1->iterate_commit([=](Transaction &tr1){
82  const Snapshot &ctr1(tr1); // For reading.
83  tr1[gn1] = ctr1[gn1] + 1;
84  tr1[gn3] = ctr1[gn3] + 1;
85  Snapshot str1(tr1);
86  tr1[gn1] = str1[gn1] - 1;
87  tr1[gn2] = str1[gn2] + 1;
88  });
89  {
90  Snapshot shot(*gn1);
91  assert(shot[*gn2] <= shot[*gn3]);
92  }
93  trans(*gn3) += 1;
94  gn4->iterate_commit([=](Transaction &tr1){
95  tr1[gn4] = tr1[gn4] + 1;
96  tr1[gn4] = tr1[gn4] - 1;
97  });
98  {
99  Snapshot shot(*gn2);
100  assert(shot[*gn2] <= shot[*gn3]);
101  }
102  gn2->iterate_commit([=](Transaction &tr1){
103  Snapshot str1(tr1);
104  tr1[gn2] = tr1[gn2] - 1;
105  tr1[gn3] = str1[gn3] - 1;
106  });
107  trans(*gn3) += -1;
108  }
109  printf("finish\n");
110  return;
111 }
112 
113 #define NUM_THREADS 4
114 
115 int
116 main(int argc, char **argv) {
117  for(int k = 0; k < 10; k++) {
118  gn1.reset(LongNode::create<LongNode>());
119  gn2.reset(LongNode::create<LongNode>());
120  gn3.reset(LongNode::create<LongNode>());
121  gn4.reset(LongNode::create<LongNode>());
122 
123  gn1->iterate_commit_if([=](Transaction &tr1)->bool{
124  if( !gn1->insert(tr1, gn2, true))
125  return false;
126  tr1[ *gn2] = tr1[ *gn2] + 1;
127  if( !gn2->insert(tr1, gn3, true))
128  return false;
129  tr1.print();
130  if( !gn3->insert(tr1, gn4, true))
131  return false;
132  tr1.print();
133  if( !gn3->release(tr1, gn4))
134  return false;
135  tr1.print();
136  return true;
137  });
138  gn1->print_();
139  gn1->release(gn2);
140  gn1->print_();
141  gn1->insert(gn2);
142  gn1->print_();
143  gn2->iterate_commit([=](Transaction &tr1){
144  tr1[ *gn2] = tr1[ *gn2] - 1;
145  tr1[ *gn3] = 0;
146  });
147  {
148  Snapshot shot1(*gn1);
149  shot1.print();
150  long x = shot1[*gn3];
151  printf("Gn3:%ld\n", x);
152  }
153  trans(*gn3) = 3;
154  long x = ***gn3;
155  printf("Gn3:%ld\n", x);
156  trans(*gn3) = 0;
157 
158  shared_ptr<LongNode> p1(LongNode::create<LongNode>());
159  gn1->insert(p1);
160  gn1->swap(p1, gn2);
161  gn3->insert(p1);
162  trans(*gn1) = 3;
163  trans(*gn1) = 0;
164 
165  {
166  shared_ptr<LongNode> p2(LongNode::create<LongNode>());
167  shared_ptr<LongNode> p22(LongNode::create<LongNode>());
168  shared_ptr<LongNode> p211(LongNode::create<LongNode>());
169  shared_ptr<LongNode> p2111(LongNode::create<LongNode>());
170  shared_ptr<LongNode> p2112(LongNode::create<LongNode>());
171  shared_ptr<LongNode> p2113(LongNode::create<LongNode>());
172  shared_ptr<LongNode> p2114(LongNode::create<LongNode>());
173  p2111->insert(p2112);
174  p2112->insert(p2113);
175  p2111->insert(p2114);
176  shared_ptr<LongNode> p21(LongNode::create<LongNode>());
177  p2->insert(p21);
178  p21->insert(p211);
179  p2->insert(p211);
180  trans(*p211) = 1;
181  p21->insert(p22);
182  p211->insert(p22);
183  gn3->iterate_commit_if([=](Transaction &tr1)->bool{
184  if( !p1->insert(tr1, p22, true))
185  return false;
186  if( !gn3->insert(tr1, p2, true))
187  return false;
188  if( !gn3->insert(tr1, p2111, true))
189  return false;
190  if( !p21->insert(tr1, p2111, false))
191  return false;
192  tr1[*p22] = 1;
193 // { Snapshot shot1( *p211); shot1.list(); }
194 // { Snapshot shot1( *p1); shot1.list(); }
195 // { Snapshot shot1( *p2); shot1.list(); }
196  return true;
197  });
198  {
199  Snapshot shot1(*p21);
200  shot1[ *p2111];
201  shot1[ *p2112];
202  shot1[ *p2113];
203  shot1[ *p2114];
204  }
205  {
206  Snapshot shot1(*gn3);
207  shot1[ *p2];
208  shot1[ *p21];
209  shot1[ *p22];
210  shot1[ *p2111];
211  shot1[ *p2114];
212  }
213  trans(*p211) = 0;
214  gn3->iterate_commit_if([=](Transaction &tr1)->bool{
215  tr1[ *p2113] = 1;
216  tr1[ *p2114] = 1;
217  if( !p1->release(tr1, p22))
218  return false;
219  if( !gn3->release(tr1, p2))
220  return false;
221  if( !gn3->release(tr1, p2111))
222  return false;
223  return true;
224  });
225  trans(*p22) = 0;
226  p2114->print_();
227  trans(*p2114) = 0;
228  trans(*p2113) = 0;
229 
230  gn1->iterate_commit([=](Transaction &tr1){
231  const Snapshot &ctr1(tr1); // For reading.
232  tr1[gn1] = ctr1[gn1] + 1;
233  tr1[gn3] = ctr1[gn3] + 1;
234  tr1[gn1] = ctr1[gn1] - 1;
235  tr1[gn3] = ctr1[gn3] - 1;
236  });
237  }
238  gn1->print_();
239  gn1->release(p1);
240  gn1->print_();
241 
242  std::thread threads[NUM_THREADS];
243 
244  for(int i = 0; i < NUM_THREADS; i++) {
245  std::thread th( &start_routine);
246  threads[i].swap(th);
247  }
248  for(int i = 0; i < NUM_THREADS; i++) {
249  threads[i].join();
250  }
251  printf("join\n");
252 
253  if(***gn1 || ***gn2 || ***gn3 || ***gn4) {
254  printf("failed1\n");
255  printf("Gn1:%ld\n", (long)***gn1);
256  printf("Gn2:%ld\n", (long)***gn2);
257  printf("Gn3:%ld\n", (long)***gn3);
258  printf("Gn4:%ld\n", (long)***gn4);
259  return -1;
260  }
261 
262  gn1.reset();
263  gn2.reset();
264  gn3.reset();
265  gn4.reset();
266  p1.reset();
267 
268  if(objcnt != 0) {
269  printf("failed1\n");
270  return -1;
271  }
272  if(total != 0) {
273  printf("failed total=%ld\n", (long)total);
274  return -1;
275  }
276  }
277  printf("succeeded\n");
278  return 0;
279 }

Generated for KAME4 by  doxygen 1.8.3