最低要求c++17 static inline实现head only

    1. #pragma once
    2. #include <atomic>
    3. template<typename Traits>
    4. class AllocImpl;
    5. template<typename Traits>
    6. inline auto Next() {
    7. return AllocImpl<Traits>::Next();
    8. }
    9. template<typename Traits>
    10. class AllocImpl {
    11. public:
    12. using Type = typename Traits::Type;
    13. static Type Next() {
    14. if (current < max) {
    15. return current++;
    16. }
    17. return SlowNext();
    18. }
    19. private:
    20. static Type SlowNext();
    21. private:
    22. static inline std::atomic<Type> global{Traits::kMin};
    23. static inline thread_local Type current = 0;
    24. static inline thread_local Type max = 0;
    25. };
    26. template<typename Traits>
    27. typename AllocImpl<Traits>::Type AllocImpl<Traits>::SlowNext() {
    28. static_assert(Traits::kMin < Traits::kMax);
    29. static_assert(Traits::kBatchSize > 0);
    30. static_assert(Traits::kMin + Traits::kBatchSize < Traits::kMax,
    31. "Not supported due to implementation limitations.");
    32. static_assert(Traits::kBatchSize > 1,
    33. "Not supported due to implementation limitations.");
    34. // Get more IDs from global counter...
    35. Type read, next;
    36. do {
    37. read = global.load(std::memory_order_relaxed);
    38. current = read;
    39. if (read > Traits::kMax - Traits::kBatchSize /* Overflowing */) {
    40. next = Traits::kMin;
    41. max = Traits::kMax;
    42. }
    43. else {
    44. next = read + Traits::kBatchSize;
    45. max = next;
    46. }
    47. } while (
    48. !global.compare_exchange_weak(read, next, std::memory_order_relaxed));
    49. // ... and retry.
    50. return Next();
    51. }

    使用时指定1个traits.

    1. struct ClientIdAllocTraits {
    2. using Type = std::uint64_t;
    3. static constexpr const Type kMin = 0;
    4. static constexpr const Type kMax = 999999999999999;
    5. static constexpr const Type kBatchSize = 200;
    6. };
    7. int main()
    8. {
    9. while (true) {
    10. std::cout << Next<ClientIdAllocTraits>() << std::endl;
    11. }
    12. return 0;
    13. }