17 std::unordered_map<std::string, std::any>
metadata;
64 template <
typename OpClass>
65 bool add(
const std::string& name, std::shared_ptr<OpClass> op)
81 info.
type = std::type_index(
typeid(OpClass));
82 info.
created_at = std::chrono::steady_clock::now();
86 m_info[name] = std::move(info);
101 template <
typename OpClass>
102 void set(
const std::string& name, std::shared_ptr<OpClass> op)
108 std::unique_lock lock(
m_mutex);
112 m_operations[name] = std::static_pointer_cast<void>(op);
114 auto& info =
m_info[name];
116 info.type = std::type_index(
typeid(OpClass));
119 info.created_at = std::chrono::steady_clock::now();
120 info.access_count = 0;
122 info.last_accessed = std::chrono::steady_clock::now();
137 template <
typename OpClass>
138 std::shared_ptr<OpClass>
get(
const std::string& name)
140 std::shared_lock lock(
m_mutex);
147 auto info_it =
m_info.find(name);
148 if (info_it !=
m_info.end()) {
149 if (info_it->second.type != std::type_index(
typeid(OpClass))) {
155 std::unique_lock write_lock(
m_mutex);
156 info_it->second.last_accessed = std::chrono::steady_clock::now();
157 info_it->second.access_count++;
161 return std::static_pointer_cast<OpClass>(it->second);
170 template <
typename OpClass>
171 std::optional<std::shared_ptr<OpClass>>
try_get(
const std::string& name)
173 auto op = get<OpClass>(name);
174 return op ? std::optional(op) : std::nullopt;
184 std::unique_lock lock(
m_mutex);
191 std::type_index type =
m_info[name].type;
208 template <
typename OpClass>
211 std::unique_lock lock(
m_mutex);
213 std::type_index target_type(
typeid(OpClass));
214 std::vector<std::string> to_remove;
216 for (
const auto& [name, info] :
m_info) {
217 if (info.type == target_type) {
218 to_remove.push_back(name);
222 for (
const auto& name : to_remove) {
231 return to_remove.size();
239 std::unique_lock lock(
m_mutex);
250 std::shared_lock lock(
m_mutex);
252 std::vector<std::string> names;
256 names.push_back(name);
267 template <
typename OpClass>
270 std::shared_lock lock(
m_mutex);
272 std::type_index target_type(
typeid(OpClass));
273 std::vector<std::string> names;
275 for (
const auto& [name, info] :
m_info) {
276 if (info.type == target_type) {
277 names.push_back(name);
291 std::shared_lock lock(
m_mutex);
293 std::vector<std::string> names;
296 if (predicate(name)) {
297 names.push_back(name);
309 bool has(
const std::string& name)
const
311 std::shared_lock lock(
m_mutex);
320 template <
typename OpClass>
323 std::shared_lock lock(
m_mutex);
325 std::type_index target_type(
typeid(OpClass));
328 [target_type](
const auto& pair) {
329 return pair.second.type == target_type;
338 std::optional<std::type_index>
get_type(
const std::string& name)
const
340 std::shared_lock lock(
m_mutex);
342 auto it =
m_info.find(name);
344 return it->second.type;
355 std::optional<PooledOperationInfo>
get_info(
const std::string& name)
const
357 std::shared_lock lock(
m_mutex);
359 auto it =
m_info.find(name);
373 std::shared_lock lock(
m_mutex);
383 std::shared_lock lock(
m_mutex);
393 std::shared_lock lock(
m_mutex);
395 std::unordered_map<std::string, std::any> stats;
398 size_t total_accesses = 0;
399 std::string most_accessed;
400 size_t max_accesses = 0;
402 for (
const auto& [name, info] :
m_info) {
403 total_accesses += info.access_count;
404 if (info.access_count > max_accesses) {
405 max_accesses = info.access_count;
406 most_accessed = name;
410 stats[
"total_accesses"] = total_accesses;
411 if (!most_accessed.empty()) {
412 stats[
"most_accessed_operation"] = most_accessed;
413 stats[
"most_accessed_count"] = max_accesses;
422 void on_add(std::function<
void(
const std::string&, std::type_index)> callback)
424 std::unique_lock lock(
m_mutex);
431 void on_remove(std::function<
void(
const std::string&, std::type_index)> callback)
433 std::unique_lock lock(
m_mutex);
440 void on_replace(std::function<
void(
const std::string&, std::type_index)> callback)
442 std::unique_lock lock(
m_mutex);
452 template <
typename OpClass>
453 size_t add_batch(
const std::unordered_map<std::string, std::shared_ptr<OpClass>>& operations)
455 std::unique_lock lock(
m_mutex);
458 for (
const auto& [name, op] : operations) {
460 m_operations[name] = std::static_pointer_cast<void>(op);
464 info.
type = std::type_index(
typeid(OpClass));
465 info.
created_at = std::chrono::steady_clock::now();
469 m_info[name] = std::move(info);
488 std::unique_lock lock(
m_mutex);
490 std::vector<std::string> to_remove;
493 if (predicate(name)) {
494 to_remove.push_back(name);
498 for (
const auto& name : to_remove) {
499 auto type =
m_info[name].type;
508 return to_remove.size();
514 std::unordered_map<std::string, PooledOperationInfo>
m_info;
std::shared_ptr< void > OperationPtr
void clear()
Clear all operations from the pool.
std::optional< PooledOperationInfo > get_info(const std::string &name) const
Get metadata about an operation.
std::function< bool(std::type_index)> TypePredicate
std::function< void(const std::string &, std::type_index)> m_on_replace_callback
std::shared_ptr< OpClass > get(const std::string &name)
Get operation from pool with type safety.
std::vector< std::string > list_names() const
List all operation names.
bool remove(const std::string &name)
Remove operation from pool.
std::vector< std::string > list_names_by_type() const
Get names of operations matching a type.
std::shared_mutex m_mutex
void set(const std::string &name, std::shared_ptr< OpClass > op)
Add or replace operation in pool.
void on_remove(std::function< void(const std::string &, std::type_index)> callback)
Set callback for when operations are removed.
void on_replace(std::function< void(const std::string &, std::type_index)> callback)
Set callback for when operations are replaced.
bool has(const std::string &name) const
Check if operation exists.
std::function< void(const std::string &, std::type_index)> m_on_add_callback
size_t remove_by_type()
Remove all operations of a specific type.
void on_add(std::function< void(const std::string &, std::type_index)> callback)
Set callback for when operations are added.
bool has_type() const
Check if any operations of a type exist.
size_t add_batch(const std::unordered_map< std::string, std::shared_ptr< OpClass > > &operations)
Add multiple operations at once.
OperationPool()=default
Default constructor.
std::optional< std::shared_ptr< OpClass > > try_get(const std::string &name)
Try to get operation, return optional.
std::unordered_map< std::string, PooledOperationInfo > m_info
std::optional< std::type_index > get_type(const std::string &name) const
Get type of named operation.
std::unordered_map< std::string, std::any > get_statistics() const
Get statistics about pool usage.
std::unordered_map< std::string, OperationPtr > m_operations
size_t remove_if(const NamePredicate &predicate)
Remove operations matching a predicate.
bool empty() const
Check if pool is empty.
std::function< void(const std::string &, std::type_index)> m_on_remove_callback
std::function< bool(const std::string &)> NamePredicate
std::vector< std::string > find_names(const NamePredicate &predicate) const
Get names matching a predicate.
size_t size() const
Get pool size.
bool add(const std::string &name, std::shared_ptr< OpClass > op)
Add named operation to pool.
Thread-safe pool for managing named operation instances.
std::unordered_map< std::string, std::any > metadata
PooledOperationInfo(std::type_index t)
std::chrono::steady_clock::time_point last_accessed
std::chrono::steady_clock::time_point created_at
Metadata about a pooled operation.