Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions test/pthread/test_pthread_proxying_cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ void test_proxy_async() {
// Proxy to looper.
{
queue.proxyAsync(looper.native_handle(), [&]() {
i = 2;
{
std::unique_lock<std::mutex> lock(mutex);
i = 2;
}
executor = std::this_thread::get_id();
cond.notify_one();
});
Expand All @@ -68,7 +71,10 @@ void test_proxy_async() {
// Proxy to returner.
{
queue.proxyAsync(returner.native_handle(), [&]() {
i = 3;
{
std::unique_lock<std::mutex> lock(mutex);
i = 3;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Despite reading you description I've having trouble seeing how putting a lock around this one assignment fixes the issue. Would making i and atomic also fix the issue?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After reading https://stackoverflow.com/questions/17101922/do-i-have-to-acquire-lock-before-calling-condition-variable-notify-one I think i understand.. I had never known this about cond vars..

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the lock is important because of the condition variable. The condition variable needs to atomically check the condition and block if the condition is not met. The mechanism for combining those into an atomic action is the lock, so if the condition can change without the lock being held, the condition variable doesn't work as intended.

executor = std::this_thread::get_id();
cond.notify_one();
});
Expand Down Expand Up @@ -164,7 +170,10 @@ void test_proxy_async_with_callback(void) {
queue.proxyAsyncWithCallback(
looper.native_handle(),
[&]() {
i = 2;
{
std::unique_lock<std::mutex> lock(mutex);
i = 2;
}
executor = std::this_thread::get_id();
cond.notify_one();
},
Expand All @@ -184,7 +193,10 @@ void test_proxy_async_with_callback(void) {
queue.proxyAsyncWithCallback(
returner.native_handle(),
[&]() {
i = 3;
{
std::unique_lock<std::mutex> lock(mutex);
i = 3;
}
executor = std::this_thread::get_id();
cond.notify_one();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to hold the lock when calling notify too?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it's actually a pessimization to hold the lock while calling notify because then the other thread wakes up just to immediately block on acquiring the lock.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL!

},
Expand Down