how to update a variable in contiguous memory atomicly - c++

I have a struct with multi variables packed which is not aligned.Then I make an array of the struct and set up a reader thread and a writer thread to update the variable concurrently.I find error value which only half of the variable is updated from output.I guess this is caused by one variable lay in two cache lines.Change the variable to atomic doesn't solve the problem.So,is there a way to solve this without memory aligned?
#include <thread>
#include <atomic>
#include <iostream>
#include <mutex>
#include <stdalign.h>
#pragma pack(1)
struct Foo {
uint64_t key;
uint64_t key2;
uint64_t key3;
uint32_t key4;
uint64_t key5;
};
#pragma pack()
const int block_size = 10;
uint64_t keys[10];
void printEle(const Foo* ele) {
std::cout << "Key " << ele->key
<< " key2 " << ele->key2
<< " key3 " << ele->key3
<< " key5 " << ele->key5 << std::endl;
}
void reader(Foo* list) {
for (int i = 0; i < 1000000; ++i) {
for (int j = 0; j < block_size; ++j) {
Foo* ele = reinterpret_cast<Foo*>(list + j);
printEle(ele);
}
}
}
void writer(Foo* list) {
for (int i = 0; i < 1000000; ++i) {
for (int j = 0; j < block_size; ++j) {
Foo* ele = reinterpret_cast<Foo*>(list + j);
if (i % 2 == 0) {
ele->key = keys[j];
ele->key2 = keys[j];
ele->key3 = keys[j];
ele->key5 = keys[j];
} else {
ele->key = j;
ele->key2 = j;
ele->key3 = j;
ele->key5 = j;
}
}
}
}
void test() {
keys[0]= 1556273083026830079;
keys[1]= 6541630416163430395;
keys[2]= 2310622570815837826;
keys[3]= 12643974306886634761;
keys[4]= 15393333677141345392;
keys[5]= 3591765785331799809;
keys[6]= 5404586990109662840;
keys[7]= 1376395845958874653;
keys[8]= 7620513273959825252;
keys[9]= 16620834775579010287;
Foo* list = new Foo[block_size];
for (int i = 0; i < block_size; ++i) {
uint64_t k = keys[i];
Foo* ele = reinterpret_cast<Foo*>(list + i);
ele->key = k;
ele->key2 = k;
ele->key3 = k;
ele->key4 = 707406378;
ele->key5 = k;
}
std::thread write(writer, list);
std::thread read(reader, list);
read.join();
write.join();
}
int main(int argc, char* argv[]) {
std::cout << "Size " << sizeof(Foo) << std::endl;
test();
std::cout << "done." << std::endl;
return 0;
}

Related

'this' cannot be used in a constant expression error

The error is on line 76 int res[mSize]; the problem is on mSize. It seems like a simple fix but I can't figure it out. If someone can figure it out or point me in the right direction that would be greatly appreciated.
Also, the deconstructor ~MyContainer(), I am not sure if I am using it right or if there is a correct place to put it.
Here is my code:
#include <iostream>
using namespace std;
class MyContainer
{
private:
int* mHead; // head of the member array
int mSize; // size of the member array
public:
MyContainer();
MyContainer(int*, int);
//~MyContainer();
void Add(int);
void Delete(int);
int GetSize();
void DisplayAll();
int FindMissing();
~MyContainer() {}
};
MyContainer::MyContainer()
{
mHead = NULL;
mSize = 0;
}
MyContainer::MyContainer(int* a, int b)
{
mHead = a;
mSize = b;
}
void MyContainer::Add(int a)
{
*(mHead + mSize) = a;
mSize++;
}
void MyContainer::Delete(int a)
{
int index;
for (int i = 0; i < mSize; i++)
{
if (*(mHead + i) == a)
{
index = i;
break;
}
}
for (int i = index; i < mSize; i++)
{
*(mHead + i) = *(mHead + i + 1);
}
mSize--;
}
int MyContainer::GetSize()
{
return mSize;
}
void MyContainer::DisplayAll()
{
cout << "\n";
for (int i = 0; i < mSize; i++)
{
cout << *(mHead + i) << " ";
}
}
int MyContainer::FindMissing()
{
int res[mSize];
int temp;
int flag = 0;
for (int i = 1; i <= mSize; i++)
{
flag = 0;
for (int j = 0; j < mSize; j++)
{
if (*(mHead + j) == i)
{
flag = 1;
break;
}
}
if (flag == 0)
{
temp = i;
break;
}
}
return temp;
}
int main()
{
const int cSize = 5;
int lArray[cSize] = { 2, 3, 7, 6, 8 };
MyContainer lContainer(lArray, cSize);
lContainer.DisplayAll();
lContainer.Delete(7);
lContainer.DisplayAll();
cout << "Size now is: " << lContainer.GetSize() << endl; lContainer.Add(-1);
lContainer.Add(-10);
lContainer.Add(15);
lContainer.DisplayAll();
cout << "Size now is: " << lContainer.GetSize() << endl;
cout << "First missing positive is: " << lContainer.FindMissing() << endl;
system("PAUSE"); return 0;
}
int res[mSize];
The size of the array mSize must be known at compile time. You cannot use a variable here. An option may be to define a macro with an largish value that will not exceeded.
static const int kLargeSize =100;
int res[kLargeSize];
Edited in response to the comments - const and constexpr are a better option than a macro.
Or even better, you can use std::vector - https://en.cppreference.com/w/cpp/container/vector

