[英]Why a waiting thread does not wake up after calling notify?
I am trying to simulate a sensor that outputs data at a certain frame rate while another is waiting to have a data ready and when it is ready it copies it locally and processes it.我正在尝试模拟一个以特定帧速率输出数据的传感器,而另一个传感器正在等待准备好数据,当它准备好时,它会在本地复制并处理它。
Sensor sensor(1,1000);
Monitor monitor;
// Function that continuously reads data from sensor
void runSensor()
{
// Initial delay
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
for(int i = 0; i < SIZE_LOOP; i++)
{
monitor.captureData<Sensor>(sensor, &Sensor::captureData);
}
}
// Function that waits until sensor data is ready
void waitSensor()
{
monitor.saveData<Sensor>(sensor, &Sensor::saveData);
}
// Main function
int main()
{
// Threads that reads at some frame rate data from sensor
std::thread threadRunSensor(runSensor);
// Processing loop
for(int i = 0; i < SIZE_LOOP; i++)
{
// Wait until data from sensor is ready
std::thread threadWaitSensor(waitSensor);
// Wait until data is copied
threadWaitSensor.join();
// Process synchronized data while sensor are throwing new data
std::cout << "Init processing (" << sensor.getData() << /*"," << sensor2.getData() << */")"<< std::endl;
// Sleep to simulate processing load
std::this_thread::sleep_for(std::chrono::milliseconds(10000 + (rand() % 1000)));
//std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "End processing" << std::endl;
}
return 0;
}
This is the sensor class.这是传感器 class。 It has two methods.
它有两种方法。 One that generates the data and other that copies the data locally.
一种生成数据,另一种在本地复制数据。
class Sensor
{
private:
int counter;
int id;
int frameRate;
int dataCaptured;
int dataSaved;
public:
Sensor(int f_id, int f_frameRate)
{
id = f_id;
counter = 0;
frameRate = f_frameRate;
};
~Sensor(){};
void captureData()
{
dataCaptured = counter;
counter ++;
std::cout << "Sensor" << id << " (" << dataCaptured << ")"<< std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(frameRate + (rand() % 500)));
};
void saveData()
{
dataSaved = dataCaptured;
std::cout << "Copying sensor" << id << " (" << dataSaved << ")"<< std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1 + (rand() % 5)));
}
int getData()
{
return dataSaved;
}
};
Then there is a class Monitor that ensures these operations are protected to concurrent accesses.然后是一个 class 监视器,可确保这些操作受到保护以防止并发访问。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <cstdlib>
#define SIZE_LOOP 1000
class Monitor
{
private:
std::mutex m_mutex;
std::condition_variable m_condVar;
bool m_isReady;
public:
Monitor()
{
init();
};
~Monitor()
{
};
void init()
{
m_isReady = false;
};
template<class T>
void captureData(T& objectCaptured, void (T::* f_captureFunction_p)())
{
// Lock read
std::unique_lock<std::mutex> lock = std::unique_lock<std::mutex>(m_mutex);
(objectCaptured.*f_captureFunction_p)();
m_isReady = true;
m_condVar.notify_one();
lock.unlock();
};
template<class T>
void saveData(T& objectSaved, void(T::*f_saveFunction_p)())
{
std::unique_lock<std::mutex> lock = std::unique_lock<std::mutex>(m_mutex);
while(!m_isReady)
{
m_condVar.wait(lock);
}
(objectSaved.*f_saveFunction_p)();
m_isReady = false;
lock.unlock();
};
};
Can anyone tell me why the waiting thread does not wakeup if the sensor is notifyng every frame rate?谁能告诉我,如果传感器通知每个帧速率,为什么等待线程不会唤醒?
The idea is having two threads with this workflow:这个想法是在这个工作流中有两个线程:
Finally I found the solution adding a waiting step after the capture to give time to save data最后我找到了解决方案,在捕获后添加了一个等待步骤,以便有时间保存数据
template<class T>
void captureData(T& objectCaptured, void (T::* f_captureFunction_p)())
{
std::unique_lock<std::mutex> lockReady = std::unique_lock<std::mutex>(m_mutexReady, std::defer_lock);
std::unique_lock<std::mutex> lockProcess = std::unique_lock<std::mutex>(m_mutexProcess, std::defer_lock);
// Lock, capture, set data ready flag, unlock and notify
lockReady.lock();
(objectCaptured.*f_captureFunction_p)();
m_isReady = true;
lockReady.unlock();
m_conditionVariable.notify_one();
// Wait while data is ready and it is not being processed
lockReady.lock();
lockProcess.lock();
while(m_isReady && !m_isProcessing)
{
lockProcess.unlock();
m_conditionVariable.wait(lockReady);
lockProcess.lock();
}
lockProcess.unlock();
lockReady.unlock();
};
template<class T>
void saveData(T& objectSaved, void(T::*f_saveFunction_p)())
{
std::unique_lock<std::mutex> lockReady(m_mutexReady, std::defer_lock);
std::unique_lock<std::mutex> lockProcess(m_mutexProcess, std::defer_lock);
// Reset processing
lockProcess.lock();
m_isProcessing = false;
lockProcess.unlock();
// Wait until data is ready
lockReady.lock();
while(!m_isReady)
{
m_conditionVariable.wait(lockReady);
}
// Make a copy of the data, reset ready flag, unlock and notify
(objectSaved.*f_saveFunction_p)();
m_isReady = false;
lockReady.unlock();
m_conditionVariable.notify_one();
// Set processing
lockProcess.lock();
m_isProcessing = true;
lockProcess.unlock();
};
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.