С++ 11 межпроцессорная атомистика и мьютексы
У меня есть программа Linux, которая генерирует несколько процессов (fork) и обменивается данными через общую память POSIX. Я хотел бы, чтобы каждый процесс выделял id (0-255). Мое намерение состоит в том, чтобы поместить битвектор в область разделяемой памяти (инициализирован на ноль) и атомарно сравнить и поменять бит, чтобы выделить идентификатор.
Есть ли способ сделать это с помощью С++ 11? Могу ли я создать атомный битбит? Могу ли я использовать мьютекс через процессы? Как я могу заверить, что конструкторы вызываются один раз и только один раз для всех процессов?
Ответы
Ответ 1
С++ 11 примитивы потоков (мьютексы, атомы и т.д.) являются примитивами на основе потоков. Они ничего не знают о процессах, и они не являются средством достижения межпроцессного общения.
Так как стандарт С++ 11 не упоминает о процессах или межпроцессной коммуникации, поведение таких примитивов при размещении в разделяемой процессами памяти (файл с отображением памяти, какой-то внепроцессный глобальный сопоставление память и т.д.) undefined.
Ответ 2
Вы можете использовать мьютекс внутри блока разделяемой памяти, но мьютекс должен быть объявлен как SHARED, поэтому нет ничего необычного в использовании мьютексов внутри общей памяти, вы можете создать собственный класс, это очень просто:
class Mutex {
private:
void *_handle;
public:
Mutex(void *shmMemMutex, bool recursive =false, );
virtual ~Mutex();
void lock();
void unlock();
bool tryLock();
};
Mutex::Mutex(void *shmMemMutex, bool recursive)
{
_handle = shmMemMutex;
pthread_mutexattr_t attr;
::pthread_mutexattr_init(&attr);
::pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
::pthread_mutexattr_settype(&attr, recursive ? PTHREAD_MUTEX_RECURSIVE_NP : PTHREAD_MUTEX_FAST_NP);
if (::pthread_mutex_init((pthread_mutex_t*)_handle, &attr) == -1) {
::free(_handle);
throw ThreadException("Unable to create mutex");
}
}
Mutex::~Mutex()
{
::pthread_mutex_destroy((pthread_mutex_t*)_handle);
}
void Mutex::lock()
{
if (::pthread_mutex_lock((pthread_mutex_t*)_handle) != 0) {
throw ThreadException("Unable to lock mutex");
}
}
void Mutex::unlock()
{
if (::pthread_mutex_unlock((pthread_mutex_t*)_handle) != 0) {
throw ThreadException("Unable to unlock mutex");
}
}
bool Mutex::tryLock()
{
int tryResult = ::pthread_mutex_trylock((pthread_mutex_t*)_handle);
if (tryResult != 0) {
if (EBUSY == tryResult) return false;
throw ThreadException("Unable to lock mutex");
}
return true;
}