Tervel  1.0.0
A collection of wait-free containers and algorithms.
testObject.h
Go to the documentation of this file.
1 /*
2 #The MIT License (MIT)
3 #
4 #Copyright (c) 2015 University of Central Florida's Computer Software Engineering
5 #Scalable & Secure Systems (CSE - S3) Lab
6 #
7 #Permission is hereby granted, free of charge, to any person obtaining a copy
8 #of this software and associated documentation files (the "Software"), to deal
9 #in the Software without restriction, including without limitation the rights
10 #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 #copies of the Software, and to permit persons to whom the Software is
12 #furnished to do so, subject to the following conditions:
13 #
14 #The above copyright notice and this permission notice shall be included in
15 #all copies or substantial portions of the Software.
16 #
17 #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 #THE SOFTWARE.
24 #
25 */
26 
27 #include <functional>
28 #include <climits>
29 #include <assert.h>
30 #include <atomic>
31 #include <random>
32 #include <string>
33 #include <cstdint>
34 #include <stdio.h>
35 #include <iostream>
36 #include <gflags/gflags.h>
37 
40 
43 // Constructor Arguments
44 DEFINE_int32(array_length, 32, "The size of the region to test on.");
45 DEFINE_int32(mcas_size, 2, "The number of words in a mcas operation.");
46 
48 DEFINE_int32(operation_type, 0, "The type of test to execute"
49  "(0: updating single multi-word object"
50  ", 1: updating multiple objects"
51  ", 2: updating overlapping multi-word updates)");
52 
53 enum class TestType : size_t {UPDATEOBJECT = 0, UPDATEMULTIOBJECT = 1,
54  RANDOMOVERLAPS = 2};
55 
56 
58 DEFINE_int32(num_threads, 1, "The number of threads to spawn.");
59 DEFINE_int32(execution_time, 5, "The amount of time to run the tests");
60 
61 typedef uint64_t Value;
62 class TestObject {
63  public:
64 
65 
67  delete test_class_;
68  };
69 
71  : execution_time_(FLAGS_execution_time)
72  , array_length_(FLAGS_array_length)
73  , num_threads_(FLAGS_num_threads)
74  , mcas_size_(FLAGS_mcas_size)
75  , operation_type_(FLAGS_operation_type) {
76  shared_memory_ = new std::atomic<void *>[array_length_];
77  passed_count_.store(0);
78  failed_count_.store(0);
79 
81  }
82 
83  void atomic_add(int passed_count, int failed_count) {
84  passed_count_.fetch_add(passed_count);
85  failed_count_.fetch_add(failed_count);
86  }
87 
88 
89 
90  // Define these functions if the test object requires per thread actions
91  void attachThread(int threadID) {
93  };
94 
95  void detachThread(int threadID) {
97  };
98 
100  /* This function is useful for enabling a blocking operation to return*/
101  };
102 
103  void init() {
104  /* This function is useful if you need to pre-fill a data structure */
105  }
106  void destroy() {
107  delete test_class_;
108  };
109 
110  struct counter{
111  int inc() {
112  assert(x_ >= 0 && x_ < limit_);
113  int y = x_++;
114  y += offset_;
115  assert(y >= 0 && y < limit_);
116  return y;
117  };
118 
119  void reset1(int offset, int len) {
120  offset_ = offset * len;
121  x_ = 0;
122  };
123 
124  void reset2(std::function<int()> func, int len) {
125  offset_ = func() * len;
126  x_ = 0;
127  };
128 
129  void setLimit(int l) {
130  limit_ = l;
131  };
132 
133  int limit_ = 0;
134  int x_ = 0;
135  int offset_ = 0;
136  };
137 
138  void run(int64_t thread_id) {
139  // Initial Setup
140  int passed_count = 0;
141  int failed_count = 0;
142  int lcount = 0;
143  attachThread(thread_id);
144 
145  std::default_random_engine generator;
146  std::uniform_int_distribution<int> distribution(0, array_length_);
147  std::uniform_int_distribution<int> dist_objs(0, array_length_/mcas_size_);
148 
149  struct counter count;
150  count.setLimit(array_length_);
151 
152  std::function<int()> posFunc;
153  std::function<void()> resFunc;
154  if (FLAGS_operation_type == 0) {
155  posFunc = std::bind(&counter::inc, count);
156  resFunc = std::bind(&counter::reset1, count,
157  0, mcas_size_);
158  } else if (FLAGS_operation_type == 1) {
159  posFunc = std::bind(&counter::inc, count);
160 
161  std::function<int()> func = std::bind(dist_objs, generator);
162  resFunc = std::bind(&counter::reset2, count,
163  func, mcas_size_);
164  } else if (FLAGS_operation_type == 2) {
165  posFunc = std::bind(distribution, generator);
166  resFunc = std::bind(&counter::reset1, count,
167  0, mcas_size_);
168  } else {
169  assert(false && "Operation type not recognized");
170  }
171 
172  // Wait for start signle
173  ready_count_.fetch_add(1);
174  while (wait_flag_.load());
175 
177  while (running_.load()) {
178  lcount++;
179  resFunc();
180 
181  bool res = test_class_->mcas(mcas_size_, posFunc, shared_memory_);
182  if (res) {
183  passed_count++;
184  } else {
185  failed_count_++;
186  }
187 
188  }
189  ready_count_.fetch_add(1);
190 
191  atomic_add(passed_count, failed_count);
192  detachThread(thread_id);
193  };
194 
195  std::string toString() {
196  std::string res("");
197  res += "Test Handler Configuration\n";
198  res += "\tThreads:" + std::to_string(num_threads_) + "\n";
199  res += "\tExecution Time: " + std::to_string(execution_time_) + "\n";
200  res += "\tarray_length: " + std::to_string(array_length_)+"\n";
201  res += "\tmcas_size: " + std::to_string(mcas_size_)+"\n";
202  res += "\toperation_type: " + std::to_string(operation_type_)+"\n";
203  return res;
204  };
205 
206  std::string results() {
207  uint64_t p = passed_count_.load();
208  uint64_t f = failed_count_.load();
209  std::string res("");
210  res += "-- Test Results--\n";
211  res += this->toString() + "\n";
212  res += "\tSuccesses: " + std::to_string(p)+"\n";
213  res += "\tFailures: " + std::to_string(f)+"\n";
214  res += "\tTotal: " + std::to_string(p+f)+"\n";
215  return res;
216  };
217 
218 
219 
220  const int execution_time_;
221  const int array_length_;
222  const int num_threads_;
223  const int mcas_size_;
224  const int operation_type_;
225 
227 
228  std::atomic<uint64_t> passed_count_ {0};
229  std::atomic<uint64_t> failed_count_ {0};
230  std::atomic<void *>* shared_memory_;
231 
232  std::atomic<bool> wait_flag_{true};
233  std::atomic<bool> running_{true};
234  std::atomic<int> ready_count_{0};
235 };
std::atomic< void * > * shared_memory_
Definition: testObject.h:230
std::atomic< uint64_t > failed_count_
Definition: testObject.h:229
std::atomic< bool > wait_flag_
Definition: testObject.h:232
TestClass< Value, Value > * test_class_
Definition: testObject.h:226
void atomic_add(int passed_count, int failed_count)
Definition: testObject.h:83
std::string results()
Definition: testObject.h:206
void destroy()
Definition: testObject.h:106
void detach_thread()
Definition: blank_api.h:43
const int operation_type_
Definition: testObject.h:224
TestObject()
Definition: testObject.h:70
void attachThread(int threadID)
Definition: testObject.h:91
std::atomic< bool > running_
Definition: testObject.h:229
void run(int64_t thread_id)
Definition: testObject.h:138
Definition: testObject.h:60
int inc()
Definition: testObject.h:111
int x_
Definition: testObject.h:134
void reset1(int offset, int len)
Definition: testObject.h:119
void detachThread(int threadID)
Definition: testObject.h:95
DEFINE_int32(capacity, 64,"The initial capacity of the hash map")
Change this when including a new data structure.
int offset_
Definition: testObject.h:135
std::atomic< uint64_t > passed_count_
Definition: testObject.h:228
int limit_
Definition: testObject.h:133
std::atomic< int > ready_count_
Definition: testObject.h:230
TestType
Definition: testObject.h:53
void attach_thread()
Definition: blank_api.h:40
void reset2(std::function< int()> func, int len)
Definition: testObject.h:124
const int num_threads_
Definition: testObject.h:223
TestClass * test_class_
Definition: testObject.h:226
uint64_t Value
Definition: testObject.h:59
bool mcas(int len, std::function< int()> posFunc, std::atomic< void * > *address)
Definition: wf_mcas_api.h:63
const int execution_time_
Definition: testObject.h:224
void init()
Definition: testObject.h:103
std::string toString()
Definition: testObject.h:195
void setLimit(int l)
Definition: testObject.h:129
const int array_length_
Definition: testObject.h:221
Definition: blank_api.h:31
const int mcas_size_
Definition: testObject.h:223
Definition: testObject.h:110
~TestObject()
Definition: testObject.h:66
void extra_end_signal()
Definition: testObject.h:99