Skip to content

Instantly share code, notes, and snippets.

@taeguk
Last active December 14, 2016 20:31
Show Gist options
  • Save taeguk/2d10916acc450cb921abbd668cf88d20 to your computer and use it in GitHub Desktop.
Save taeguk/2d10916acc450cb921abbd668cf88d20 to your computer and use it in GitHub Desktop.
Abstracted class combining several variables to one variable for atomic instructions.
#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