typemap: make use of volatile qualifier

Use shared lock for volatile pointers
Use no lock for const volatile pointers
This commit is contained in:
Nekotekina 2018-11-09 16:03:39 +03:00
parent 6a30d5a6c1
commit 7180c1f2d0

View file

@ -396,7 +396,10 @@ namespace utils
void release() void release()
{ {
if constexpr (type_const()) if constexpr (type_const() && type_volatile())
{
}
else if constexpr (type_const() || type_volatile())
{ {
m_block->m_mutex.unlock_shared(); m_block->m_mutex.unlock_shared();
} }
@ -484,6 +487,7 @@ namespace utils
ullong create(Args&&... args) ullong create(Args&&... args)
{ {
static_assert(!type_const()); static_assert(!type_const());
static_assert(!type_volatile());
const ullong result = ++m_head->m_create_count; const ullong result = ++m_head->m_create_count;
@ -593,6 +597,11 @@ namespace utils
{ {
return std::is_const_v<std::remove_reference_t<T>>; return std::is_const_v<std::remove_reference_t<T>>;
} }
static constexpr bool type_volatile()
{
return std::is_volatile_v<std::remove_reference_t<T>>;
}
}; };
// Dynamic object collection, one or more per any type; shall not be initialized before main() // Dynamic object collection, one or more per any type; shall not be initialized before main()
@ -772,7 +781,9 @@ namespace utils
if constexpr (constexpr uint last = typeinfo_count<Type>::max_count - 1) if constexpr (constexpr uint last = typeinfo_count<Type>::max_count - 1)
{ {
// If max_count > 1 only id_new is supported // If max_count > 1 only id_new is supported
static_assert(std::is_same_v<id_tag, id_new_t> && !std::is_const_v<std::remove_reference_t<Type>>); static_assert(std::is_same_v<id_tag, id_new_t>);
static_assert(!std::is_const_v<std::remove_reference_t<Type>>);
static_assert(!std::is_volatile_v<std::remove_reference_t<Type>>);
// Try to acquire the semaphore // Try to acquire the semaphore
if (UNLIKELY(!head->m_sema.try_inc(last + 1))) if (UNLIKELY(!head->m_sema.try_inc(last + 1)))
@ -806,6 +817,7 @@ namespace utils
if constexpr (std::is_same_v<id_tag, id_new_t>) if constexpr (std::is_same_v<id_tag, id_new_t>)
{ {
static_assert(!std::is_const_v<std::remove_reference_t<Type>>); static_assert(!std::is_const_v<std::remove_reference_t<Type>>);
static_assert(!std::is_volatile_v<std::remove_reference_t<Type>>);
if (block->m_type != 0 || !block->m_mutex.try_lock()) if (block->m_type != 0 || !block->m_mutex.try_lock())
{ {
@ -940,6 +952,7 @@ namespace utils
{ {
// Initialize object if necessary // Initialize object if necessary
static_assert(!std::is_const_v<std::remove_reference_t<Type>>); static_assert(!std::is_const_v<std::remove_reference_t<Type>>);
static_assert(!std::is_volatile_v<std::remove_reference_t<Type>>);
if constexpr (std::is_lvalue_reference_v<Type>) if constexpr (std::is_lvalue_reference_v<Type>)
{ {
@ -1008,8 +1021,9 @@ namespace utils
{ {
// Use reader lock for const access // Use reader lock for const access
constexpr bool is_const = std::is_const_v<std::remove_reference_t<Type>>; constexpr bool is_const = std::is_const_v<std::remove_reference_t<Type>>;
constexpr bool is_volatile = std::is_volatile_v<std::remove_reference_t<Type>>;
// Already locked // Already locked or lock is unnecessary
if constexpr (!Lock) if constexpr (!Lock)
{ {
return true; return true;
@ -1024,7 +1038,7 @@ namespace utils
if constexpr (Try) if constexpr (Try)
{ {
if constexpr (is_const) if constexpr (is_const || is_volatile)
{ {
return block->m_mutex.try_lock_shared(); return block->m_mutex.try_lock_shared();
} }
@ -1033,7 +1047,7 @@ namespace utils
return block->m_mutex.try_lock(); return block->m_mutex.try_lock();
} }
} }
else if constexpr (is_const) else if constexpr (is_const || is_volatile)
{ {
if (LIKELY(block->m_mutex.is_lockable())) if (LIKELY(block->m_mutex.is_lockable()))
{ {
@ -1075,7 +1089,7 @@ namespace utils
{ {
if (array[I].m_block) if (array[I].m_block)
{ {
if constexpr (std::is_const_v<std::remove_reference_t<Type>>) if constexpr (std::is_const_v<std::remove_reference_t<Type>> || std::is_volatile_v<std::remove_reference_t<Type>>)
{ {
array[I].m_block->m_mutex.unlock_shared(); array[I].m_block->m_mutex.unlock_shared();
} }
@ -1117,6 +1131,22 @@ namespace utils
return {array[I]...}; return {array[I]...};
} }
template <typename T, typename Arg>
static constexpr bool does_need_lock()
{
if constexpr (std::is_same_v<std::decay_t<Arg>, id_new_t>)
{
return false;
}
if constexpr (std::is_const_v<std::remove_reference_t<T>> && std::is_volatile_v<std::remove_reference_t<T>>)
{
return false;
}
return true;
}
public: public:
// Lock any objects by their identifiers, special tags id_new/id_any/id_always, or search predicates // Lock any objects by their identifiers, special tags id_new/id_any/id_always, or search predicates
template <typename... Types, typename... Args, typename = std::enable_if_t<sizeof...(Types) == sizeof...(Args)>> template <typename... Types, typename... Args, typename = std::enable_if_t<sizeof...(Types) == sizeof...(Args)>>
@ -1131,7 +1161,7 @@ namespace utils
std::array<typeptr_base, sizeof...(Types)> result{this->init_ptr<Types>(std::forward<Args>(ids))...}; std::array<typeptr_base, sizeof...(Types)> result{this->init_ptr<Types>(std::forward<Args>(ids))...};
// Whether requires locking after init_ptr // Whether requires locking after init_ptr
using locks_t = std::integer_sequence<bool, !std::is_same_v<std::decay_t<Args>, id_new_t>...>; using locks_t = std::integer_sequence<bool, does_need_lock<Types, Args>()...>;
// Array index helper // Array index helper
using seq_t = std::index_sequence_for<Types...>; using seq_t = std::index_sequence_for<Types...>;