У меня есть dll, которая имеет высокоприоритетные функции, которые работают в потоке с высоким приоритетом. Эта DLL должна сообщить о прогрессе. В основном используется система обратного вызова. Проблема в том, что dll не контролирует количество времени, которое должен выполнить обратный вызов для завершения. Это означает, что высокоприоритетные функции зависят от реализации обратного вызова, который неприемлем.Сделать область блокировки меньше в потоковом очереди
Идея состоит в том, чтобы иметь класс между ними, который буферизует уведомления о ходе и вызывает обратный вызов.
Я новичок в C++ 11, и это функция потоковой передачи и пытается найти возможности. У меня есть реализация, но у меня есть проблема (по крайней мере, тот, который я вижу сейчас). Когда поток оживает после ожидания мьютекса, он снова приобретается и остается до следующего ожидания. Это означает, что блокировка сохраняется до тех пор, пока продолжается продолжительная операция. Добавление прогресса будет заблокировано здесь. В основном много кода без выигрыша. Я подумал об изменении кода, но я не знаю, правильная ли это реализация.
Progress progress = queue.front();
queue.pop();
lock.unlock();
// Do lengthy operation with progress
lock.lock();
Я думаю, что мне нужно ждать переменную условия, но это не должно быть связано с блокировкой. Я не понимаю, как это можно сделать. Пропустить фиктивную блокировку и использовать другую блокировку для защиты очереди? Как эта проблема должна решаться в C++ 11?
заголовок файла
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <queue>
#include "Error.h"
#include "TypeDefinitions.h"
struct Progress
{
StateDescription State;
uint8 ProgressPercentage;
};
class ProgressIsolator
{
public:
ProgressIsolator();
virtual ~ProgressIsolator();
void ReportProgress(const Progress& progress);
void Finish();
private:
std::atomic<bool> shutdown;
std::condition_variable itemAvailable;
std::mutex mutex;
std::queue<Progress> queue;
std::thread worker;
void Work();
};
CPP файл
#include "ProgressIsolator.h"
ProgressIsolator::ProgressIsolator() :
shutdown(false),
itemAvailable(),
worker([this]{ Work(); }),
progressCallback(progressCallback),
completedCallback(completedCallback)
{
// TODO: only continue when worker thread is ready and listening?
}
ProgressIsolator::~ProgressIsolator()
{
Finish();
worker.join();
}
void ProgressIsolator::ReportProgress(const Progress& progress)
{
std::unique_lock<std::mutex> lock(mutex);
queue.push(progress);
itemAvailable.notify_one();
}
void ProgressIsolator::Finish()
{
shutdown = true;
itemAvailable.notify_one();
}
void ProgressIsolator::Work()
{
std::unique_lock<std::mutex> lock(mutex);
while (!shutdown)
{
itemAvailable.wait(lock);
while (!queue.empty())
{
Progress progress = queue.front();
queue.pop();
// Do lengthy operation with progress
}
}
}
Я вижу, где вы идете, но это не дает ту же функциональность. Если нажимается заголовок и в очереди находится более одного элемента, а затем вызывается метод Finish, это приведет к тому, что не будут выгружены все элементы. Из некоторого дальнейшего чтения я думаю, что ожидание требует блокировки, но блокировка существует только для защиты переменной условия, а не для защиты очереди. –