Вопрос

Я ищу способ использования pthread rwlock. структура с условия Процедуры в C ++.

У меня есть два вопроса:

Во-первых: как это возможно, и если мы не можем, почему?

Во-вторых: Почему нынешний POTREAD PHHREAD не реализовал это поведение?

Чтобы понять мою цели, я объясню, что будет мое использование: у меня есть модель потребительских производителей, занимающихся одним общим массивом. Потребитель будет COND_WAIT, когда массив пуст, но RDLock при чтении некоторых элементов. Производитель будет заблокироваться при добавлении (+ сигнал) или удаления утеплений из массива.

Преимущество использования RDLock вместо Mutex_Lock - улучшить производительность: при использовании Mutex_Lock, несколько читателей будут блокировать, тогда как использование RDLock несколько читателей не будет блокировать.

Это было полезно?

Решение

Я предполагаю, что по «условиям» вы имеете в виду «условные переменные». Они разные вещи.

Нет, вы не можете использовать RWlock, когда в ожидании условной переменной. Я не могу ответить на то, что «почему», но вот в том, что Posix решил сделать это. Возможно, просто держать вещи простыми.

Однако вы все еще можете получить желаемое поведение, сделав свой класс RWLOLS, используя только Mutex и 2 условные переменные без использования POSIX RWLOCK:

getReadLock():
     lock(mutex)
     while(array.empty())
         wait(readersCondVar, mutex)
     readers++;
     unlock(mutex)       

releaseReadLock():
     lock(mutex)
     if (--readers == 0)
           broadcast(writerCondVar, mutex) // or signal, if only 1 producer
     unlock(mutex)

readerThread:
     forever() {
         getReadLock()
         read()
         releaseReadLock()
      }

getWriteLock():
     lock(mutex)
     while(readers) {
         wait(writerCondVar, mutex)
     }

releaseWriteLock():
     broadcast(readersCondVar, mutex)
     unlock(mutex)

writerThread():
      forever() {
         getWriteLock()
         write()
         releaseWriteLock()
      }

Просто и делает то, что вы хотите.

Другие советы

У меня такое же требование, как вам нужно.

Вот мое решение:

Wrap pthread_rwlock_t.

class rwlock
{
public:
    rwlock()
    {
        pthread_rwlock_init(&_lock, nullptr);
    }

    ~rwlock()
    {
        pthread_rwlock_destroy(&_lock);
    }

    void read_lock()
    {
        pthread_rwlock_rdlock(&_lock);
    }

    void write_lock()
    {
        pthread_rwlock_wrlock(&_lock);
    }

    bool try_read_lock()
    {
        return pthread_rwlock_tryrdlock(&_lock) == 0;
    }

    bool try_write_lock()
    {
        return pthread_rwlock_trywrlock(&_lock) == 0;
    }

    void lock()
    {
        read_lock();
    }

    void try_lock()
    {
        try_read_lock();
    }

    void unlock()
    {
        pthread_rwlock_unlock(&_lock);
    }

private:
    pthread_rwlock_t _lock;
};

Применение

rwlock lock;

std::condition_variable_any cond;

bool ready = false;

Режиссер

lock.write_lock();
...
if (!ready) {
    ready = true;
    cond.notify_all();
}
lock.unlock();

Потребитель

std::unique_lock<rwlock> lock_(lock);
while (!ready) {
    cond.wait(lock_, []{ return ready; });
}
...
ready = false;

C ++ 0x - получение многопотативной поддержки, и эта поддержка включает в себя новый тип под названием Condent_Variable_any:

class condition_variable_any
{
public:
    condition_variable_any();
    ~condition_variable_any();

    condition_variable_any(const condition_variable_any&) = delete;
    condition_variable_any& operator=(const condition_variable_any&) = delete;

    void notify_one();
    void notify_all();

    template <class Lock>
        void wait(Lock& lock);
    template <class Lock, class Predicate>
        void wait(Lock& lock, Predicate pred);

    template <class Lock, class Clock, class Duration>
        cv_status
        wait_until(Lock& lock,
                   const chrono::time_point<Clock, Duration>& abs_time);

    template <class Lock, class Clock, class Duration, class Predicate>
        bool
        wait_until(Lock& lock,
                   const chrono::time_point<Clock, Duration>& abs_time,
                   Predicate pred);

    template <class Lock, class Rep, class Period>
        cv_status
        wait_for(Lock& lock,
                 const chrono::duration<Rep, Period>& rel_time);

    template <class Lock, class Rep, class Period, class Predicate>
        bool
        wait_for(Lock& lock,
                 const chrono::duration<Rep, Period>& rel_time,
                 Predicate pred);
};

Есть объяснение того, как реализовать условия_Variable_Any здесь:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html#gen_cond_var.

Но на этой связи названа Gen_cond_var. Волшебная вещь о условиях /variable_any заключается в том, что она будет ждать все, что имеет блокировку () и разблокировать () элементы. Как только у вас есть condition_variable_any, то все, что вам нужно, это rwlock. Ссылка выше также представляет shared_mutex и shared_lock и показывает пример код, который вы хотите:

std::tr2::shared_mutex mut;
std::gen_cond_var cv;

void wait_in_shared_ownership_mode()
{
    std::tr2::shared_lock<std::tr2::shared_mutex> shared_lk(mut);
    // mut is now shared-locked
    // ...
    while (not_ready_to_proceed())
        cv.wait(shared_lk);  // shared-lock released while waiting
    // mut is now shared-locked
    // ...
}   // mut is now unlocked

void wait_in_unique_ownership_mode()
{
    std::unique_lock<std::tr2::shared_mutex> lk(mut);
    // mut is now unique-locked
    // ...
    while (not_ready_to_proceed())
        cv.wait(lk);  // unique-lock released while waiting
    // mut is now unique-locked
    // ...
}   // mut is now unlocked

Вышеуказанный документ несколько датируется. Здесь есть более актуальная реализация и описание Shared_Mutex / Shared_lock:

http://howardhinnant.github.io/shared_mutex. http://howardhinnant.github.io/shared_mutex.cpp.

Все это реализовано на вершине phthreads posix. Я надеюсь получить общий замок в техническом отчете C ++ (TR2), но, конечно, нет никакой гарантии этого.

Для чего вы хотите, вам нужно просто иметь 1 набор RWLOLD и 1 набор переменной Mutex / COND, PSEUDO-кода (хотя вам понадобится обычные петли на переменных POSIX COND)

consumer() {

  get_readlock();
  if(array_empty()) {
    release_readlock();
    grab_mutex();
    wait_on_condition();
    release_mutex();
    get_readlock();
  }
  process_elements();
  release_readlock();
}

producer()
{
  get_writelock();
  get_mutex();
  insert_elements();
  signal_condition();
  release_mutex();
  release_writelock();
}

Я догадаю, что переменные состояния работают только с Mutexes, потому что ожидание или сигнализация условия нуждается в взаимной исключительности.

Есть несколько Rwlocks. реализован на вершине mutexes и конденсар. Выберите любого и добавьте некоторые конденсары для ваших пользовательских потребностей.

Чтобы решить проблему, сигнализируемую в течение дня, нужно проверить снова после grab_mutex и раньше wait_on_condition:

consumer() {

  get_readlock();
  if(array_empty()) {
    release_readlock();
    grab_mutex();
    if(array_empty()) {
       wait_on_condition();
    }
    release_mutex();
    get_readlock();
  }
  process_elements();
  release_readlock();
}  
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top