#include <atomic>
template<class StorageType, unsigned offset, unsigned width, class FieldType>
class AtomicField {
static constexpr StorageType MASK = static_cast<StorageType>(((1u<<width)-1u)<<offset);
std::atomic<StorageType>& bits;
static FieldType extract(StorageType newValue)
{return static_cast<FieldType>((newValue&MASK)>>width);}
static StorageType insert(StorageType oldBits, FieldType newValue)
{return ((static_cast<StorageType>(newValue)<<offset)&MASK)|(oldBits&~MASK);}
template<class F>
FieldType manip(FieldType manipValue, F f) {
StorageType oldBits = bits.load();
StorageType newBits;
do {
FieldType oldValue = extract(oldBits);
FieldType newValue = f(oldValue, manipValue);
newBits = insert(oldBits, newValue);
} while (bits.compare_exchange_weak(oldBits, newBits));
return oldBits;
}
public:
static const unsigned OFFSET = offset;
static const unsigned WIDTH = width;
AtomicField(std::atomic<StorageType>& bits_) : bits(bits_){}
operator FieldType() const {return load();}
FieldType load() const {return extract(bits.load());}
FieldType operator!() const {return !load();}
FieldType operator~() const {return ~load();}
AtomicField& operator=(FieldType desired) {store(desired);return *this;}
FieldType store(FieldType desired)
{return manip(desired, [](FieldType oldValue,FieldType newValue){return newValue;});}
bool compare_exchange_weak(FieldType expected, FieldType desired) {
StorageType oldBits = bits.load();
StorageType newBits = insert(oldBits, desired);
return bits.compare_exchange_weak(oldBits, newBits);
}
bool compare_exchange_strong(FieldType expected, FieldType desired) {
StorageType oldBits = bits.load();
StorageType newBits = insert(oldBits, desired);
return bits.compare_exchange_strong(oldBits, newBits);
}
FieldType operator|(FieldType rhs) const {return load()|rhs;}
AtomicField& operator|=(FieldType rhs)
{manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue|newValue;}); return *this;}
FieldType operator&(FieldType rhs) const {return load()&rhs;}
AtomicField& operator&=(FieldType rhs)
{manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue&newValue;}); return *this;}
FieldType operator^(FieldType rhs) const {return load()^rhs;}
AtomicField& operator^=(FieldType rhs)
{manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue^newValue;}); return *this;}
FieldType operator<<(FieldType rhs) const {return load()<<rhs;}
AtomicField& operator<<=(FieldType rhs)
{manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue<<newValue;}); return *this;}
FieldType operator>>(FieldType rhs) const {return load()<<rhs;}
AtomicField& operator>>=(FieldType rhs)
{manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue>>newValue;}); return *this;}
FieldType operator==(FieldType rhs) const {return load()==rhs;}
FieldType operator!=(FieldType rhs) const {return load()==rhs;}
FieldType operator<(FieldType rhs) const {return load()<rhs;}
FieldType operator<=(FieldType rhs) const {return load()<=rhs;}
FieldType operator>(FieldType rhs) const {return load()>rhs;}
FieldType operator>=(FieldType rhs) const {return load()>=rhs;}
bool operator&&(FieldType rhs) const {return load()&&rhs;}
bool operator||(FieldType rhs) const {return load()||rhs;}
FieldType operator+(FieldType rhs) const {return load()+rhs;}
AtomicField& operator+=(FieldType rhs)
{manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue+newValue;}); return *this;}
FieldType operator++()
{return manip(1, [](FieldType oldValue,FieldType newValue){return oldValue+newValue;});}
AtomicField& operator++(int) {operator++(); return *this;}
FieldType operator-(FieldType rhs) const {return load()-rhs;}
AtomicField& operator-=(FieldType rhs)
{manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue-newValue;}); return *this;}
FieldType operator--()
{return manip(-1, [](FieldType oldValue,FieldType newValue){return oldValue-newValue;});}
AtomicField& operator--(int) {operator--(); return *this;}
FieldType operator*(FieldType rhs) const {return load()-rhs;}
AtomicField& operator*=(FieldType rhs)
{manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue*newValue;}); return *this;}
FieldType operator/(FieldType rhs) const {return load()/rhs;}
AtomicField& operator/=(FieldType rhs)
{manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue/newValue;}); return *this;}
FieldType operator%(FieldType rhs) const {return load()%rhs;}
AtomicField& operator%=(FieldType rhs)
{manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue%newValue;}); return *this;}
};
//USAGE:
class MyClass
{
std::atomic<unsigned> bits;
public:
AtomicField<unsigned, 0, 8, unsigned char> r() {return {bits};}
AtomicField<unsigned, 8, 8, unsigned char> g() {return {bits};}
AtomicField<unsigned, 16, 8, unsigned char> b() {return {bits};}
AtomicField<unsigned, 24, 8, unsigned char> a() {return {bits};}
};
#include <iostream>
int main() {
MyClass test;
test.r() = 0;
test.g() = 255;
test.b() = 0xFF;
test.a() = -1;
std::cout << test.g();
}