Everett
Loading...
Searching...
No Matches
catalog_bindings.h
Go to the documentation of this file.
1
12#pragma once
13
14#include <everett/object_path.h>
15
16#include <functional>
17#include <memory>
18#include <mutex>
19#include <vector>
20
21namespace everett {
22 // Embedded in a shared immutable owner, rather than kept in a weak-owner
23 // table. Catalog copies can share an identity, so the canonical local root
24 // also distinguishes their file namespaces. This cache performs no I/O.
25 template <class T> struct catalog_bindings {
26 using pointer = std::shared_ptr<T const>;
27 private:
28 struct slot {
30 std::filesystem::path root;
31 std::mutex mutex;
33 slot(object_id id, std::filesystem::path path) : catalog(std::move(id)), root(std::move(path)) {}
34 };
35 public:
36 // Prepare every slot before acquiring a batch. Once any claim is held,
37 // try_lock is the only permitted acquisition: unrelated producers may be
38 // holding a parent while waiting for one of our dependencies.
39 // A locked producer is thread-affine: move it only within that thread,
40 // and install, release or destroy it on the thread which acquired it.
41 struct producer {
42 producer(producer const &) = delete;
43 producer & operator=(producer const &) = delete;
44 producer(producer &&) noexcept = default;
45 producer & operator=(producer &&) = delete;
46 bool try_lock() { return lock_.try_lock(); }
47 pointer value() const {
48 if (!lock_.owns_lock()) throw std::logic_error("unclaimed catalog owner");
49 return entry_->value;
50 }
51 void release() noexcept { if (lock_.owns_lock()) lock_.unlock(); }
53 if (!lock_.owns_lock() || entry_->value || !value)
54 throw std::logic_error("invalid catalog owner installation");
55 entry_->value = std::move(value);
56 lock_.unlock();
57 }
58 private:
59 friend struct catalog_bindings;
60 std::shared_ptr<slot> entry_;
61 std::unique_lock<std::mutex> lock_;
62 explicit producer(std::shared_ptr<slot> entry)
63 : entry_(std::move(entry)), lock_(entry_->mutex, std::defer_lock) {}
64 };
65 producer prepare(object_id const & catalog, std::filesystem::path const & root) const {
66 return producer(locate(catalog, root, true));
67 }
68 catalog_bindings() = default;
71
72 pointer find(object_id const & catalog, std::filesystem::path const & root) const {
73 auto entry = locate(catalog, root, false);
74 if (!entry) return {};
75 std::lock_guard lock(entry->mutex);
76 return entry->value;
77 }
78
79 // A producer installs only an acknowledged immutable result. An exception
80 // leaves the slot empty: another healthy backend can make a fresh attempt.
81 // Producers may resolve immediate dependencies in an acyclic owner graph,
82 // but must not retain locks on unrelated roots. Queries never use this lock.
83 template <class F> pointer get_or_create(object_id const & catalog,
84 std::filesystem::path const & root, F && produce) const {
85 auto entry = locate(catalog, root, true);
86 std::lock_guard lock(entry->mutex);
87 if (!entry->value) {
88 pointer value = std::invoke(std::forward<F>(produce));
89 if (!value) throw std::logic_error("null catalog owner binding");
90 entry->value = std::move(value);
91 }
92 return entry->value;
93 }
94
95 private:
96 mutable std::mutex mutex_;
97 mutable std::vector<std::shared_ptr<slot>> entries_;
98
99 std::shared_ptr<slot> locate(object_id const & catalog, std::filesystem::path const & root, bool create) const {
100 std::lock_guard lock(mutex_);
101 for (auto const & entry : entries_)
102 if (entry->catalog == catalog && entry->root == root) return entry;
103 if (!create) return {};
104 auto entry = std::make_shared<slot>(catalog, root);
105 entries_.push_back(entry);
106 return entry;
107 }
108 };
109}
Definition active_engine.h:18
Declares Everett's object path support.
Definition catalog_bindings.h:41
std::unique_lock< std::mutex > lock_
Definition catalog_bindings.h:61
bool try_lock()
Definition catalog_bindings.h:46
producer(producer &&) noexcept=default
void install(pointer value)
Definition catalog_bindings.h:52
producer(producer const &)=delete
producer(std::shared_ptr< slot > entry)
Definition catalog_bindings.h:62
pointer value() const
Definition catalog_bindings.h:47
std::shared_ptr< slot > entry_
Definition catalog_bindings.h:60
producer & operator=(producer const &)=delete
void release() noexcept
Definition catalog_bindings.h:51
Definition catalog_bindings.h:28
object_id catalog
Definition catalog_bindings.h:29
pointer value
Definition catalog_bindings.h:32
slot(object_id id, std::filesystem::path path)
Definition catalog_bindings.h:33
std::filesystem::path root
Definition catalog_bindings.h:30
std::mutex mutex
Definition catalog_bindings.h:31
Definition catalog_bindings.h:25
pointer get_or_create(object_id const &catalog, std::filesystem::path const &root, F &&produce) const
Definition catalog_bindings.h:83
producer prepare(object_id const &catalog, std::filesystem::path const &root) const
Definition catalog_bindings.h:65
std::shared_ptr< T const > pointer
Definition catalog_bindings.h:26
pointer find(object_id const &catalog, std::filesystem::path const &root) const
Definition catalog_bindings.h:72
std::shared_ptr< slot > locate(object_id const &catalog, std::filesystem::path const &root, bool create) const
Definition catalog_bindings.h:99
catalog_bindings(catalog_bindings const &)=delete
catalog_bindings & operator=(catalog_bindings const &)=delete
std::vector< std::shared_ptr< slot > > entries_
Definition catalog_bindings.h:97
std::mutex mutex_
Definition catalog_bindings.h:96
Definition object_path.h:38