-
-
Notifications
You must be signed in to change notification settings - Fork 216
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
Seqlock implementation extract #664
Conversation
🤖 Upon creation, pull request description does not have a link to an issue. If there is a related issue, please add it to the description using any of the supported formats. |
Oh wait... the Timer is using Seqlock, so it's clearly uncovered a bug in my change. |
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.
Thanks!
void* val_; | ||
size_t val_size_; |
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.
If we will store pointer and size in members, then every call (try_store, try_load, etc) will involve two additional reads from memory, and the whole operation will depend on these reads.
If, instead, we will pass &val
and sizeof(val)
to these methods as arguments, then chances are that no memory reads are needed: &val
can be calculated as this + offset
, and this is likely already in register, and sizeof(val)
is a constant. And then on many architectures like x86_64 ARM function arguments will be passed via registers.
In our code base Seqlock is often used for small frequently used variables, like counters. E.g. seqlock is a replacement for 64-bit atomics (because 64-bit atomics are not available everywhere). So it makes sense to keep seqlock overhead low and comparable with a regular atomic.
static void | ||
volatile_copy_(volatile void* dst, const volatile void* src, size_t val_size); |
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.
I guess we can move this method into .cpp file in anon namespace.
#include "roc_core/seqlock_impl.h" | ||
|
||
#include "roc_core/atomic_ops.h" | ||
#include "roc_core/cpu_instructions.h" |
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.
nit: extra empty line.
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.
Oh... we don't want to include the header related to the cpp file first?
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.
Oh, it was intentional. Yes, current "defacto" code style uses:
<one block with stdlib headers>
<one block with external libs headers>
<one block with roc headers>
e.g.:
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
#include "roc_core/array.h"
#include "roc_core/time.h"
26f90d6
to
f8e31b9
Compare
Thanks! Small refactoring: 3ebb8c8 (see commit message for details) |
Why
For #599
What
Testing
There are tests.