-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix thread unsafety in occasional logging when using std::atomic #808
Closed
Nimrod0901
wants to merge
5
commits into
google:master
from
Nimrod0901:occasional_logging_thread_safety
Closed
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
ba4ad45
fix thread unsafety in occasional logging when using std::atomic
Nimrod0901 51d5348
replace fetch_add with ++
Nimrod0901 30f8a84
use unsigned int to avoid UB
Nimrod0901 821a5b6
add unittest for multiple thread occasional logging for C++11 and later
Nimrod0901 eeb85a2
replace implicit conversion with explicit one
Nimrod0901 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not clear to me why changing to
fetch_add
provides a solution here.op++
also callsfetch_add
albeit with different memory ordering. Consequently, you cannot avoid the problem you are trying to solve. To be able to, you would need to perform all the involved operations atomically by protecting concurrent access in a critical section.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem was "a series of atomic operations of
LOG_OCCURRENCES_MOD_N
, but in whole, they are not atomic, which unexpected". Here only theLOG_OCCURRENCES
is static, the only place we need to protect. Specifically, we only do one atomic operationfetch_add
onLOG_OCCURRENCES
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My question is: in what way do the changes fix the problem? The operations are still not atomic as a whole.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. But they don't need to be. There is only one operation that needs to be atomic, access to the static variable
LOG_OCCURRENCES
.For every use of this macro (under different threads), a unique
LOG_OCCURRENCES
value is assigned, incremented by 1. We use a local variableLOG_OCCURRENCES_MOD_N
to get the reminder of% n
. By now, there is no need for protection or being atmoic. It can be written likeThey are the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You cannot do that. Once
LOG_OCCURRENCES
overflows you will hit undefined behavior.Also, the change from
op++
tofetch_add
is not clear to me. Why is this necessary? If you need the previous value, you can use the post increment.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main idea is to promise every call can have the exact value in the
if
condition statements to represent if it should be logged. When the static atomic variable isfetch_add
to a local variable, the state is recorded. You'll never get the same value.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. This may need more consideration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not correct. With post increment you will get the previous value since it essentially calls
fetch_add
as well.Please refer to the documentation of
std::atomic::op++
before we continue the discussion. Thanks.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, It's my bad. You're right. I agree there is no need to use
fetch_add
.++
is enough.Use
atomic_uint
instead. Unsigned integer overflow is not a UB. Will this help?