С++ 11 межпроцессорная атомистика и мьютексы - программирование
Подтвердить что ты не робот

С++ 11 межпроцессорная атомистика и мьютексы

У меня есть программа Linux, которая генерирует несколько процессов (fork) и обменивается данными через общую память POSIX. Я хотел бы, чтобы каждый процесс выделял id (0-255). Мое намерение состоит в том, чтобы поместить битвектор в область разделяемой памяти (инициализирован на ноль) и атомарно сравнить и поменять бит, чтобы выделить идентификатор.

Есть ли способ сделать это с помощью С++ 11? Могу ли я создать атомный битбит? Могу ли я использовать мьютекс через процессы? Как я могу заверить, что конструкторы вызываются один раз и только один раз для всех процессов?

4b9b3361

Ответ 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;
}