/** * @file libconcur/element.h * @author mutouyun (orz@orzz.org) * @brief Define concurrent queue element abstraction. * @date 2022-11-19 */ #pragma once #include #include #include // std::numeric_limits #include #include #include "libimp/detect_plat.h" #include "libimp/log.h" #include "libconcur/def.h" LIBCONCUR_NAMESPACE_BEG_ namespace state { /// @brief The state flag type for the queue element. using flag_t = std::uint64_t; enum : flag_t { /// @brief The invalid state value. invalid_value = (std::numeric_limits::max)(), }; } // namespace state template class element { /// @brief Committed flag. alignas(cache_line_size) std::atomic f_ct_; /// @brief The user data segment. T data_; /// @brief Disable copy & move. element(element const &) = delete; element &operator=(element const &) = delete; public: template element(A &&... args) noexcept(noexcept(T{std::forward(args)...})) : f_ct_{state::invalid_value} , data_{std::forward(args)...} {} template void set_data(U &&src) noexcept { LIBIMP_LOG_(); LIBIMP_TRY { data_ = std::forward(src); } LIBIMP_CATCH(std::exception const &e) { log.error("failed: `data = std::forward(src)`. error = ", e.what()); } LIBIMP_CATCH(...) { log.error("failed: `data = std::forward(src)`. error = unknown"); } } T &&get_data() noexcept { return std::move(data_); } void set_flag(state::flag_t flag) noexcept { f_ct_.store(flag, std::memory_order_release); } state::flag_t get_flag() const noexcept { return f_ct_.load(std::memory_order_acquire); } }; LIBCONCUR_NAMESPACE_END_