30#include "ipc/shm/arena_lend/shm_pool.hpp"
31#include <flow/util/thread_lcl_obj.hpp>
32#include <flow/util/util.hpp>
33#include <boost/container/flat_map.hpp>
34#include <boost/unordered/unordered_flat_map.hpp>
78template<
typename Repository_t,
bool LOOKUP_CAN_FAIL,
typename Shm_arena_t>
110 void insert(
const Shm_pool& pool);
118 void erase(
const void* base);
306template<
typename Shm_arena_t>
308 private boost::noncopyable
429 using Pool_bases_cache = flow::util::Thread_local_obj_deinit_safe<Pool_bases_cache_map, Owner_shm_pool_repository>;
464template<
typename Repository_t,
bool LOOKUP_CAN_FAIL,
typename Shm_arena_t>
472template<
typename Repository_t,
bool LOOKUP_CAN_FAIL,
typename Shm_arena_t>
483 Tl_copy::s_registry.while_locked([&](
const auto& state_per_thread)
485 m_pools_by_base[pool.get_address()] =
Pool_by_base{ pool.get_id(),
486 S_LOOKUP_CAN_FAIL ? pool.get_size() : 0 };
487 tl_copy_push_pools(state_per_thread);
491template<
typename Repository_t,
bool LOOKUP_CAN_FAIL,
typename Shm_arena_t>
497 Tl_copy::s_registry.while_locked([&](
const auto& state_per_thread)
499 m_pools_by_base.erase(
const_cast<void*
>(base));
500 tl_copy_push_pools(state_per_thread);
504template<
typename Repository_t,
bool LOOKUP_CAN_FAIL,
typename Shm_arena_t>
506 (
const typename decltype(Tl_copy::s_registry)::State_per_thread_map& caches_per_thread)
const
516 Map pools_sorted_by_base;
517 tl_copy_rev_pull_pools(&pools_sorted_by_base);
520 size_t n = caches_per_thread.size();
521 for (
const auto& [cache, nil] : caches_per_thread)
524 cache->push_pools(((--n) == 0) ? std::move(pools_sorted_by_base)
525 : Map{pools_sorted_by_base});
529template<
typename Repository_t,
bool LOOKUP_CAN_FAIL,
typename Shm_arena_t>
533 using std::is_same_v;
535 using Src_map = std::decay_t<
decltype(m_pools_by_base)>;
545 assert(pools_sorted_by_base->empty() &&
"By contract we are to load an empty map-copy.");
549 static_assert(is_same_v<Map, boost::container::flat_map<void*, Pool_by_base>>,
550 "Optimization below assumes target Map = sorted flat map (sorted-by-key in array). "
551 "Try maintaining this in spirit if possible. Do note this is not the fast-path though.");
552 static_assert(is_same_v<Src_map, std::map<void*, Pool_by_base>>,
553 "Optimization below assumes Src_map = sorted map of some kind (std::map is one such thing, "
554 "and there are probably others, but we are just sanity-checking here. "
555 "Try maintaining this in spirit if possible. Do note this is not the fast-path though.");
557 pools_sorted_by_base->reserve(m_pools_by_base.size());
558 for (
const auto& base_and_pool : m_pools_by_base)
561 pools_sorted_by_base->emplace_hint(pools_sorted_by_base->end(),
562 base_and_pool.first, base_and_pool.second);
566template<
typename Repository_t,
bool LOOKUP_CAN_FAIL,
typename Shm_arena_t>
573 Tl_copy::s_registry.this_thread_state()->lookup(address, pool_id, pool_offset);
578template<
typename Shm_arena_t>
581template<
typename Shm_arena_t>
589template<
typename Shm_arena_t>
593 const auto pool_bases_by_id = Pool_bases_cache::this_thread_obj_or_null();
594 if (pool_bases_by_id)
596 auto& pool_base_ref = (*pool_bases_by_id)[pool_id];
600 pool_base_ref = get_instance().pull_pool_base_by_id(pool_id);
603 pool_base = pool_base_ref;
610 pool_base = get_instance().pull_pool_base_by_id(pool_id);
612 return reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(pool_base) + pool_offset);
615template<
typename Shm_arena_t>
621 Core_rev::get_instance().lookup(address, pool_id, pool_offset);
624template<
typename Shm_arena_t>
627 const auto& pool = *shm_pool;
631 m_pool_bases_by_id.emplace(pool.get_id(), std::move(shm_pool));
634 Core_rev::get_instance().insert(pool);
640template<
typename Shm_arena_t>
650 const auto it = m_pool_bases_by_id.find(pool_id);
651 base = it->second->get_address();
653 m_pool_bases_by_id.erase(it);
656 Core_rev::get_instance().erase(base);
659template<
typename Shm_arena_t>
665 return m_pool_bases_by_id.find(pool_id)->second->get_address();
Singleton repository for SHM-pool data pertaining to all SHM-arenas owned by this process.
static void from_address(const void *address, pool_id_t &pool_id, pool_offset_t &pool_offset)
Key high-performance API: Essentially the reverse of to_address().
static void * to_address(pool_id_t pool_id, pool_offset_t pool_offset)
Key high-performance API: Given an in-SHM location as the pool and in-pool offset (values that remain...
void insert(Shm_pool_ptr &&shm_pool)
Registers an owned SHM-pool.
Shm_arena_t Shm_arena
The SHM-arena type; see class template parameter doc header.
boost::unordered_flat_map< pool_id_t, Shm_pool_ptr > m_pool_bases_by_id
Canonical map: pool-ID -> Shm_pool handle (and thus base-vaddr via ->get_address()).
flow::util::Thread_local_obj_deinit_safe< Pool_bases_cache_map, Owner_shm_pool_repository > Pool_bases_cache
Death-aware access to this thread's Pool_bases_cache_map: to_address() can run during thread exit (se...
flow::util::Mutex_non_recursive Pool_bases_by_id_mutex
Short-hand for the mutex type guarding m_pool_bases_by_id.
std::shared_ptr< Shm_pool > Shm_pool_ptr
Short-hand for shared_ptr<Shm_pool>.
Owner_shm_pool_repository()
Constructor. Zero-arg due to singleton pattern.
void * pull_pool_base_by_id(pool_id_t pool_id) const
Forward-lookup slow-path helper: returns the base vaddr for the given pool ID from the canonical m_po...
static Owner_shm_pool_repository & get_instance()
Returns the process-wide singleton instance of this class.
void erase(pool_id_t pool_id)
Deregisters an owned SHM-pool.
boost::unordered_flat_map< pool_id_t, void * > Pool_bases_cache_map
Per-thread cache map: pool-ID -> base-vaddr. Populated lazily in to_address(). Entries are never remo...
flow::util::Lock_guard< Pool_bases_by_id_mutex > Pool_bases_by_id_lock
Short-hand for the lock type for Pool_bases_by_id_mutex.
typename Shm_pool_repo_lookup_core_rev< Owner_shm_pool_repository, true, Shm_arena >::pool_offset_t pool_offset_t
Short-hand for pool-offset type.
Pool_bases_by_id_mutex m_pool_bases_by_id_mutex
Mutex guarding m_pool_bases_by_id.
Helper singleton for each of at least the 2 essential central flat SHM-pool repositories (Owner_shm_p...
void tl_copy_push_pools(const typename decltype(Tl_copy::s_registry)::State_per_thread_map &caches_per_thread) const
Helper for insert() and erase() that pushes the current canonical m_pools_by_base state into all per-...
Shm_arena_t Shm_arena
See Pool_lookup_global_stats.
static Shm_pool_repo_lookup_core_rev & get_instance()
Returns the process-wide singleton instance of this class.
void tl_copy_rev_pull_pools(typename Tl_copy::Map *pools_sorted_by_base) const
Internal callback invoked by Tl_copy ctor (via Thread_local_state_registry) during per-thread cache c...
void lookup(const void *address, pool_id_t &pool_id, pool_offset_t &pool_offset) const
Performs a high-performance reverse-lookup, as for (e.g.) Owner_shm_pool_repository::from_address().
void erase(const void *base)
Undoes insert().
void insert(const Shm_pool &pool)
Adds a SHM-pool to the canonical map and pushes the updated state into all per-thread reverse-lookup ...
Shm_pool::size_t pool_offset_t
Short-hand for pool-offset type.
std::map< void *, Pool_by_base > m_pools_by_base
Canonical sorted map: pool-base vaddr -> Pool_by_base.
static constexpr bool S_LOOKUP_CAN_FAIL
true <=> lookup() can legitimately fail to find the containing pool.
Repository_t Repository
The consuming repository type (e.g., Owner_shm_pool_repository, Borrower_shm_pool_collection_reposito...
Thread_local_pool_lookup_rev<R>.s_registry, where R is a distinct pool-repository type,...
boost::container::flat_map< void *, Pool_by_base > Map
Reverse-lookup map type (base vaddr -> Pool_by_base).
static flow::util::Thread_local_state_registry< Thread_local_pool_lookup_rev > s_registry
Global registry of per-thread *this instances.
Segregated private stuff for ipc::shm::arena_lend.
uint32_t pool_id_t
Pool ID type.
Value type in the reverse-lookup map: identifies the pool and, when LOOKUP_CAN_FAIL is true for the c...