nilcpp is (will be) a collection of small C++ libraries that raises the level of abstraction and makes it easier to write safer code. The implementations are intended to be simple, easy to understand and easy to fork and modify for specific uses. Performance, while important, is a secondary concern to simplicity and safety for this collection.
Currently, there's only one module, async. Stay tuned for updates.
async provides higher level abstractions for working with multi-threaded code in C++ beyond the default STL constructs. It promotes simpler and safer code such that non-thread-safe operations don't compile at all, without limiting overall utility.
nil::atomic is similar to std::atomic. It couples a mutex with any type T and the public API only provides thread-safe access to the underlying data.
nil::atomic_baseis templated on the mutex and lock types, so you can use it with STL, Boost or other locksnil::atomicis a convenience alias for usingstd::mutexandstd::lock_guard
- It currently only works with
copyabletypes- This is because
peek, the only "normal" accessor, returns a copy, making it hard to work with non-copyable types
- This is because
- It provides a generic
applymethod which executes any function while locked, allowing for multi-statement thread-safe execution when needed
nil::async::optional is the same as nil::atomic with an additional nullstate for the underlying type. As with nil::optional, it only provides a thread-safe API.
nil::async::optional_baseis templated on the optional type, allowing you to work with std::optional, boost::optional or othersnil::async::optionalis a convenience alias forstd::optional
- It will also be templated on the mutex type, so you can use it with any mutex-like type
- currently, it uses
std::mutex
- currently, it uses
- In addition to
pushandpeek, it also provides apopto leave the data behind in a null-state - It works with move-only types, since
popcan return a moved value.peekis non usuable if the type is not copyable - It also has
apply, which works the same asnil::atomic
nil::atomic_rw allows for multiple concurrent readers and exclusive writers. It wraps any type T with a shared_mutex and provides RAII read/write proxies through public API
nil::atomic_rw_baseis templated on mutex and read/write lock type, so it works with STL, Boost and othersnil::atomic_rwis convenience alias forstd::shared_mutex,std::shared_lockandstd::unique_lock
- terse, pointer-like semantics for obtaining read proxies. All proxies are RAII, they release lock on destruction
- proxies provide pointer-like access to underlying data, either read-only for read proxies, or read/write for write proxies.
nil::async::container allows you to wrap STL-like containers (vector/deque/list) and provides a thread-safe API to underlying data. The function names are the same, so it can be a (near) drop-in replacement.
nil::async::container_baseis templated on the mutex and lock types to work with STL, Boost or othersnil::async::vector,nil::async::dequeandnil::async::listare convenience aliases for their respective STL containers
- provides most functions of STL containers, with similar behaviour
- no calls return refs, as that would not be thread-safe. Instead, you get copies
- no iterators, because they are defacto refs
extractdoesn't return nodes, but rather just the (moved) element
- container type used doesn't need to be STL or Boost, and doesn't need to implement all functions
- if you attempt to use an unimplemented function, it won't compile (no runtime issues or UB)
- generic
applyfunction for handling anything the normal API doesn't already do. Works the same asnil::atomic::apply(...) - comes with some traits for SFINAE or similar purposes