Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
seqlock.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Roc Streaming authors
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 */
8
9//! @file roc_core/seqlock.h
10//! @brief Seqlock.
11
12#ifndef ROC_CORE_SEQLOCK_H_
13#define ROC_CORE_SEQLOCK_H_
14
17
18namespace roc {
19namespace core {
20
21//! Seqlock.
22//!
23//! Provides safe concurrent access to a single value.
24//! Provides sequential consistency.
25//! Optimized for infrequent writes and frequent reads.
26//! Writes are lock-free and take priority over reads.
27//!
28//! See details on the barriers here:
29//! https://elixir.bootlin.com/linux/latest/source/include/linux/seqlock.h
30//! https://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf
31template <class T> class Seqlock : public NonCopyable<> {
32public:
33 //! Initialize with given value.
34 explicit Seqlock(T value)
35 : val_(value) {
36 }
37
38 //! Load value version.
39 //! Wait-free.
40 inline seqlock_version_t version() const {
41 return impl_.version();
42 }
43
44 //! Store value.
45 //! Can be called concurrently, but only one concurrent call will succeed.
46 //! Is both lock-free and wait-free, i.e. it never waits for sleeping threads
47 //! and never spins.
48 //! After this call returns, any thread calling wait_load() is guaranteed to
49 //! get the updated value, and try_load() is guaranteed either return the
50 //! updated value or fail (if changes are not fully published yet).
51 inline bool try_store(const T& value) {
53 return impl_.try_store(ver, &val_, sizeof(val_), &value);
54 }
55
56 //! Store value.
57 //! Like try_store(), but also returns updated version.
58 inline bool try_store_v(const T& value, seqlock_version_t& ver) {
59 return impl_.try_store(ver, &val_, sizeof(val_), &value);
60 }
61
62 //! Store value.
63 //! Can NOT be called concurrently, assumes that writes are serialized.
64 //! Is both lock-free and wait-free, i.e. it never waits for sleeping threads
65 //! and never spins.
66 //! After this call returns, any thread calling wait_load() is guaranteed to
67 //! get the updated value, and try_load() is guaranteed either return the
68 //! updated value or fail (if changes are not fully published yet).
69 inline void exclusive_store(const T& value) {
71 impl_.exclusive_store(ver, &val_, sizeof(val_), &value);
72 }
73
74 //! Store value.
75 //! Like exclusive_store(), but also returns updated version.
76 inline void exclusive_store_v(const T& value, seqlock_version_t& ver) {
77 impl_.exclusive_store(ver, &val_, sizeof(val_), &value);
78 }
79
80 //! Try to load value.
81 //! Returns true if the value was loaded.
82 //! May return false if concurrent store is currently in progress.
83 //! Is both lock-free and wait-free, i.e. it never waits for sleeping threads
84 //! and never spins.
85 inline bool try_load(T& value) const {
87 return impl_.try_load_repeat(ver, &val_, sizeof(val_), &value);
88 }
89
90 //! Try to load value and version.
91 //! Like try_load(), but also returns version.
92 inline bool try_load_v(T& value, seqlock_version_t& ver) const {
93 return impl_.try_load_repeat(ver, &val_, sizeof(val_), &value);
94 }
95
96 //! Load value.
97 //! May spin until concurrent store completes.
98 //! Is NOT lock-free (or wait-free).
99 inline T wait_load() const {
100 T value;
102 impl_.wait_load(ver, &val_, sizeof(val_), &value);
103 return value;
104 }
105
106 //! Load value and version.
107 //! Like wait_load(), but also returns version.
108 inline void wait_load_v(T& value, seqlock_version_t& ver) const {
109 impl_.wait_load(ver, &val_, sizeof(val_), &value);
110 }
111
112private:
113 T val_;
114 SeqlockImpl impl_;
115};
116
117} // namespace core
118} // namespace roc
119
120#endif // ROC_CORE_SEQLOCK_H_
Base class for non-copyable objects.
Definition noncopyable.h:23
Seqlock implementation class.
bool try_store(seqlock_version_t &ver, void *current_value, size_t value_size, const void *new_value)
Try to store value.
void exclusive_store(seqlock_version_t &ver, void *current_value, size_t value_size, const void *new_value)
Store value.
bool try_load_repeat(seqlock_version_t &ver, const void *current_value, size_t value_size, void *return_value) const
Try to load value and version.
void wait_load(seqlock_version_t &ver, const void *current_value, size_t value_size, void *return_value) const
Load value and version.
seqlock_version_t version() const
Load value version.
bool try_store(const T &value)
Store value. Can be called concurrently, but only one concurrent call will succeed....
Definition seqlock.h:51
bool try_load_v(T &value, seqlock_version_t &ver) const
Try to load value and version. Like try_load(), but also returns version.
Definition seqlock.h:92
void exclusive_store(const T &value)
Store value. Can NOT be called concurrently, assumes that writes are serialized. Is both lock-free an...
Definition seqlock.h:69
void exclusive_store_v(const T &value, seqlock_version_t &ver)
Store value. Like exclusive_store(), but also returns updated version.
Definition seqlock.h:76
seqlock_version_t version() const
Load value version. Wait-free.
Definition seqlock.h:40
Seqlock(T value)
Initialize with given value.
Definition seqlock.h:34
bool try_store_v(const T &value, seqlock_version_t &ver)
Store value. Like try_store(), but also returns updated version.
Definition seqlock.h:58
T wait_load() const
Load value. May spin until concurrent store completes. Is NOT lock-free (or wait-free).
Definition seqlock.h:99
void wait_load_v(T &value, seqlock_version_t &ver) const
Load value and version. Like wait_load(), but also returns version.
Definition seqlock.h:108
bool try_load(T &value) const
Try to load value. Returns true if the value was loaded. May return false if concurrent store is curr...
Definition seqlock.h:85
Shared ownership intrusive pointer.
Definition shared_ptr.h:32
uint32_t seqlock_version_t
Type for holding seqlock value version. Version is changed each value update. May wrap.
Root namespace.
Non-copyable object.
Seqlock implementation.