C++ program produces an exception to?

why an error occurs An exception was thrown at address 0x003329B0 in ConsoleApplication1.exe: 0xC0000005: access violation occurred while writing to address 0xCCCCCCCC
#include <iostream>
#include <time.h>
#include <random>
//------------------
using namespace::std;
//------------------
void input(int* size)
{
cout << "Input pleas size your diapason of array";
cout << endl;
cin >> (*size);
};
void randomizer(int** array, int& size)
{
srand(time(NULL));
int result = rand() % size;
result += 1;
for (int i = 1; i <= result; i++)
{
(*array[i]) = rand() % 100;
if (i % 2)
{
(*array[i]) *= -1;
}
};
(*array)[0] = result;
};
//------------------------------------------------------
int ittMOD(int** array)
{
int result = 0;
int itt = (*array)[1];
for (int i(0); i < (*arrey[0]); i++)
{
if (itt < 0)
{
itt *= -1;
};
if (itt < (*array[i]))
{
itt = (*array[i]);
result = i;
};
return result;
};
};
int main()
{
setlocale(LC_ALL, "RUSSIAN");
//---------------------------
int* array = new int;
int size = 0;
//---------------------------
input(&size);
randomizer(&array, size);
cout << ittMOD(`&array);
cout << endl;
//cout << summELEMENTS(arrey);
delete array;
array = NULL;
return 0;
};

Nested struct with dynamic size in C++

I am trying to print data in showValues(mainStruct*) but I am unable to do so..
#include <iostream>
#include <string>
#include <vector>
#include <memory>
typedef struct
{
uint32_t someNumber;
}subStruct;
typedef struct{
uint32_t sizeofSubStruct;
subStruct subStructArray[1];
}mainStruct;
This function construct the mainStruct and fill it with some values
mainStruct* constructMainStruct()
{
mainStruct* msPtr;
msPtr = (mainStruct*)malloc(sizeof(mainStruct)*10);
msPtr->sizeofSubStruct = 10;
subStruct* ssPtr = msPtr->subStructArray;
for(uint32_t i=0; i < msPtr->sizeofSubStruct; i++)
{
ssPtr->someNumber = i+10;
ssPtr++;
}
return msPtr;
}
Following function does not print anything
void showValues(mainStruct* msPtr)
{
subStruct* ssPtr = msPtr->subStructArray;
for(uint32_t i=0; i < msPtr->sizeofSubStruct; i++)
{
std::cout << " - " + ssPtr->someNumber <<std::endl;
}
}
Main function
int main()
{
//contructing mainStruct with some values
mainStruct* msPtr = constructMainStruct();
//trying to print values which has been created in above step
showValues(msPtr);
}
Your printing problem (which is by no means the only issue) is in the line:
for(uint32_t i=0; i > msPtr->sizeofSubStruct; i++)
You initialize i to 0 but use a test of "i > msPtr->sizeofSubStruct;", it should be less-than rather than greater-than.
Other problems are with your allocation size, it should be sizeof(mainStruct)+sizeof(subStruct)*9, it's not a huge problem with the subStruct you have right now but as soon as subStruct becomes something complicated it would be.
Besides what #SoronelHaetir has already noticed, the function showValues is not incrementing the subStruct pointer.
The code should look like this;
void showValues(mainStruct* msPtr)
{
subStruct* ssPtr = msPtr->subStructArray;
for (uint32_t i = 0; i < msPtr->sizeofSubStruct; i++)
{
std::cout << " - " + ssPtr->someNumber << std::endl;
++ssPtr;
}
}
Following is the working code for showValues
void showValues(mainStruct* msPtr)
{
subStruct* ssPtr = msPtr->subStructArray;
for(uint32_t i=0; i < msPtr->sizeofSubStruct; i++)
{
std::cout << (ssPtr+i)->someNumber <<std::endl;
}
}
and complete program code is as below:
#include <iostream>
typedef struct
{
uint32_t someNumber;
}subStruct;
typedef struct{
uint32_t sizeofSubStruct;
subStruct subStructArray[1];
}mainStruct;
mainStruct* constructMainStruct()
{
mainStruct* msPtr;
msPtr = (mainStruct*)malloc(sizeof(mainStruct)*10);
msPtr->sizeofSubStruct = 10;
subStruct* ssPtr = msPtr->subStructArray;
for(uint32_t i=0; i < msPtr->sizeofSubStruct; i++)
{
ssPtr->someNumber = i+10;
ssPtr++;
}
return msPtr;
}
void showValues(mainStruct* msPtr)
{
subStruct* ssPtr = msPtr->subStructArray;
for(uint32_t i=0; i < msPtr->sizeofSubStruct; i++)
{
std::cout << (ssPtr+i)->someNumber <<std::endl;
}
}
int main()
{
//contructing mainStruct with some values
mainStruct* msPtr = constructMainStruct();
//trying to print values which has been created in above step
showValues(msPtr);
}

declaring a function with arrays

First of all, im a c++ noob! Ok with that being said, i need to declare a function that initializes a grid. The function takes an array of int as the input and needs to return an array of int. I have:
array<int> InitializeGrid (array<int>)
{
const int NB_ROWS = 10;
const int NB_COLUMN = 10;
const int WATER = 0;
int grid[NB_ROWS][NB_COLONN];
for (int i = 0; i < NB_ROWS; i++)
{
for (int j = 0; j < NB_COLONN; j++)
{
grid[i][j] = WATER;
cout << grid[i][j] << " ";
}
cout << endl;
}
return ??
}
You don't need to return anything if you pass the array by reference:
#include <array>
#include <iostream>
static const int NB_ROWS = 10;
static const int NB_COLUMN = 10;
static const int WATER = 0;
void InitializeGrid (std::array<std::array<int, NB_COLUMN>, NB_ROWS> &grid)
{
for (auto &row : grid)
{
for (auto &col : row)
{
col = WATER;
std::cout << col << " ";
}
std::cout << '\n';
}
}
int main()
{
std::array<std::array<int, NB_COLUMN>, NB_ROWS> grid;
InitializeGrid(grid);
}
btw, if your WATER is 0 it is sufficive to write
std::array<std::array<int, NB_COLUMN>, NB_ROWS> grid{};
to initialize all elements to zero.

Converting 1D to 2D?

This might seem like a stupid question but it's really bugging me.
Basically, I have a 1D array that I need to convert into a 2D array. Basically, the size of the array is: 62017 now from this, I need to get the Rows and Cols of this. But, do this dynamically, so for example, it would take the number of say: 43101 and then establish the rows+cols and then re-size the vector accordingly.
I hope I've explained enough and hope someone can help, thanks :)
And here it is old school array style (since I can't access a C++0x compiler at the moment)
#include <iostream>
//#include <array>
#include <inttypes.h>
#include <math.h>
void calc_new_sizes(const size_t old_size, size_t& new_size1, size_t& new_size2)
{
new_size1 = 1;
new_size2 = 1;
size_t stop_at = (size_t)sqrt(old_size) + 1;
for (size_t i = 1; i<stop_at; i++)
{
if ( old_size % i == 0 )
{
new_size1 = i;
new_size2 = old_size / i;
}
}
}
template <class T>
T** twoDimensionify(T* p_old_array, const size_t old_size)
{
size_t new_size1=1, new_size2=1, old_i=0;
calc_new_sizes(old_size, new_size1, new_size2);
T** returnValue = new T*[new_size1];
for (size_t i=0; i<new_size1; i++)
{
returnValue[i] = new T[new_size2];
for (size_t j=0; j<new_size2; j++)
{
returnValue[i][j] = p_old_array[old_i];
old_i++;
}
}
return returnValue;
}
int main()
{
size_t old_size=20, new_size1=0, new_size2=0;
calc_new_sizes(old_size, new_size1, new_size2);
std::cout << "From " << old_size << " to " << new_size1 << "x" << new_size2 << std::endl;
int old_array[20] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
int **new_array = twoDimensionify<int>(old_array, 20);
for (size_t i=0; i<new_size1; i++)
{
for (size_t j=0; j<new_size2; j++)
{
std::cout << "new array[" << i << "," << j << "] = " << new_array[i][j] << std::endl;
}
}
// Clean up my memory. This is C++ afterall.
for (size_t i=0; i<new_size1; i++)
{
delete [](new_array[i]);
}
delete []new_array;
return 0;
}
I believe you're looking for something like this. Though with some challenges accessing a proper compiler I can't verify...
#include <iostream>
#include <array>
#include <inttypes.h>
#include <math.h>
void calc_new_sizes(const size_t old_size, size_t& new_size1, size_t& new_size2)
{
new_size1 = 1;
new_size2 = 1;
size_t stop_at = (size_t)sqrt(old_size) + 1;
for (size_t i = 1; i<stop_at; i++)
{
if ( old_size % i == 0 )
{
new_size1 = i;
new_size2 = old_size / i;
}
}
}
template <class T, size_t new_size_1, size_t new_size_2, size_t old_size>
std::array<new_size_1, std::array<T, new_size_2>> twoDimensionify(std::array<T, old_size> p_input)
{
std::array<new_size_1, std::array<T, new_size_2>> returnValue;
int old_i = 0;
for (int i=0; i<new_size_1; i++)
{
for (int j=0; j<new_size_2; j++)
{
returnValue[i][j] = p_input[old_i];
old_i++;
}
}
return returnValue;
}
int main()
{
size_t old_size=20, new_size1=0, new_size2=0;
calc_new_sizes(old_size, new_size1, new_size2);
std::cout << "From " << old_size << " to " << new_size1 << "x" << new_size2 << std::endl;
return 0;
}