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

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

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

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

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

Ответов (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 завершения.

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

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