29#include <shared_mutex>
30#include <unordered_map>
31#include <unordered_set>
143 std::type_index interface_type,
144 const std::string& type_name,
149 std::type_index interface_type,
150 const std::string& type_name,
151 std::shared_ptr<void> instance)
override;
154 std::type_index interface_type)
override;
191 std::type_index interface_type,
192 std::unordered_map<std::type_index, std::shared_ptr<void>>* scoped_instances =
nullptr);
197 bool is_resolving(std::type_index interface_type)
const;
225 const std::string& type_name,
227 const std::string& error_message)
const;
239 std::type_index interface_type,
240 const std::string& type_name)
const;
253 std::unordered_map<std::type_index, service_entry>
services_;
321 std::type_index interface_type,
322 const std::string& type_name,
327 std::type_index interface_type,
328 const std::string& type_name,
329 std::shared_ptr<void> instance)
override;
332 std::type_index interface_type)
override;
358 return std::make_unique<service_scope>(*
this);
362 std::shared_lock lock(
mutex_);
364 std::vector<service_descriptor> result;
367 for (
const auto& [type_index, entry] :
services_) {
370 result.push_back(std::move(desc));
381 "Container is frozen"));
384 "Cannot clear services: container is frozen",
385 "di::service_container"
389 std::unique_lock lock(
mutex_);
400 frozen_.store(
true, std::memory_order_release);
408 return frozen_.load(std::memory_order_acquire);
416 const std::string& type_name,
418 const std::string& error_message)
const {
424 "Container is frozen"));
428 "di::service_container"
436 std::type_index interface_type,
437 const std::string& type_name)
const {
443 "Service already registered"));
446 "Service already registered: " + type_name,
447 "di::service_container"
459 }
catch (
const std::exception& e) {
462 std::string(
"Factory threw exception: ") + e.what(),
463 "di::service_container"
469 std::type_index interface_type,
470 const std::string& type_name,
478 "Cannot register service: container is frozen");
479 if (!frozen_check.is_ok()) {
483 std::unique_lock lock(
mutex_);
487 if (!registered_check.is_ok()) {
488 return registered_check;
493 service_entry(interface_type, type_name, std::move(factory), lifetime)
504 std::type_index interface_type,
505 const std::string& type_name,
506 std::shared_ptr<void> instance) {
512 "Cannot register instance: container is frozen");
513 if (!frozen_check.is_ok()) {
517 std::unique_lock lock(
mutex_);
521 if (!registered_check.is_ok()) {
522 return registered_check;
533 entry.is_instantiated =
true;
535 services_.emplace(interface_type, std::move(entry));
545 std::type_index interface_type) {
550 std::type_index interface_type,
551 std::unordered_map<std::type_index, std::shared_ptr<void>>* scoped_instances) {
558 "Circular dependency detected: " + cycle_info,
559 "di::service_container"
565 std::shared_lock lock(
mutex_);
566 auto it =
services_.find(interface_type);
570 "Service not registered: " + std::string(interface_type.name()),
571 "di::service_container"
580 struct resolution_guard {
582 std::type_index type;
584 } guard{
this, interface_type};
587 std::shared_lock read_lock(
mutex_);
588 auto it =
services_.find(interface_type);
589 auto& entry = it->second;
593 auto factory_copy = entry.factory;
594 auto lifetime = entry.lifetime;
599 if (entry.is_instantiated) {
607 if (!factory_result.is_ok()) {
608 return factory_result;
612 std::unique_lock write_lock(
mutex_);
615 auto it2 =
services_.find(interface_type);
616 auto& entry2 = it2->second;
617 if (entry2.is_instantiated) {
622 entry2.singleton_instance = std::move(factory_result.value());
623 entry2.is_instantiated =
true;
635 if (scoped_instances ==
nullptr) {
638 "Cannot resolve scoped service from root container. Use create_scope().",
639 "di::service_container"
644 auto scoped_it = scoped_instances->find(interface_type);
645 if (scoped_it != scoped_instances->end()) {
652 if (!factory_result.is_ok()) {
653 return factory_result;
656 auto instance = std::move(factory_result.value());
657 (*scoped_instances)[interface_type] = instance;
664 "Unknown service lifetime",
665 "di::service_container"
671 std::shared_lock lock(
mutex_);
676 std::string type_name = interface_type.name();
682 "Container is frozen"));
685 "Cannot unregister service: container is frozen",
686 "di::service_container"
690 std::unique_lock lock(
mutex_);
692 auto it =
services_.find(interface_type);
697 "Service not registered"));
700 "Service not registered",
701 "di::service_container"
758 return std::make_unique<service_scope>(
parent_);
767 std::unique_lock lock(
mutex_);
773 std::type_index interface_type,
774 const std::string& type_name,
782 std::type_index interface_type,
783 const std::string& type_name,
784 std::shared_ptr<void> instance) {
790 std::type_index interface_type) {
794 std::unique_lock lock(
mutex_);
Result type for error handling with member function support.
static Result< T > ok(U &&value)
Create a successful result with value (static factory)
Abstract interface for dependency injection containers.
Scoped service container for request-level isolation.
Concrete implementation of IServiceContainer.
std::unordered_map< std::type_index, service_entry > services_
VoidResult register_factory_internal(std::type_index interface_type, const std::string &type_name, std::function< std::shared_ptr< void >(IServiceContainer &)> factory, service_lifetime lifetime) override
Internal factory registration (type-erased).
VoidResult check_already_registered(std::type_index interface_type, const std::string &type_name) const
Check if a service is already registered and log audit event if so.
static thread_local std::unordered_set< std::type_index > resolution_stack_
bool is_registered_internal(std::type_index interface_type) const override
Internal registration check (type-erased).
VoidResult unregister_internal(std::type_index interface_type) override
Internal unregistration (type-erased).
bool is_resolving(std::type_index interface_type) const
Check if currently resolving this type (circular dependency check).
std::string get_resolution_stack_string() const
Get current resolution stack as string for error messages.
Result< std::shared_ptr< void > > resolve_internal(std::type_index interface_type) override
Internal service resolution (type-erased).
Result< std::shared_ptr< void > > resolve_with_detection(std::type_index interface_type, std::unordered_map< std::type_index, std::shared_ptr< void > > *scoped_instances=nullptr)
Resolve a service with circular dependency detection.
service_container(const service_container &)=delete
VoidResult register_instance_internal(std::type_index interface_type, const std::string &type_name, std::shared_ptr< void > instance) override
Internal instance registration (type-erased).
void freeze()
Freeze the container to prevent further registrations.
service_container(service_container &&)=delete
static service_container & global()
Get the global service container instance.
bool is_frozen() const
Check if the container is frozen.
void push_resolution(std::type_index interface_type)
Push type onto resolution stack.
service_container & operator=(const service_container &)=delete
~service_container() override=default
Destructor.
std::atomic< bool > frozen_
std::vector< service_descriptor > registered_services() const override
Get list of all registered service descriptors.
VoidResult check_frozen_for_registration(const std::string &type_name, interfaces::registry_action action, const std::string &error_message) const
Check if container is frozen and log audit event if so.
VoidResult clear() override
Clear all registrations.
std::unique_ptr< IServiceScope > create_scope() override
Create a new service scope.
service_container & operator=(service_container &&)=delete
static thread_local std::vector< std::type_index > resolution_order_
service_container()=default
Default constructor.
Result< std::shared_ptr< void > > invoke_factory_safe(const std::function< std::shared_ptr< void >(IServiceContainer &)> &factory)
Safely invoke a factory function with exception handling.
void pop_resolution(std::type_index interface_type)
Pop type from resolution stack.
Scoped service container implementation.
service_scope & operator=(const service_scope &)=delete
std::unique_ptr< IServiceScope > create_scope() override
Create a new service scope.
service_container & parent_
~service_scope() override=default
Destructor - disposes scoped instances.
service_scope(const service_scope &)=delete
std::unordered_map< std::type_index, std::shared_ptr< void > > scoped_instances_
bool is_registered_internal(std::type_index interface_type) const override
Internal registration check (type-erased).
service_scope & operator=(service_scope &&)=delete
VoidResult unregister_internal(std::type_index interface_type) override
Internal unregistration (type-erased).
IServiceContainer & parent() override
Get the parent container.
VoidResult register_instance_internal(std::type_index interface_type, const std::string &type_name, std::shared_ptr< void > instance) override
Internal instance registration (type-erased).
VoidResult register_factory_internal(std::type_index interface_type, const std::string &type_name, std::function< std::shared_ptr< void >(IServiceContainer &)> factory, service_lifetime lifetime) override
Internal factory registration (type-erased).
Result< std::shared_ptr< void > > resolve_internal(std::type_index interface_type) override
Internal service resolution (type-erased).
service_scope(service_scope &&)=delete
std::vector< service_descriptor > registered_services() const override
Get list of all registered service descriptors.
service_scope(service_container &parent)
Construct a scope with a parent container.
VoidResult clear() override
Clear all registrations.
static void log_event(const registry_event &event)
Log a registry event.
constexpr int scoped_from_root
Scoped service resolved from root container.
constexpr int circular_dependency
Circular dependency detected during resolution.
constexpr int invalid_lifetime
Invalid service lifetime configuration.
constexpr int factory_error
Factory threw an exception during instantiation.
constexpr int service_not_registered
Service not registered in container.
constexpr int already_registered
Service already registered (duplicate registration attempt)
service_lifetime
Defines the lifetime policy for registered services.
@ singleton
Single instance shared globally.
@ scoped
Single instance within a scope.
@ transient
New instance created for each request.
constexpr int REGISTRY_FROZEN
registry_action
Types of registry mutation actions.
@ register_service
Service registration.
@ unregister_service
Service unregistration.
@ freeze_service_container
Freeze service container.
@ clear_services
Clear all services.
Result< T > make_error(int code, const std::string &message, const std::string &module="")
Create an error result with code and message.
VoidResult ok()
Create a successful void result.
Audit logging for registry operations.
Service container interfaces for dependency injection.
Internal service registration entry.
service_entry(std::type_index type, std::string name, std::function< std::shared_ptr< void >(IServiceContainer &)> f, service_lifetime lt)
std::shared_ptr< void > singleton_instance
std::function< std::shared_ptr< void >(IServiceContainer &)> factory
service_lifetime lifetime
std::type_index interface_type
Metadata describing a registered service.
bool is_instantiated
Whether this service has been instantiated (for singletons)
Represents a single audit event for registry mutations.
static constexpr source_location current(const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE()) noexcept