I found out that this piece of code doesn't work as intended:
#pragma pack(push, 1)
class myclass {
protected:
bool mycrasher[1];
std::mutex mtx;
std::condition_variable cv;
void thread_func() {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::chrono::milliseconds timeout(1000);
std::unique_lock<std::mutex> l(mtx, std::defer_lock);
while (true) {
auto now = std::chrono::system_clock::now();
l.lock();
while (true) {
std::cout << "Waiting..." << std::endl;
auto result = cv.wait_until(l, now + timeout);
std::cout << "Timed out..." << std::endl;
if (result == std::cv_status::timeout)
break;
}
l.unlock();
}
}
public:
myclass() {
std::lock_guard<std::mutex> l(mtx);
std::thread *t = new std::thread(&myclass::thread_func, this);
t->detach();
};
void start() {
std::cout << "myclass started." << std::endl;
std::cout << "sizeof(std::mutex) = " << sizeof(std::mutex) << std::endl;
std::cout << "sizeof(std::condition_variable) = " << sizeof(std::condition_variable) << std::endl;
}
};
#pragma pack(pop)
int main() {
myclass x;
x.start();
std::this_thread::sleep_for(std::chrono::seconds(60));
}
I expected the code to wait for one second on the cv.wait_until
call and then repeat, but is simply hangs on the call. The issue (intuitively) goes away if I remove the #pragma
directives, because I'm packing the mutex and the CV. However, when I run this code I get:
myclass started.
sizeof(std::mutex) = 40
sizeof(std::condition_variable) = 48
with or without the pragma
, so it seems the packing is not the real problem.
In addition, I discovered that if I align the mycrasher
variable to a 4-bytes boundary the problem disappears as well. Likewise, if I move the variable after the std::condition_variable cv
declaration the problem disappears, but when moved between std::mutex mtx
and std::condition_variable cv
it still persists.
Why the snippet hangs on the cv.wait_until
call when the CV is not properly aligned? A performance hit would be expected, but not a plain stall.
Aucun commentaire:
Enregistrer un commentaire