fork(1) download
  1. #include <atomic>
  2.  
  3. template<class StorageType, unsigned offset, unsigned width, class FieldType>
  4. class AtomicField {
  5. static constexpr StorageType MASK = static_cast<StorageType>(((1u<<width)-1u)<<offset);
  6.  
  7. std::atomic<StorageType>& bits;
  8.  
  9. static FieldType extract(StorageType newValue)
  10. {return static_cast<FieldType>((newValue&MASK)>>width);}
  11. static StorageType insert(StorageType oldBits, FieldType newValue)
  12. {return ((static_cast<StorageType>(newValue)<<offset)&MASK)|(oldBits&~MASK);}
  13. template<class F>
  14. FieldType manip(FieldType manipValue, F f) {
  15. StorageType oldBits = bits.load();
  16. StorageType newBits;
  17. do {
  18. FieldType oldValue = extract(oldBits);
  19. FieldType newValue = f(oldValue, manipValue);
  20. newBits = insert(oldBits, newValue);
  21. } while (bits.compare_exchange_weak(oldBits, newBits));
  22. return oldBits;
  23. }
  24. public:
  25. static const unsigned OFFSET = offset;
  26. static const unsigned WIDTH = width;
  27.  
  28. AtomicField(std::atomic<StorageType>& bits_) : bits(bits_){}
  29.  
  30. operator FieldType() const {return load();}
  31. FieldType load() const {return extract(bits.load());}
  32. FieldType operator!() const {return !load();}
  33. FieldType operator~() const {return ~load();}
  34.  
  35. AtomicField& operator=(FieldType desired) {store(desired);return *this;}
  36. FieldType store(FieldType desired)
  37. {return manip(desired, [](FieldType oldValue,FieldType newValue){return newValue;});}
  38. bool compare_exchange_weak(FieldType expected, FieldType desired) {
  39. StorageType oldBits = bits.load();
  40. StorageType newBits = insert(oldBits, desired);
  41. return bits.compare_exchange_weak(oldBits, newBits);
  42. }
  43. bool compare_exchange_strong(FieldType expected, FieldType desired) {
  44. StorageType oldBits = bits.load();
  45. StorageType newBits = insert(oldBits, desired);
  46. return bits.compare_exchange_strong(oldBits, newBits);
  47. }
  48.  
  49. FieldType operator|(FieldType rhs) const {return load()|rhs;}
  50. AtomicField& operator|=(FieldType rhs)
  51. {manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue|newValue;}); return *this;}
  52. FieldType operator&(FieldType rhs) const {return load()&rhs;}
  53. AtomicField& operator&=(FieldType rhs)
  54. {manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue&newValue;}); return *this;}
  55. FieldType operator^(FieldType rhs) const {return load()^rhs;}
  56. AtomicField& operator^=(FieldType rhs)
  57. {manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue^newValue;}); return *this;}
  58. FieldType operator<<(FieldType rhs) const {return load()<<rhs;}
  59. AtomicField& operator<<=(FieldType rhs)
  60. {manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue<<newValue;}); return *this;}
  61. FieldType operator>>(FieldType rhs) const {return load()<<rhs;}
  62. AtomicField& operator>>=(FieldType rhs)
  63. {manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue>>newValue;}); return *this;}
  64.  
  65. FieldType operator==(FieldType rhs) const {return load()==rhs;}
  66. FieldType operator!=(FieldType rhs) const {return load()==rhs;}
  67. FieldType operator<(FieldType rhs) const {return load()<rhs;}
  68. FieldType operator<=(FieldType rhs) const {return load()<=rhs;}
  69. FieldType operator>(FieldType rhs) const {return load()>rhs;}
  70. FieldType operator>=(FieldType rhs) const {return load()>=rhs;}
  71.  
  72. bool operator&&(FieldType rhs) const {return load()&&rhs;}
  73. bool operator||(FieldType rhs) const {return load()||rhs;}
  74.  
  75. FieldType operator+(FieldType rhs) const {return load()+rhs;}
  76. AtomicField& operator+=(FieldType rhs)
  77. {manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue+newValue;}); return *this;}
  78. FieldType operator++()
  79. {return manip(1, [](FieldType oldValue,FieldType newValue){return oldValue+newValue;});}
  80. AtomicField& operator++(int) {operator++(); return *this;}
  81. FieldType operator-(FieldType rhs) const {return load()-rhs;}
  82. AtomicField& operator-=(FieldType rhs)
  83. {manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue-newValue;}); return *this;}
  84. FieldType operator--()
  85. {return manip(-1, [](FieldType oldValue,FieldType newValue){return oldValue-newValue;});}
  86. AtomicField& operator--(int) {operator--(); return *this;}
  87. FieldType operator*(FieldType rhs) const {return load()-rhs;}
  88. AtomicField& operator*=(FieldType rhs)
  89. {manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue*newValue;}); return *this;}
  90. FieldType operator/(FieldType rhs) const {return load()/rhs;}
  91. AtomicField& operator/=(FieldType rhs)
  92. {manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue/newValue;}); return *this;}
  93. FieldType operator%(FieldType rhs) const {return load()%rhs;}
  94. AtomicField& operator%=(FieldType rhs)
  95. {manip(rhs, [](FieldType oldValue,FieldType newValue){return oldValue%newValue;}); return *this;}
  96. };
  97.  
  98.  
  99.  
  100. //USAGE:
  101. class MyClass
  102. {
  103. std::atomic<unsigned> bits;
  104. public:
  105. AtomicField<unsigned, 0, 8, unsigned char> r() {return {bits};}
  106. AtomicField<unsigned, 8, 8, unsigned char> g() {return {bits};}
  107. AtomicField<unsigned, 16, 8, unsigned char> b() {return {bits};}
  108. AtomicField<unsigned, 24, 8, unsigned char> a() {return {bits};}
  109. };
  110.  
  111. #include <iostream>
  112. int main() {
  113. MyClass test;
  114. test.r() = 0;
  115. test.g() = 255;
  116. test.b() = 0xFF;
  117. test.a() = -1;
  118. std::cout << test.g();
  119. }
Success #stdin #stdout 0.01s 5288KB
stdin
Standard input is empty
stdout