Testing SC-DRF non-atomic global read and write within an atomic acquire/release critical block.
#include <iostream>
#include <cassert>
#include <cinttypes>
#include <cstring>
#include <atomic>
#include <memory>
#include <thread>
#include <pthread.h>
#define CATCH_CONFIG_MAIN
#include <catch2/catch_amalgamated.hpp>
private:
enum Defaults : int {
array_size = 10
};
constexpr
int number(
const Defaults rhs) noexcept {
return static_cast<int>(rhs);
}
int value1 = 0;
int array[array_size] = { 0 };
void reset(int v1, int array_value) {
int _sync_value = sync_value;
(void) _sync_value;
value1 = v1;
for(int i=0; i<array_size; i++) {
array[i] = array_value;
}
sync_value = v1;
}
void putThreadType01(int _len, int startValue) {
const int len = std::min(
number(array_size), _len);
{
int _sync_value = sync_value;
_sync_value = startValue;
for(int i=0; i<len; i++) {
array[i] = _sync_value+i;
}
value1 = startValue;
sync_value = _sync_value;
}
}
void getThreadType01(const std::string msg, int _len, int startValue) {
const int len = std::min(
number(array_size), _len);
int _sync_value;
while( startValue != ( _sync_value = sync_value ) ) ;
REQUIRE_MSG(msg+
": %s: value at read value1 (sync)", _sync_value == value1);
REQUIRE_MSG(msg+
": %s: value at read value1 (start)", startValue == value1);
for(int i=0; i<len; i++) {
int v = array[i];
}
sync_value = _sync_value;
}
void putThreadType11(int indexAndValue) {
const int idx = std::min(
number(array_size)-1, indexAndValue);
{
int _sync_value;
do {
_sync_value = sync_value;
} while( idx != (_sync_value * -1) - 1 );
_sync_value = idx;
value1 = idx;
array[idx] = idx;
sync_value = _sync_value;
}
}
void getThreadType11(const std::string msg, int _idx) {
const int idx = std::min(
number(array_size)-1, _idx);
int _sync_value;
do {
_sync_value = sync_value;
} while( idx != _sync_value );
_sync_value = (idx+1)%array_size;
_sync_value = ( _sync_value + 1 ) * -1;
value1 = _sync_value;
sync_value = _sync_value;
}
public:
: value1(0), sync_value(0) {}
void test01_Read1Write1() {
reset(0, 1010);
std::thread getThread01(&TestMemModelSCDRF00::getThreadType01, this, "test01.get01", array_size, 3);
std::thread putThread01(&TestMemModelSCDRF00::putThreadType01, this, array_size, 3);
putThread01.join();
getThread01.join();
}
void test02_Read2Write1() {
reset(0, 1021);
{
std::thread getThread00(&TestMemModelSCDRF00::getThreadType01, this, "test01.get00", array_size, 4);
std::thread getThread01(&TestMemModelSCDRF00::getThreadType01, this, "test01.get01", array_size, 4);
std::thread putThread01(&TestMemModelSCDRF00::putThreadType01, this, array_size, 4);
putThread01.join();
getThread00.join();
getThread01.join();
}
reset(0, 1022);
{
std::thread putThread01(&TestMemModelSCDRF00::putThreadType01, this, array_size, 5);
std::thread getThread00(&TestMemModelSCDRF00::getThreadType01, this, "test01.get00", array_size, 5);
std::thread getThread01(&TestMemModelSCDRF00::getThreadType01, this, "test01.get01", array_size, 5);
putThread01.join();
getThread00.join();
getThread01.join();
}
}
void test03_Read4Write1() {
reset(0, 1030);
std::thread getThread01(&TestMemModelSCDRF00::getThreadType01, this, "test02.get01", array_size, 6);
std::thread getThread02(&TestMemModelSCDRF00::getThreadType01, this, "test02.get02", array_size, 6);
std::thread putThread01(&TestMemModelSCDRF00::putThreadType01, this, array_size, 6);
std::thread getThread03(&TestMemModelSCDRF00::getThreadType01, this, "test02.get03", array_size, 6);
std::thread getThread04(&TestMemModelSCDRF00::getThreadType01, this, "test02.get04", array_size, 6);
putThread01.join();
getThread01.join();
getThread02.join();
getThread03.join();
getThread04.join();
}
void test11_Read10Write10() {
reset(-1, 1110);
std::thread reader[array_size];
std::thread writer[array_size];
for(
int i=0; i<
number(array_size); i++) {
reader[i] = std::thread(&TestMemModelSCDRF00::getThreadType11, this, "test11.get11", i);
}
for(
int i=0; i<
number(array_size); i++) {
writer[i] = std::thread(&TestMemModelSCDRF00::putThreadType11, this, i);
}
for(
int i=0; i<
number(array_size); i++) {
writer[i].join();
}
for(
int i=0; i<
number(array_size); i++) {
reader[i].join();
}
}
void test12_Read10Write10() {
reset(-1, 1120);
std::thread reader[array_size];
std::thread writer[array_size];
for(
int i=0; i<
number(array_size); i++) {
writer[i] = std::thread(&TestMemModelSCDRF00::putThreadType11, this, i);
}
for(
int i=0; i<
number(array_size); i++) {
reader[i] = std::thread(&TestMemModelSCDRF00::getThreadType11, this, "test12.get11", i);
}
for(
int i=0; i<
number(array_size); i++) {
writer[i].join();
}
for(
int i=0; i<
number(array_size); i++) {
reader[i].join();
}
}
void test_list() {
for(
int i=
loops; i>0; i--) { test01_Read1Write1(); }
for(
int i=
loops; i>0; i--) { test02_Read2Write1(); }
for(
int i=
loops; i>0; i--) { test03_Read4Write1(); }
for(
int i=
loops; i>0; i--) { test11_Read10Write10(); }
for(
int i=
loops; i>0; i--) { test12_Read10Write10(); }
}
};