#include <iostream>
#include <cstdint>
#include <atomic>
using namespace std;
template<typename ERange>
class CGlobalSeqT
{
public:
typedef uint32_t SEQ_T;
static SEQ_T Gen(bool next = true)
{
static CGlobalSeqT<ERange> instance;
if (next)
{
return instance.Next();
}
else
{
instance.Reset();
return 0;
}
}
private:
CGlobalSeqT()
: m_min((SEQ_T)ERange::MIN)
, m_max((SEQ_T)ERange::MAX)
, m_seq((SEQ_T)ERange::MIN - 1)
{
static_assert((SEQ_T)ERange::MIN < (SEQ_T)ERange::MAX, "invalid range");
}
inline uint32_t Next()
{
SEQ_T expected_max = m_max;
if (m_seq.compare_exchange_strong(expected_max, m_min))
{
return m_min;
}
else
{
return ++m_seq;
}
}
inline void Reset()
{
m_seq = m_min - 1;
}
SEQ_T m_min;
SEQ_T m_max;
std::atomic<SEQ_T> m_seq;
};
class CInboundGlobalSeq : public CGlobalSeqT<CInboundGlobalSeq>
{
public:
enum ERange { MIN = 0, MAX = UINT32_MAX };
};
class COutboundGlobalSeq : public CGlobalSeqT<COutboundGlobalSeq>
{
public:
enum ERange { MIN = 2000, MAX = 2002 };
};
int main()
{
cout << "inbound:" << CInboundGlobalSeq::Gen() << "," << CInboundGlobalSeq::Gen() << endl;
cout << "1.outbound:"
<< COutboundGlobalSeq::Gen() << ","
<< COutboundGlobalSeq::Gen() << ","
<< COutboundGlobalSeq::Gen() << ","
<< COutboundGlobalSeq::Gen() << endl;
COutboundGlobalSeq::Gen(false);
cout << "2.outbound:" << COutboundGlobalSeq::Gen() << "," << COutboundGlobalSeq::Gen() << endl;
return 0;
}