CK_SEQUENCE(3)
β¨ ck_sequence β sequence locks (yes bestie, the seqlock page) β¨
okay so this is ck_sequence(3), from the Concurrency Kit manual, and it covers the whole girl squad of functions: ck_sequence_init, ck_sequence_read_begin, ck_sequence_read_retry, ck_sequence_write_begin, and ck_sequence_write_end. sequence locks, periodt. π
π LIBRARY π
Concurrency Kit β link it with libck, aka -lck. π«Ά
πΈ SYNOPSIS πΈ
#include <ck_sequence.h>
ck_sequence_t seqlock = CK_SEQUENCE_INITIALIZER;
void
ck_sequence_init(ck_sequence_t *sq);
unsigned int
ck_sequence_read_begin(const ck_sequence_t *sq);
bool
ck_sequence_read_retry(const ck_sequence_t *sq, unsigned int version);
void
ck_sequence_write_begin(ck_sequence_t *sq);
void
ck_sequence_write_end(ck_sequence_t *sq);
π¦ DESCRIPTION π¦
So here's the vibe: you reach for ck_sequence when you've got a small amount of data, that data cannot be accessed atomically, and you need to sync it up with readers in a way that never blocks a single writer. That's the whole fantasy. β¨
And the readers? They get to run their read-side critical sections with zero atomic operations. literally nothing. no atomics. living rent free. π
Now, the rules of the game, and you do have to follow them:
- A
ck_sequence_tmust be initialized before use. No skipping this. - You can initialize it two ways: the static initializer
CK_SEQUENCE_INITIALIZER, or the functionck_sequence_init(). Pick your fighter. π - Before a reader tries to read data that might be getting concurrently modified, it must first save the return value of
ck_sequence_read_begin(). do not lose that value bestie, it's your receipt. - While (or after) a reader has finished copying the data associated with a
ck_sequence_t, it must pass that earlier return value intock_sequence_read_retry(). - If
ck_sequence_read_retry()returnstrue, then your copy of the data may be inconsistent, and the whole read process must be retried. π it's giving "try again". - Writers, listen: you must rely on your own synchronization primitives. ck_sequence is not doing that part for you, that's on you. π
- Once a writer has entered its respective critical section, it must call
ck_sequence_write_begin()to signal its intent to update the data protected by theck_sequence_t. - Before the writer leaves that critical section, it must execute
ck_sequence_write_end()to indicate that the updates have left the respective objects in a consistent state. π«Ά
no cap, if you skip the begin/end pair your readers are gonna have a bad time and it's gonna be your fault.
π EXAMPLE π
okay here's the whole thing in action, main character energy:
#include <ck_sequence.h>
#include <stdlib.h>
static struct example {
int a;
int b;
int c;
} global;
static ck_sequence_t seqlock = CK_SEQUENCE_INITIALIZER;
void
reader(void)
{
struct example copy;
unsigned int version;
/*
* Attempt a read of the data structure. If the structure
* has been modified between ck_sequence_read_begin and
* ck_sequence_read_retry then attempt another read since
* the data may be in an inconsistent state.
*/
do {
version = ck_sequence_read_begin(&seqlock);
copy = global;
} while (ck_sequence_read_retry(&seqlock, version));
/*
* The previous may also be expressed using CK_SEQUENCE_READ.
* Generally recommend to only use ck_sequence_read_retry
* if you would like to detect a conflicting write at some
* higher granularity.
*/
CK_SEQUENCE_READ(&seqlock, &version) {
copy = global;
}
return;
}
void
writer(void)
{
for (;;) {
ck_sequence_write_begin(&seqlock);
global.a = rand();
global.b = global.a + global.b;
global.c = global.b + global.c;
ck_sequence_write_end(&seqlock);
}
return;
}
see how the reader just loops on ck_sequence_read_retry(&seqlock, version) until it stops being true? obsessed. and note the comment about CK_SEQUENCE_READ β generally you're recommended to only reach for ck_sequence_read_retry if you want to detect a conflicting write at some higher granularity. iykyk. πΈ
π SEE ALSO π
ck_brlock(3)ck_bytelock(3)ck_rwlock(3)
and if you want even more, additional information is available at http://concurrencykit.org/ π
k that's the whole page, bestie. this one was dated July 26, 2013, it lives in section 3 as ck_sequence(3), and it's part of the Concurrency Kit docs. go forth and seqlock responsibly. π
β¨π¦
π¦ where this page comes from
- alpine 3.24: ck-doc 0.7.2-r1 Β· BSD-2-Clause AND Apache-2.0
- debian bookworm: libck-dev 0.7.1-10 Β· BSD-2-Clause
- debian trixie: libck-dev 0.7.2-6 Β· BSD-2-Clause
- epel 10: ck-devel 0.7.2-1.el10_1 Β· BSD-2-clause AND Apache-2.0 AND BSD-3-clause
- epel 9: ck-devel 0.7.0-10.el9 Β· BSD
- fedora 43: ck-devel 0.7.2-2.fc43 Β· BSD-2-clause AND Apache-2.0 AND BSD-3-clause
- fedora 43: ck-devel 0.7.2-2.fc43 Β· BSD-2-clause AND Apache-2.0 AND BSD-3-clause
- fedora 44: ck-devel 0.7.2-4.fc44 Β· BSD-2-clause AND Apache-2.0 AND BSD-3-clause
- fedora 44: ck-devel 0.7.2-4.fc44 Β· BSD-2-clause AND Apache-2.0 AND BSD-3-clause
- nixos 26.05: ck 0.7.2
- nixpkgs unstable: ck 0.7.2
- opensuse-leap 16.0: ck-devel 0.7.2-bp160.1.9 Β· Apache-2.0 AND BSD-2-Clause
- opensuse-leap 16.0: ck-devel 0.7.2-bp160.1.9 Β· Apache-2.0 AND BSD-2-Clause
- opensuse-leap 16.0: ck-devel 0.7.2-bp160.1.9 Β· Apache-2.0 AND BSD-2-Clause
- ubuntu jammy: libck-dev 0.7.1-6ubuntu2 Β· BSD-2-Clause
- ubuntu noble: libck-dev 0.7.1-13build1 Β· BSD-2-Clause
- ubuntu questing: libck-dev 0.7.2-5ubuntu1
- ubuntu resolute: libck-dev 0.7.2-5ubuntu2 Β· BSD-2-Clause
- ubuntu stonking: libck-dev 0.7.2-11 Β· BSD-2-Clause
- Copyright 2013 Samy Al Bahra
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms