1515
1616#include < swoc/MemArena.h>
1717#include < swoc/Errata.h>
18+ #include < swoc/IntrusiveHashMap.h>
1819
1920#include " txn_box/common.h"
2021#include " txn_box/Rxp.h"
@@ -37,12 +38,6 @@ class Context
3738{
3839 using self_type = Context;
3940 friend class Config ;
40- // / Cleanup functor for an inverted arena.
41- // / @internal Because the arena is inverted, calling the destructor will clean up everything.
42- // / For this reason @c delete must @b not be called (that will double free).
43- struct ArenaDestructor {
44- void operator ()(swoc::MemArena *arena);
45- };
4641
4742public:
4843 // / Construct based a specific configuration.
@@ -147,7 +142,32 @@ class Context
147142 *
148143 * @see mark_for_cleanup
149144 */
150- template <typename T> swoc::MemSpan<T> alloc_span (unsigned count);
145+ template <typename T> swoc::MemSpan<T> alloc_span (unsigned count, size_t align = 1 );
146+
147+ /* * Find or allocate an instance of @a T in configuration storage.
148+ *
149+ * @tparam T Type of object.
150+ * @tparam Args Arguments to @a T constructor.
151+ * @param name Name of object.
152+ * @return A pointer to an initialized instance of @a T in configuration storage.
153+ *
154+ * Looks for the named object and if found returns it. If the name is not found, a @a T is
155+ * allocated and constructed with the arguments after @a name forwarded.
156+ *
157+ * @note This should only be called during configuration loading.
158+ */
159+ template < typename T, typename ... Args > T * obtain_named_object (swoc::TextView name, Args && ... args);
160+
161+ /* * Find named object.
162+ *
163+ * @tparam T Expected type of object.
164+ * @param name Name of the object.
165+ * @return A pointer to the object, or @c nullptr if not found.
166+ *
167+ * @note The caller is presumed to know that @a T is correct, no checks are done. This is purely a convenience to
168+ * avoid excessive casting.
169+ */
170+ template < typename T > T * named_object (swoc::TextView name);
151171
152172 /* * Require @a n bytes of transient buffer.
153173 *
@@ -515,6 +535,13 @@ class Context
515535 swoc::MemSpan<void > _storage;
516536 };
517537
538+ // / Cleanup functor for an inverted arena.
539+ // / @internal Because the arena is inverted, calling the destructor will clean up everything.
540+ // / For this reason @c delete must @b not be called (that will double free).
541+ struct ArenaDestructor {
542+ void operator ()(swoc::MemArena *arena);
543+ };
544+
518545 // / Transaction local storage.
519546 // / This is a pointer so that the arena can be inverted to minimize allocations.
520547 std::unique_ptr<swoc::MemArena, ArenaDestructor> _arena;
@@ -567,20 +594,9 @@ class Context
567594 // / Linkage for @c IntrusiveHashMap.
568595 struct Linkage : public swoc ::IntrusiveLinkage<self_type, &self_type::_next, &self_type::_prev> {
569596 static swoc::TextView
570- key_of (self_type *self)
571- {
572- return self->_name ;
573- }
574- static auto
575- hash_of (swoc::TextView const &text) -> decltype (Hash_Func(text))
576- {
577- return Hash_Func (text);
578- }
579- static bool
580- equal (swoc::TextView const &lhs, swoc::TextView const &rhs)
581- {
582- return lhs == rhs;
583- }
597+ key_of (self_type *self) { return self->_name ; }
598+ static auto hash_of (swoc::TextView const &text) -> decltype(Hash_Func(text)){ return Hash_Func (text); }
599+ static bool equal (swoc::TextView const &lhs, swoc::TextView const &rhs) { return lhs == rhs; }
584600 };
585601
586602 TxnVar (swoc::TextView const &name, Feature const &value) : _name(name), _value(value) {}
@@ -589,6 +605,30 @@ class Context
589605 using TxnVariables = swoc::IntrusiveHashMap<TxnVar::Linkage>;
590606 TxnVariables _txn_vars; // /< Variables for the transaction.
591607
608+ // / Internal named object local to the context.
609+ struct NamedObject {
610+ using self_type = NamedObject; // /< Self reference type.
611+ static constexpr std::hash<std::string_view> Hash_Func{};
612+
613+ swoc::TextView _name; // /< Name of variable.
614+ swoc::MemSpan<void > _span; // /< Object memroy.
615+ self_type *_next = nullptr ; // /< Intrusive link.
616+ self_type *_prev = nullptr ; // /< Intrusive link.
617+
618+ // / Linkage for @c IntrusiveHashMap.
619+ struct Linkage : public swoc ::IntrusiveLinkage<self_type, &self_type::_next, &self_type::_prev> {
620+ static swoc::TextView
621+ key_of (self_type *self) { return self->_name ; }
622+ static auto hash_of (swoc::TextView const &text) -> decltype(Hash_Func(text)){ return Hash_Func (text); }
623+ static bool equal (swoc::TextView const &lhs, swoc::TextView const &rhs) { return lhs == rhs; }
624+ };
625+
626+ NamedObject (swoc::TextView const &name, swoc::MemSpan<void > span) : _name(name), _span(span) {}
627+ };
628+
629+ using NamedObjects = swoc::IntrusiveHashMap<NamedObject::Linkage>;
630+ NamedObjects _named_objects; // /< Conext local data objects.
631+
592632 // / Flag for continuing invoking directives.
593633 bool _terminal_p = false ;
594634
@@ -639,10 +679,10 @@ Context::mark_for_cleanup(T* ptr, void (*cleaner)(T*))
639679
640680template <typename T>
641681swoc::MemSpan<T>
642- Context::alloc_span (unsigned int count)
682+ Context::alloc_span (unsigned count, size_t align )
643683{
644684 this ->commit_transient ();
645- return _arena->alloc (sizeof (T) * count).rebind <T>();
685+ return _arena->alloc (sizeof (T) * count, align ).rebind <T>();
646686}
647687
648688inline swoc::MemSpan<void >
@@ -754,3 +794,25 @@ Context::inbound_ssn()
754794{
755795 return _txn.inbound_ssn ();
756796}
797+
798+ template <typename T, typename ... Args>
799+ T *
800+ Context::obtain_named_object (swoc::TextView name, Args&&... args)
801+ {
802+ auto spot = _named_objects.find (name);
803+ if (spot != _named_objects.end ()) {
804+ return static_cast <T*>(spot->_span .data ());
805+ }
806+
807+ auto span = this ->alloc_span <T>(1 , alignof (T));
808+ _named_objects.insert (this ->make <NamedObject>(name, span));
809+ return new (span.data ()) T (std::forward<Args>(args)...);
810+ }
811+
812+ template <typename T>
813+ T *
814+ Context::named_object (swoc::TextView name)
815+ {
816+ auto spot = _named_objects.find (name);
817+ return spot != _named_objects.end () ? static_cast <T*>(spot->_span .data ()) : nullptr ;
818+ }
0 commit comments