Как проверить, заблокирован ли поток - PullRequest
0 голосов
/ 30 октября 2018

Я надеюсь проверить, заблокирован ли поток с помощью библиотеки boost.thread. Я написал следующие коды, чтобы проверить это.

worker.h

#pragma once

#include <boost/thread.hpp>

class Worker
{
  private:
    boost::thread *_thread;
    boost::thread *_checker_thread;
    boost::condition_variable _cond;
    boost::mutex _mutex;
    bool _run;
    int _id;

  public:
    Worker(int id);
    ~Worker();

    void initialize();
    void start();
    void join();

    static unsigned process(void *param);
    static unsigned check_running(void *param);
};

worker.cpp:

#include "worker.h"
#include <iostream>
#include <boost/chrono.hpp>

Worker::Worker(int id) : _thread(nullptr)
{
  _id = id;
}

Worker::~Worker()
{
  std::cout << "Invoked destructor()" << std::endl;

  if (_thread) {
    delete _thread;
    _thread = nullptr;
  }
}

void Worker::initialize()
{
  std::cout << "Invoked initialize()" << std::endl;

  boost::thread::attributes attrs;
  _run = true;

  try {
    _thread = new boost::thread(attrs, boost::bind(Worker::process, this));
    _checker_thread = new boost::thread(attrs, boost::bind(Worker::check_running, this));
  } catch(...) {
    std::cerr << "Begin thread error" << std::endl;

    if (_thread) {
      delete _thread;
      _thread = nullptr;
    }

    if (_checker_thread) {
      delete _checker_thread;
      _checker_thread = nullptr;
    }
  }
}

void Worker::start()
{
  std::cout << "Invoked start()" << std::endl;
  _cond.notify_one();
}

void Worker::join()
{
  std::cout << "Invoked join()" << std::endl;

  if (_thread) {
    _thread->join();
  }
}

unsigned Worker::process(void *param)
{
  std::cout << "Invoked process()" << std::endl;

  Worker *worker = (Worker*)param;
  boost::unique_lock<boost::mutex> lock(worker->_mutex);

  while (worker->_run) {
    worker->_cond.wait(lock);
    std::cout << "Start process" << std::endl;

    for (int i = 0; i < 20; i++) {
      boost::this_thread::sleep_for(boost::chrono::milliseconds{1});
      std::cout << i << std::endl;
    }

    worker->_run = false;
  }

  return 0;
}

unsigned Worker::check_running(void *param)
{
  Worker *worker = (Worker*)param;

  std::cout << "Start check running" << std::endl;

  while (worker->_run) {
    if (worker->_mutex.try_lock()) {
      std::cout << '-';
      worker->_mutex.unlock();
    } else {
      std::cout << '+';
    }

    boost::this_thread::sleep_for(boost::chrono::milliseconds{1});
  }

  return 0;
}

main.cpp:

#include "worker.h"
#include <iostream>

int main()
{
  Worker worker(99);

  worker.initialize();

  for (int i = 0; i < 26; i++)
  {
    if (i == 5)
    {
      worker.start();
    }

    boost::this_thread::sleep_for(boost::chrono::milliseconds{1});
    std::cout << static_cast<char>(i + 'a') << std::endl;
  }

  worker.join();

  return 0;
}

Этот код имеет 3 темы:

  1. Печать алфавита от a до z в main ().
  2. Вывести число от 0 до 19 в Worker :: process (). Запускается после печати «е».
  3. Проверьте, заблокирован ли поток номера печати в Worker :: check_running (). Если он заблокирован, он печатает «+», иначе «-».

В Worker :: check_running () я использовал mutex.try_lock (), чтобы проверить, заблокирован ли поток. Но в этом случае mutex.unlock () должен быть вызван.

Как я могу сделать этот код в стиле RAII? Я имею в виду, что хочу использовать другой шаблон блокировки, такой как boost :: unique_lock <>, чтобы не пропустить mutex.unlock ().


@ Майлз Буднек,

Спасибо за ваш ответ.

Я применил ваш ответ, но он показал другой результат.

Мои коды показывают результат, как показано ниже:

Invoked initialize()
Invoked process()Start check running

-a
-b
-c
-d
-e
Invoked start()
Start process
+f
+0
g
+1
h
+2
i

...

17
x
+18
y
+19
z
Invoked join()
Invoked destructor()

Ваши коды действуют следующим образом:

Invoked initialize()
Invoked process()
Start check running
-a
-b
-c
--d
-e
Invoked start()
-f
-g
-h

...

-x
-y
-z
Invoked join()
---------------- ... -----------Start process
++0
+1
+2
+3
+4
5
+6
+7

...

+18
+19
Invoked destructor()

Не могли бы вы проверить это, пожалуйста?

1 Ответ

0 голосов
/ 30 октября 2018

Вы можете использовать boost::unique_lock с параметром boost::try_to_lock:

while (worker->_run) {
  boost::unique_lock<boost::mutex> lock(worker->_mutex, boost::try_to_lock);
  if (lock.owns_lock()) {
    std::cout << '-';
  } else {
    std::cout << '+';
  }

  boost::this_thread::sleep_for(boost::chrono::milliseconds{1});
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...