Frage

Ich bin für eine Art und Weise zu nutzen suchen Pthread rwlock Struktur mit Bedingungen Routinen in C ++.

Ich habe zwei Fragen:

Erstens: Wie ist es möglich, und wenn wir es nicht können, warum

?

Zweitens: Warum aktuelle POSIX Pthread dieses Verhalten nicht umgesetzt haben,

meine Absicht zu verstehen, erkläre ich, was meinen Einsatz sein wird: Ich habe ein Erzeuger-Verbraucher-Modell mit einem gemeinsamen Array handelt. Der Verbraucher wird cond_wait, wenn das Array leer ist, aber rdlock wenn einige elems lesen. Der Produzent wird wrlock beim Hinzufügen (+ Signal) oder elems aus dem Array entfernt werden.

Der Vorteil rdlock statt mutex_lock zu verwenden, ist die Leistung zu verbessern. Wenn mutex_lock verwenden, würden mehrere Leser blockieren, während rdlock mehrere Leser mit nicht blockieren

War es hilfreich?

Lösung

Ich gehe davon aus, dass durch „Bedingungen“, Sie „Bedingungsvariablen“ bedeuten. Sie sind verschiedene Dinge.

Nein, man kann nicht eine rwlock verwenden, wenn eine bedingte Variable warten. Ich kann nicht in Bezug auf die „Warum“ beantworten, aber das ist die Art und Weise POSIX entschieden hat, es zu tun. Vielleicht nur die Dinge einfach zu halten.

Sie können das Verhalten erhalten Sie jedoch, indem Sie Ihre eigene rwlock Klasse zu machen, indem nur ein Mutex und 2 bedingte Variablen ohne eine POSIX rwlock mit:

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()
      }

Einfache und tut, was Sie wollen.

Andere Tipps

Ich habe die gleiche Anforderung wie Sie benötigt werden.

Hier ist meine Lösung:

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;
};

Verwendung

rwlock lock;

std::condition_variable_any cond;

bool ready = false;

Hersteller

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

Verbraucher

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

C ++ 0x wird immer Unterstützung Multithreading, und dass die Unterstützung enthält einen neuen Typ namens condition_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);
};

Es gibt eine Erklärung dafür, wie condition_variable_any zu implementieren hier:

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

aber unter diesem Link wird sie unter der Bezeichnung gen_cond_var. Die magische Sache über condition_variable_any ist, dass es auf etwas wartet, das Schloss hat () und unlock () Mitglieder. Sobald Sie condition_variable_any haben, dann alles, was Sie brauchen, ist ein rwlock. Der Link oben auch führt shared_mutex und shared_lock und zeigt Beispielcode zu tun, was Sie wollen:

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

Das oben gezeigte Dokument ist etwas veraltet. Es gibt eine mehr up-to-date Implementierung und Beschreibung von shared_mutex / shared_lock hier:

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

All dies wird auf der POSIX pthreads umgesetzt. Ich hoffe, dass den gemeinsamen sichernde Sachen in eine C ++ technischen Bericht (TR2) zu bekommen, aber natürlich gibt es keine Garantie dafür.

Für das, was Sie wollen, müssen Sie haben nur 1 Satz rwlock und 1 Satz Mutex / lf Variable, Pseudo-Code (auch wenn Sie die üblichen Schleifen auf den Posix-cond Variablen müssen)

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();
}

Ich würde Bedingungsvariablen erraten funktioniert nur mit Mutexe, weil warten oder Signal eine Bedingungen für die gegenseitige Exklusivität muss.

Es gibt mehrere RWLocks oben auf mutexes implementiert und condvars. Egal auf welche ein und fügen Sie einige condvars für Ihre individuellen Bedürfnisse.

Zur Ausgabe von Doomsday signalisiert löst eine hat erneut überprüfen Zustand nach grab_mutex und vor 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();
}  
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top