доступ к переменной-члену объекта потока boost

Я использую объект для запуска потока повышения, и у него есть некоторые общедоступные переменные-члены, которые я изменяю в потоке (в операторе ()). Как я могу получить доступ к переменным-членам объекта извне потока?

Я попытался использовать мьютекс (определенный в классе объекта), который заблокирован как в операторе () объекта, так и снаружи, но, похоже, он не работает.

Вот код объекта потока:

struct Mouse
{
  int x, y;
  string port;

  boost::mutex mutex;

  Mouse(const string& p) : port(p) { x = y = 0; }
  Mouse(const Mouse& m) : mutex() { x = m.x; y = m.y; port = m.port; }

  void operator()()  
  {
    ifstream ifs;
    ifs.open (port.c_str(), ios::binary );
    if (!ifs.is_open())
    {
      cout << "Impossible d'ouvrir " << port.c_str() << "\n";
      exit(0);
    }
    while (true) //modify x, y in infinit loop
      {
    char buf[3];
    ifs.read(buf, 3);
        unsigned char * msg = (unsigned char *) buf;
    unsigned char xsign = (msg[0]>>4) & 1;
    unsigned char ysign = (msg[0]>>5) & 1;
        unsigned char always1 = (msg[0]>>3) & 1;
    short dx = msg[1] - 256*xsign;
    short dy = msg[2] - 256*ysign;
    {
      boost::mutex::scoped_lock lock(mutex);
      x += abs(dx);
      y += dy;
    }
      }
  }
};

И здесь я пытаюсь получить доступ к переменным x и y мыши:

  {
    boost::mutex::scoped_lock leftlock(leftMouse.mutex);
    xLeft = leftMouse.x;
    yLeft = leftMouse.y;
  }
  {
    boost::mutex::scoped_lock rightlock(rightMouse.mutex);
    xRight = rightMouse.x;
    yRight = rightMouse.y;
  }
  cout << xRight << " " << yRight << endl;  //this always prints 0 0

person Al.    schedule 23.02.2009    source источник
comment
Не могли бы вы опубликовать код, чтобы увидеть, как именно это не работает?   -  person Diego Sevilla    schedule 24.02.2009


Ответы (2)


boost::thread копирует переданную функцию потока во внутреннее хранилище, поэтому, если вы начнете свой поток таким образом, поток будет работать с другой копией mouse:

int main() {
  Mouse mouse("abc.txt");
  boost::thread thr(mouse); // thr gets a copy of mouse
  ...
  // thread changes it's own copy of mouse
  ...
}

Вместо этого вы можете использовать boost::ref для передачи ссылки на существующий объект:

  Mouse mouse("abc.txt");
  boost::thread thr(boost::ref(mouse)); // thr gets a reference of mouse

В этом случае thr изменит глобальный объект mouse, но вы должны убедиться, что mouse не выйдет за пределы области видимости или не будет уничтожен до завершения thr.

person sth    schedule 23.02.2009

Хорошо, теперь я вижу это яснее. Некоторые советы, глядя на ваш код:

  1. Не открывайте внутренние мьютексы.
  2. Напишите операции доступа, которые блокируют и разблокируют мьютекс. Таким образом, вам не нужно полагаться на пользователя вашего класса для эффективной блокировки (и разблокировки) мьютекса.
  3. Прочитайте данные из файла перед потоком. Вероятно, чтение блокируется или другой поток слишком медленно получает данные. Если вы прочитаете данные раньше, а затем запустите поток, все данные будут прочитаны к тому времени, когда клиенты получат доступ к данным потока.
person Diego Sevilla    schedule 23.02.2009