Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Mapping_Factory.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Containers_Concrete_Mapping_Factory_h_
5#define _Stroika_Foundation_Containers_Concrete_Mapping_Factory_h_
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <type_traits>
10
11/**
12 * \file
13 */
14
16 template <typename KEY_TYPE, typename MAPPED_VALUE_TYPE>
17 class Mapping;
18}
19
20namespace Stroika::Foundation::Containers::Factory {
21
22 /**
23 * \brief Singleton factory object - Used to create the default backend implementation of a Mapping<> container; typically not called directly
24 *
25 * Note - you can override the underlying factory dynamically by calling Mapping_Factory<T,TRAITS>::Register ().
26 *
27 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
28 *
29 * \note Mapping_Factory<K,P> makes up its own default comparer, and so can use order mappings, like Mapping_stdmap, whereas
30 * Mapping_Factory<K,P,E> - since it takes an equals comparer - is restricted to backends that work with an equals comparere.
31 */
32 template <typename KEY_TYPE, typename VALUE_TYPE, IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER = equal_to<KEY_TYPE>>
34 private:
35 static inline atomic<Mapping<KEY_TYPE, VALUE_TYPE> (*) (const KEY_EQUALS_COMPARER&)> sFactory_{nullptr};
36
37 public:
38 static_assert (not is_reference_v<KEY_TYPE> and not is_reference_v<VALUE_TYPE> and not is_reference_v<KEY_EQUALS_COMPARER>,
39 "typically if this fails its because a (possibly indirect) caller forgot to use forward<TTT>(), or remove_cvref_t");
40
41 public:
42 /**
43 * The type of object produced by the factory.
44 */
46
47 public:
48 /**
49 * Function type to create an Mapping object.
50 */
51 using FactoryFunctionType = function<ConstructedType (const KEY_EQUALS_COMPARER& keyEqualsComparer)>;
52
53 public:
54 /**
55 * Hints can be used in factory constructor to guide the choice of the best container implementation/backend.
56 */
57 struct Hints {
58 optional<bool> fOptimizeForLookupSpeedOverUpdateSpeed;
59 };
60
61 public:
62 /**
63 * Construct a factory for producing new ConstructedType ivhects. The default is to use whatever was registered with
64 * Mapping_Factory::Register (), but a specific factory can easily be constructed with provided arguments.
65 */
66 constexpr Mapping_Factory ();
67 constexpr Mapping_Factory (const Hints& hints);
68 constexpr Mapping_Factory (const FactoryFunctionType& f);
69 constexpr Mapping_Factory (const Mapping_Factory&) = default;
70
71 public:
72 /**
73 * This can be called anytime, before main(), or after. BUT - beware, any calls to Register must
74 * be externally synchronized, meaning effectively that they must happen before the creation of any
75 * threads, to be safe. Also note, since this returns a const reference, any calls to Register() after
76 * a call to Default, even if synchronized, is suspect.
77 */
78 static const Mapping_Factory& Default ();
79
80 public:
81 /**
82 * You can call this directly, but there is no need, as the Mapping<T> CTOR does so automatically.
83 */
84 nonvirtual ConstructedType operator() (const KEY_EQUALS_COMPARER& keyEqualsComparer) const;
85
86 public:
87 /**
88 * Register a default global factory for Mapping objects (of the templated type/parameters).
89 * No need to call, typically, as the default factory is generally fine.
90 *
91 * \par Example Usage
92 * \code
93 * Mapping_Factory::Register(Mapping_Factory{Mapping_Factory::Hints{.fOptimizeForLookupSpeedOverUpdateSpeed=true});
94 * Mapping_Factory::Register(); // or use defaults
95 * \endcode
96 *
97 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
98 * BUT - special note/restriction - must be called before any threads call Association_Factory::Mapping_Factory() OR
99 * Mapping_Factory::Default(), which effectively means must be called at the start of main, but before creating any threads
100 * which might use the factory).
101 *
102 * \note this differs markedly from Stroika 2.1, where Register could be called anytime, and was internally synchronized.
103 *
104 * \note If you wanted a dynamically changeable factory (change after main), you could write one yourself with its own internal synchronization,
105 * set the global one here, then perform the changes to its internal structure through another API.
106 */
107 static void Register (const optional<Mapping_Factory>& f = nullopt);
108
109 private:
110 const FactoryFunctionType fFactory_;
111 const bool fHints_OptimizeForLookupSpeedOverUpdateSpeed{true};
112
113 private:
114 // function to assure magically constructed even if called before main
115 static Mapping_Factory& AccessDefault_ ();
116 };
117
118}
119
120/*
121 ********************************************************************************
122 ******************************* Implementation Details *************************
123 ********************************************************************************
124 */
125#include "Mapping_Factory.inl"
126
127#endif /*_Stroika_Foundation_Containers_Concrete_Mapping_Factory_h_ */
Singleton factory object - Used to create the default backend implementation of a Mapping<> container...
function< ConstructedType(const KEY_EQUALS_COMPARER &keyEqualsComparer)> FactoryFunctionType
static void Register(const optional< Mapping_Factory > &f=nullopt)
nonvirtual ConstructedType operator()(const KEY_EQUALS_COMPARER &keyEqualsComparer) const