16#include <unordered_map>
39template <
typename Access>
class access_tracker {
40 std::shared_ptr<context> ctx;
42 std::function<Access(access_tracker &)> access_factory;
47 explicit access_tracker(std::shared_ptr<context> context, std::string name)
48 : ctx(std::move(context)), name(std::move(name)) {}
64 auto operator=(access_tracker
const &) =
delete;
68 auto operator=(access_tracker &&rhs)
noexcept -> access_tracker &;
85 assert(not access_factory);
86 access_factory = std::move(factory);
113class context :
public std::enable_shared_from_this<context> {
119 std::unordered_map<std::string, std::any> trackers;
121 template <
typename Access>
friend class access_tracker;
123 template <
typename Access>
124 void update_tracker_address(std::string
const &name,
125 access_tracker<Access> *ptr) {
127 *std::any_cast<access_tracker<Access> *>(&trackers.at(name)) = ptr;
135 context(context
const &) =
delete;
136 auto operator=(context
const &) =
delete;
137 context(context &&) =
delete;
138 auto operator=(context &&) =
delete;
139 ~context() =
default;
145 static auto create() -> std::shared_ptr<context> {
146 return std::shared_ptr<context>(
new context());
158 template <
typename Access>
159 auto tracker(std::string name) -> access_tracker<Access> {
160 if (trackers.count(name) != 0) {
161 throw std::logic_error(
162 "cannot create tracker for existing name: " + name);
164 auto ret = access_tracker<Access>(shared_from_this(), std::move(name));
165 trackers.insert({ret.name, std::any(&ret)});
179 template <
typename Access>
auto access(std::string
const &name) -> Access {
181 std::any_cast<access_tracker<Access> *>(trackers.at(name));
182 if (tracker_ptr ==
nullptr)
183 throw std::logic_error(
"cannot access destroyed object: " + name);
184 return tracker_ptr->access_factory(*tracker_ptr);
193template <
typename Access>
195 : ctx(std::move(other.ctx)), name(std::move(other.name)),
196 access_factory(std::move(other.access_factory)) {
198 ctx->update_tracker_address(name,
this);
201template <
typename Access>
204 ctx = std::move(rhs.ctx);
205 name = std::move(rhs.name);
206 access_factory = std::move(rhs.access_factory);
208 ctx->update_tracker_address(name,
this);
214 ctx->update_tracker_address<Access>(name,
nullptr);
223#if defined(__GNUC__) || defined(__clang__)
224#define LIBTCSPC_INTERNAL_DISABLE_OFFSETOF_WARNING \
225 _Pragma("GCC diagnostic push"); \
226 _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
227#define LIBTCSPC_INTERNAL_POP_OFFSETOF_WARNING _Pragma("GCC diagnostic pop")
229#define LIBTCSPC_INTERNAL_DISABLE_OFFSETOF_WARNING
230#define LIBTCSPC_INTERNAL_POP_OFFSETOF_WARNING
253#define LIBTCSPC_OBJECT_FROM_TRACKER(obj_type, tracker_field_name, tracker) \
254 std::invoke([&tracker]() { \
255 LIBTCSPC_INTERNAL_DISABLE_OFFSETOF_WARNING; \
256 return reinterpret_cast<std::add_pointer_t<obj_type>>( \
257 reinterpret_cast<std::byte *>(&(tracker)) - \
258 offsetof(obj_type, tracker_field_name)); \
259 LIBTCSPC_INTERNAL_POP_OFFSETOF_WARNING; \
Tracker that mediates access to objects via a tcspc::context.
Definition context.hpp:39
access_tracker()=default
Construct an empty tracker.
void register_access_factory(F factory)
Register an access factory with this tracker's context.
Definition context.hpp:83
Context for enabling access to objects after they have been incorporated into a processing graph.
Definition context.hpp:113
static auto create() -> std::shared_ptr< context >
Create an instance.
Definition context.hpp:145
auto access(std::string const &name) -> Access
Obtain an access for the named object.
Definition context.hpp:179
auto tracker(std::string name) -> access_tracker< Access >
Obtain a tracker for an object with the given name.
Definition context.hpp:159
libtcspc namespace.
Definition acquire.hpp:29