Будет ли такой класс читаемым только один раз множеством потоков? - PullRequest
1 голос
/ 17 января 2011

Таким образом, класс имеет вид:

class mySafeData
{
public:
  mySafeData() : myData(0), changed( false )
  {
  }

  void Set(int i) 
  {
    boost::mutex::scoped_lock lock(myMutex);
    myData = i; // set the data
    changed = true; // mark as changed
    myCondvar.notify_one(); // notify so a reader can process it
  }

  void Get( int& i)
  {
    boost::mutex::scoped_lock lock(myMutex);
    while( !changed )
    {
       myCondvar.wait( lock );
    } 
    i = myData;
    changed = false; // mark as read
    myCondvar.notify_one(); // notify so the writer can write if necessary
  }
 private:
   int myData;
   boost::mutex myMutex;
   boost::condition_variable myCondvar;
   bool changed;
};

И один поток в цикле вызывает Set.И 3 или более потоков, вызывающих Get, как заставить все потоки, вызывающие Get, фактически получать данные (каждый поток должен Get данных только после вызова Set) (кажется, что только первый «читатель» вызываетGet получает данные)?

обновление будет это делать?:

class mySafeData
{
public:
  mySafeData() : myData(0)
  {
  }

  void Set(int i) 
  {
    boost::mutex::scoped_lock lock(myMutex);
    myData = i; // set the data
  }

  void Get( int& i)
  {
    boost::mutex::scoped_lock lock(myMutex);
    i = myData;

  }
 private:
   int myData;
   boost::mutex myMutex;
};

Ответы [ 2 ]

3 голосов
/ 17 января 2011

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

Кроме того, переменная changed вам не помогает;это позволяет только одному потоку увидеть изменения.Удалите это также.

1 голос
/ 17 января 2011

На самом деле, это странный подход к вызову notify_one() в ридере (Get)!Если вы хотите, чтобы ваши читатели ждали, пока что-то будет установлено, вам нужно что-то вроде этого:

 void Set(int i) 
  {
    boost::mutex::scoped_lock lock(myMutex);
    myData = i; // set the data
    ++stateCounter;  // some int to track state chages
    myCondvar.notify_all(); // notify all readers
  }

  void Get( int& i)
  {
    boost::mutex::scoped_lock lock(myMutex);
    // copy the current state
    int cState = stateCounter;
    // waits for a notification and change of state
    while (stateCounter == cState)
      myCondvar.wait( lock );
  }

Теперь вызов Get будет эффективно ждать, пока не произойдет действительное изменение состояния.Однако этот подход (с условиями) склонен к таким проблемам, как ложные пробуждения (которые должны обрабатываться циклом), потерянные уведомления и т. Д. Вам нужно найти лучшую модель для этого (все это звучит как случай очереди на поток).

...