Air-Trap 1.0.0
A multiplayer R-Type clone game engine built with C++23 and ECS architecture
Loading...
Searching...
No Matches
LibraryManager.cpp
Go to the documentation of this file.
1/*
2** EPITECH PROJECT, 2025
3** R-Type
4** File description:
5** LibraryManager.cpp, implementation of dynamic library manager
6*/
7
8/*
9** MIT License
10**
11** Copyright (c) 2025 Robin Toillon
12**
13** Permission is hereby granted, free of charge, to any person obtaining
14** a copy of this software and associated documentation files (the
15** "Software"), to deal in the Software without restriction, including
16** without limitation the rights to use, copy, modify, merge, publish,
17** distribute, sublicense, and/or sell copies of the Software, and to
18** permit persons to whom the Software is furnished to do so, subject to
19** the following conditions:
20**
21** The above copyright notice and this permission notice shall be
22** included in all copies or substantial portions of the Software.
23**
24** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
28** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
29** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31*/
32
47#include "LibraryBackend.hpp"
48
49#include <format>
50#include <mutex>
51
52namespace rtp::sys
53{
55 // Public API
57
58 auto LibraryManager::load(std::string_view path)
59 -> std::expected<const DynamicLibrary *, rtp::Error>
60 {
61 return this->getOrLoadInternal(path).transform(
62 [](const std::shared_ptr<DynamicLibrary> &libPtr)
63 -> const DynamicLibrary *
64 {
65 return libPtr.get();
66 });
67 }
68
69 auto LibraryManager::loadShared(std::string_view path)
70 -> std::expected<std::shared_ptr<DynamicLibrary>, rtp::Error>
71 {
72 return this->getOrLoadInternal(path);
73 }
74
75 auto LibraryManager::loadStandalone(std::string_view path)
76 -> std::expected<std::unique_ptr<DynamicLibrary>, rtp::Error>
77 {
78 auto handle = impl::LibraryBackend::open(path);
79 if (!handle.has_value()) [[unlikely]]
80 return std::unexpected{Error::failure(ErrorCode::LibraryLoadFailed,
81 "Failed to load dynamic library at " \
82 "'{}': '{}'", path, handle.error())};
83
84 return std::make_unique<DynamicLibrary>(handle.value());
85 }
86
88 // Private API
90
91 auto LibraryManager::getOrLoadInternal(std::string_view path)
92 -> std::expected<std::shared_ptr<DynamicLibrary>, rtp::Error>
93 {
94 const std::string pathStr{path}; // TODO: avoid copy, by adding HashStringView
95 // as key in unordered_map
96
97 // --- READ LOCK --- (Cache hit)
98 {
99 std::shared_lock lock{this->_mutex};
100 auto it = this->_libraries.find(pathStr);
101 if (it != this->_libraries.end()) [[likely]]
102 return it->second;
103 }
104 // --- WRITE LOCK --- (Cache miss)
105 {
106 std::unique_lock lock{this->_mutex};
107 auto it = this->_libraries.find(pathStr);
108 if (it != this->_libraries.end()) [[unlikely]]
109 return it->second;
110
111 auto handle = impl::LibraryBackend::open(path);
112 if (!handle.has_value()) [[unlikely]]
113 return std::unexpected{
115 "Failed to load dynamic library at " \
116 "'{}': '{}'", path, handle.error())};
117
118 auto lib = std::make_shared<DynamicLibrary>(handle.value());
119 this->_libraries.emplace(std::string{path}, lib);
120
121 return lib;
122 }
123 }
124}
Declarations for platform-specific dynamic library handling.
Declaration of the Dynamic Library Manager.
Comprehensive error object with severity and retry tracking.
Definition Error.hpp:156
static auto failure(ErrorCode code, std::format_string< Args... > fmt, Args &&...args) -> Error
Create a failure-level error.
Represents a dynamically loaded library.
auto get(std::string_view name) const -> std::expected< T, rtp::Error >
Get a symbol from the dynamic library.
auto loadShared(std::string_view path) -> std::expected< std::shared_ptr< DynamicLibrary >, rtp::Error >
Shared API.
auto load(std::string_view path) -> std::expected< const DynamicLibrary *, rtp::Error >
Main API.
static auto loadStandalone(std::string_view path) -> std::expected< std::unique_ptr< DynamicLibrary >, rtp::Error >
Isolated API (Factory).
auto getOrLoadInternal(std::string_view path) -> std::expected< std::shared_ptr< DynamicLibrary >, rtp::Error >
Get an existing library or load it if not present.
static auto open(std::string_view path) -> std::expected< void *, rtp::Error >
Open a dynamic library from the given path.
@ LibraryLoadFailed
Failed to load dynamic library.