condition_variable 如果在结构内部使用它则不起作用
condition_variable is not working if use it inside structure
如果在结构中使用 condition_variable
则不起作用。如果我将它作为全局变量,一切正常。但是我需要为每个数据包提供一个 condition_variable
,因为我不知道什么时候会收到答复,我需要为每个数据包等待它。我做错了什么?
这是控制台输出:
Wait: 416
StopWait: 423
从中可以看到我收到数据,锁定后解锁线程。
结构
struct Waiting {
bool IsWaiting = false;
mutable std::condition_variable cv;
mutable std::mutex m;
clock_t localCLock = 0;
void Wait() const {
const double ms = Utils::MillisecondsSpent(localCLock);
std::cout << "Wait: " << ms << std::endl;
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [this] { return IsWaiting; });
}
void StopWait() {
const double ms = Utils::MillisecondsSpent(localCLock);
std::cout << "StopWait: " << ms << std::endl;
std::unique_lock<std::mutex> lock(m);
IsWaiting = true;
cv.notify_all();
}
};
struct Packet
{
Packet() : id(0), waiting(new Waiting) {}
int id;
Waiting* waiting;
};
class Map
{
static Map* instance;
Map();
~Map();
Map(const Map&) = delete;
public:
static Map* Instance() {
if (!instance) instance = new Map;
return instance;
}
std::map<int, Packet> packets;
};
线程数
//Send Thread - called first
while(true){
Packet packet;
packet.id = 1;
//some send packet logic here
...
///
Map::Instance()->packets.insert(std::pair<int, Packet>(p.id, p));
Map::Instance()->packets[id].waiting->Wait(); // thread now locked and never unlocks
const Packet received = Map::Instance()->packets[id];
Map::Instance()->packets.erase(id);
}
//Receive Thread - called second
while(true){
//some receive packet logic here
...
///
const Packet packet = ... // receive a packet data;
Map::Instance()->packets[packet.id] = packet;
Map::Instance()->packets[packet.id].answered = true;
Map::Instance()->packets[packet.id].waiting->StopWait(); // i unlock Send Thread, but it won't work
}
撇开同步问题和内存泄漏不谈,每次分配 Packet
时都是按值复制它,并分配一个新的 Waiting
。内存中漂浮着许多不同的悬挂 Waiting
对象,没有理由在一个对象上调用 StopWait
会触发另一个对象的 condition_variable
。
查看我添加的代码注释。
while(true){
// *** PACKET A ***
Packet packet;
packet.id = 1;
//*** PACKET B ***
Map::Instance()->packets.insert(std::pair<int, Packet>(p.id, p));
Map::Instance()->packets[id].waiting->Wait();
}
while(true){
// *** PACKET C ***
const Packet packet = ...
//You are overwriting PACKET B with a copy of PACKET C which is PACKET D.
//Don't you mean to find a packet which has the same id as the received packet instead of overwriting it?
Map::Instance()->packets[packet.id] = packet;
Map::Instance()->packets[packet.id].answered = true;
// There's no reason calling StopWait on PACKET D's Waiting object will release PACKET B.
Map::Instance()->packets[packet.id].waiting->StopWait();
}
condition_variable
则不起作用。如果我将它作为全局变量,一切正常。但是我需要为每个数据包提供一个 condition_variable
,因为我不知道什么时候会收到答复,我需要为每个数据包等待它。我做错了什么?
这是控制台输出:
Wait: 416
StopWait: 423
从中可以看到我收到数据,锁定后解锁线程。
结构
struct Waiting {
bool IsWaiting = false;
mutable std::condition_variable cv;
mutable std::mutex m;
clock_t localCLock = 0;
void Wait() const {
const double ms = Utils::MillisecondsSpent(localCLock);
std::cout << "Wait: " << ms << std::endl;
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [this] { return IsWaiting; });
}
void StopWait() {
const double ms = Utils::MillisecondsSpent(localCLock);
std::cout << "StopWait: " << ms << std::endl;
std::unique_lock<std::mutex> lock(m);
IsWaiting = true;
cv.notify_all();
}
};
struct Packet
{
Packet() : id(0), waiting(new Waiting) {}
int id;
Waiting* waiting;
};
class Map
{
static Map* instance;
Map();
~Map();
Map(const Map&) = delete;
public:
static Map* Instance() {
if (!instance) instance = new Map;
return instance;
}
std::map<int, Packet> packets;
};
线程数
//Send Thread - called first
while(true){
Packet packet;
packet.id = 1;
//some send packet logic here
...
///
Map::Instance()->packets.insert(std::pair<int, Packet>(p.id, p));
Map::Instance()->packets[id].waiting->Wait(); // thread now locked and never unlocks
const Packet received = Map::Instance()->packets[id];
Map::Instance()->packets.erase(id);
}
//Receive Thread - called second
while(true){
//some receive packet logic here
...
///
const Packet packet = ... // receive a packet data;
Map::Instance()->packets[packet.id] = packet;
Map::Instance()->packets[packet.id].answered = true;
Map::Instance()->packets[packet.id].waiting->StopWait(); // i unlock Send Thread, but it won't work
}
撇开同步问题和内存泄漏不谈,每次分配 Packet
时都是按值复制它,并分配一个新的 Waiting
。内存中漂浮着许多不同的悬挂 Waiting
对象,没有理由在一个对象上调用 StopWait
会触发另一个对象的 condition_variable
。
查看我添加的代码注释。
while(true){
// *** PACKET A ***
Packet packet;
packet.id = 1;
//*** PACKET B ***
Map::Instance()->packets.insert(std::pair<int, Packet>(p.id, p));
Map::Instance()->packets[id].waiting->Wait();
}
while(true){
// *** PACKET C ***
const Packet packet = ...
//You are overwriting PACKET B with a copy of PACKET C which is PACKET D.
//Don't you mean to find a packet which has the same id as the received packet instead of overwriting it?
Map::Instance()->packets[packet.id] = packet;
Map::Instance()->packets[packet.id].answered = true;
// There's no reason calling StopWait on PACKET D's Waiting object will release PACKET B.
Map::Instance()->packets[packet.id].waiting->StopWait();
}