https://github.com/avakar/intrusive_lfstack
Lock-free, allocation-free, header-only, composition-based stack for C++11
https://github.com/avakar/intrusive_lfstack
cpp lock-free-stack
Last synced: about 2 months ago
JSON representation
Lock-free, allocation-free, header-only, composition-based stack for C++11
- Host: GitHub
- URL: https://github.com/avakar/intrusive_lfstack
- Owner: avakar
- License: 0bsd
- Created: 2021-10-30T10:12:43.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2021-10-30T16:16:31.000Z (over 3 years ago)
- Last Synced: 2025-04-12T19:57:44.889Z (about 2 months ago)
- Topics: cpp, lock-free-stack
- Language: C++
- Homepage:
- Size: 3.91 KB
- Stars: 2
- Watchers: 3
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# intrusive_lfstack
Lock-free, allocation-free, header-only, composition-based stack for C++11.
## Getting started
Add `lfstack_node` as a member to whatever struct you want to keep in a stack.
Then, you can push and pop _references_ to that struct.```cpp
#include
using namespace avakar::intrusive;struct X {
// A node maintains a membership in at most one lfstack.
lfstack_node node;
};int main()
{
// You must specify the node to be used by each stack.
lfstack st;X x;
st.push(x);// You can check if a node is pushed in a stack.
assert(x.node.attached());// If the stack is non-empty, `pop` removes the most recently inserted
// element and returns a pointer to it. Otherwise, it returns `nullptr`.
X * px = st.pop();
assert(px == &x);px = st.pop();
assert(px == nullptr);
}
```Both stacks and nodes are immovable.
If a node is destroyed while attached, the behavior is undefined.
Clearing or destroying a stack will detach all its nodes.## Thread-safety
Member functions `lfstack::push`, `lfstack::pop` and `lfstack_node::attached`
can be invoked simultaneously without data races. The same holds for
simultaneous invocations of `lfstack_node::attached` and the `lfstack`
destructor.A push to `lfstack` synchronizes-with (and therefore happens-before) a pop
of the corresponding node.All operations are lock-free as long as your implementation of `std::atomic`
has lock-free DCAS. On amd64 platforms, this requires cmpxchg16b instruction,
which early 64-bit AMD processors didn't have.
As of today, MSVC's 64-bit implementation does not support lock-free
DCAS regardless of your actual processor.You can check if lfstack is actually lock-free by checking
`lfstack::is_lock_free()` or
`lfstack::is_always_lock_free` (C++17 or newer only).In either case, lfstack is thread-safe.
## CMake integration
Copy this repo into yours, add it as a submodule, or `FetchContent` it.
Either way, make sure this repo is added via `add_subdirectory` or
`FetchContent_MakeAvailable`, then link against `avakar::intrusive_lfstack`.FetchContent(avakar.intrusive_lfstack SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/lfstack")
FetchContent_MakeAvailable(avakar.intrusive_lfstack)# ...
target_link_libraries(mytarget PUBLIC avakar::intrusive_lfstack)