Last active
December 14, 2016 20:31
-
-
Save taeguk/2d10916acc450cb921abbd668cf88d20 to your computer and use it in GitHub Desktop.
Abstracted class combining several variables to one variable for atomic instructions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <atomic> | |
#include <cstddef> | |
#include <limits> | |
#include <cstdint> | |
using namespace std; | |
class BaseIndexD32 | |
{ | |
public: | |
using value_type = std::uint64_t; | |
protected: | |
union _InnerUnion { | |
struct _InnerItems { | |
alignas(4) std::uint32_t head; | |
alignas(4) std::uint32_t tail; | |
} items; | |
value_type value; | |
} atomic_items; | |
}; | |
template <int QueueSize> | |
class IndexD32 : public BaseIndexD32 | |
{ | |
private: | |
static const int HEAD_BIT_OFFSET = 8*offsetof(_InnerUnion::_InnerItems, head); | |
static const int TAIL_BIT_OFFSET = 8*offsetof(_InnerUnion::_InnerItems, tail); | |
public: | |
inline IndexD32() = default; | |
inline IndexD32(value_type number) | |
{ atomic_items.value = number; } | |
inline operator value_type () const { | |
return atomic_items.value; | |
} | |
inline std::uint32_t head() const { return atomic_items.items.head & (QueueSize-1); } | |
inline std::uint32_t tail() const { return atomic_items.items.tail & (QueueSize-1); } | |
/**************** | |
count(), full() are needed type casting(to std::uint64_t) if QueueSize is enough big. | |
*****************/ | |
inline std::uint32_t count () const { | |
return (atomic_items.items.tail - atomic_items.items.head + 1 + QueueSize) % (QueueSize+1); | |
} | |
inline bool empty () const { | |
return atomic_items.items.head == atomic_items.items.tail; | |
} | |
inline bool full () const { | |
return atomic_items.items.head == (atomic_items.items.tail + 1) & (QueueSize-1); | |
} | |
inline static value_type from_head_data(std::uint32_t data) | |
{ return (static_cast<value_type>(data) << HEAD_BIT_OFFSET); } | |
inline static value_type from_tail_data(std::uint32_t data) | |
{ return static_cast<value_type>(data) << TAIL_BIT_OFFSET; } | |
}; | |
/**** | |
* BUG) 3 -> 0 (2^32 - 1 -> 0) | |
****/ | |
using MyIndexD32 = IndexD32<1024>; | |
int main() { | |
std::cout << "sizeof = " << sizeof(MyIndexD32) << std::endl; | |
std::atomic<MyIndexD32::value_type> index_; | |
// your code goes here | |
index_.store(0); | |
MyIndexD32::value_type k1 = index_.fetch_add(MyIndexD32::from_head_data(1022)); | |
MyIndexD32::value_type k2 = index_.fetch_add(MyIndexD32::from_tail_data(1023)); | |
index_.fetch_add(MyIndexD32::from_tail_data(1)); | |
MyIndexD32::value_type k3 = index_.load(); | |
MyIndexD32 kk1 = static_cast<MyIndexD32>(k3); | |
std::cout << "head=" << kk1.head() << ", tail=" << kk1.tail() << std::endl; | |
std::cout << "count=" << kk1.count() << ", empty=" << kk1.empty() << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment