An open API service indexing awesome lists of open source software.

https://github.com/macmade/cppatomic

Replacement of std::atomic supporting non trivially-copyable types
https://github.com/macmade/cppatomic

atomic atomicity c-plus-plus generic lock

Last synced: about 1 year ago
JSON representation

Replacement of std::atomic supporting non trivially-copyable types

Awesome Lists containing this project

README

          

CPPAtomic
=========

[![Build Status](https://img.shields.io/github/actions/workflow/status/macmade/CPPAtomic/ci-mac.yaml?label=macOS&logo=apple)](https://github.com/macmade/CPPAtomic/actions/workflows/ci-mac.yaml)
[![Build Status](https://img.shields.io/github/actions/workflow/status/macmade/CPPAtomic/ci-win.yaml?label=Windows&logo=windows)](https://github.com/macmade/CPPAtomic/actions/workflows/ci-win.yaml)
[![Issues](http://img.shields.io/github/issues/macmade/CPPAtomic.svg?logo=github)](https://github.com/macmade/CPPAtomic/issues)
![Status](https://img.shields.io/badge/status-active-brightgreen.svg?logo=git)
![License](https://img.shields.io/badge/license-mit-brightgreen.svg?logo=open-source-initiative)
[![Contact](https://img.shields.io/badge/follow-@macmade-blue.svg?logo=twitter&style=social)](https://twitter.com/macmade)
[![Sponsor](https://img.shields.io/badge/sponsor-macmade-pink.svg?logo=github-sponsors&style=social)](https://github.com/sponsors/macmade)

About
-----

Replacement of `std::atomic` supporting **non trivially-copyable** types.

### Rationale

C++11 introduced the awesome [`std::atomic`](http://en.cppreference.com/w/cpp/atomic/atomic) template.
Unfortunately, it can only be used with [**non trivially-copyable**](http://en.cppreference.com/w/cpp/concept/TriviallyCopyable) types.

This restricts its usage to primitive types and [POD](http://en.cppreference.com/w/cpp/concept/PODType) types, meaning you can't use `std::atomic` with most C++ classes (user-defined or STL).

**CPPAtomic addresses this issue by providing a new template that can be used with non trivially-copyable types as well ass trivially-copyable types.**

As an example, assuming the following declarations:

struct s
{
int x;
};

class A
{};

class B
{
public:

B( void );
B( const B & rhs );
};

Here's what will happen with `std::atomic`:

std::atomic< struct s > s; /* OK - POD type */
std::atomic< A > a; /* OK - POD type */
std::atomic< B > b; /* Error - Class B is not trivially-copyable */
std::atomic< std::string > str; /* Error - std::string is not trivially-copyable */

In that example, class `B` is not trivially-copyable due to its copy constructor, so it cannot be used with `std::atomic`.

Using `XS::Atomic` instead, everything will compile and be fine:

XS::Atomic< struct s > s; /* OK */
XS::Atomic< A > a; /* OK */
XS::Atomic< B > b; /* OK */
XA::Atomic< std::string > str; /* OK */

### Operators

`XS::Atomic` overloads all operators, but uses type traits to enable specific overloads, depending on the type.

For instance, the following is valid, and atomic:

XS::Atomic< int > i{ 42 };
XS::Atomic< unsigned int > u{ 42 };

i++;
u &= 0xFF;

The following is not (compilation error):

XS::Atomic< double > d{ 42 };

d &= 0xFF;

Bitwise operations make no sense with floating point value, so such overloads are disabled when using a floating point type.

When using classes, usual operators are also detected using type traits, and available if they are implemented:

class Foo
{};

class Bar
{
public:

Bar & operator +=( const Bar & rhs );
};

XS::Atomic< Foo > f;
XS::Atomic< Bar > b;

f += Foo(); /* Compiler error - Foo has no such operator */
b += Bar(); /* Bar::operator+= will be used, atomically */

### Initialisation

All `XS::Atomic` objects initialise their values to a default one, using C++11 value initialisation (`{}`)..

As an example, an `XS::Atomic< int >` will default to `0`.
Structure types are zero-initialised as well.
For classes, the default constructor will be used.

### Implementation details

`XS::Atomic` internally ensures locking for all types.
It will use a `std::recursive_mutex`, along with `std::lock_guard` and `std::lock`.

This is necessary in order to allow operations on non trivially-copyable types, as well as operations not implemented by `std::atomic` on primitive types (see section about operators).

You might still prefer `std::atomic` for primitive types, if you're concerned about potential performance issues and if your implementation provides lock-free atomicity.

License
-------

CPPAtomic is released under the terms of the MIT license.

Repository Infos
----------------

Owner: Jean-David Gadina - XS-Labs
Web: www.xs-labs.com
Blog: www.noxeos.com
Twitter: @macmade
GitHub: github.com/macmade
LinkedIn: ch.linkedin.com/in/macmade/
StackOverflow: stackoverflow.com/users/182676/macmade