lundi 26 juin 2017

Accessing parts of a memory block (e.g. Char array) atomically in C++


My use case

I have a program that manages a large number of data records, each of which with the size of R bytes. Each record has a lock whose size is 4 bytes. So in total, each record takes up S = R + 4 bytes. These records have to be laid in memory next to each other due to application-specific reasons, as illustrated below:

.-------------------------------------------------------------------------------.
| lock_1 | data_1 | lock_2 | data_2 | ........... | lock_n | data_n |
.-------------------------------------------------------------------------------.

On the c++ level, my program allocates a contiguous memory block, in the form of a char array. The array is cache line aligned, and R is a multiple of 4, effectively making each lock to be properly aligned:
char* region = new char[S*N]; // N is the number of records


Question

How can I use std::atomic functions to atomically modify the locks, without actually having to maintain an array of std::atomic<int> objects. I can think of two solutions:

  1. Given that Linux kernel uses identical bitwise representation for int and std::atomic<int>, cast a pointer of a lock to std::atomic, e.g.:
    char* x = region + (lockID * S); reinterpret_cast<atomic<int>*>(x)->fetch_add(1);
    , where x is the memory location of a given lock.
  2. If the above solution is not correct (perhaps because it may mess up the static code analysis done by the compiler), actually define a lock as an atomic value using placement new:
    for (int lockID = 0; lockID < N; lockID++) { char* memoryOffset = region + (lockID * S); std::atomic<int>* lockPtr = new (memoryOffset) std::atomic<int>; }
    Here, I do not want to keep an array of lockPtrs, due to space considerations, so I throw them away, and use the cast from solution 1 to get the pointer to the atomic object of a given lock.

Is any of these solutions correct? If not, what is the right solution?

Aucun commentaire:

Enregistrer un commentaire