1 | // |
2 | // immer: immutable data structures for C++ |
3 | // Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente |
4 | // |
5 | // This software is distributed under the Boost Software License, Version 1.0. |
6 | // See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt |
7 | // |
8 | |
9 | #pragma once |
10 | |
11 | #include <immer/heap/cpp_heap.hpp> |
12 | #include <immer/heap/heap_policy.hpp> |
13 | #include <immer/refcount/refcount_policy.hpp> |
14 | #include <immer/refcount/unsafe_refcount_policy.hpp> |
15 | #include <immer/refcount/no_refcount_policy.hpp> |
16 | #include <immer/transience/no_transience_policy.hpp> |
17 | #include <immer/transience/gc_transience_policy.hpp> |
18 | #include <type_traits> |
19 | |
20 | namespace immer { |
21 | |
22 | /*! |
23 | * Metafunction that returns the best *transience policy* to use for a |
24 | * given *refcount policy*. |
25 | */ |
26 | template <typename RefcountPolicy> |
27 | struct get_transience_policy |
28 | : std::conditional<std::is_same<RefcountPolicy, |
29 | no_refcount_policy>::value, |
30 | gc_transience_policy, |
31 | no_transience_policy> |
32 | {}; |
33 | |
34 | template <typename T> |
35 | using get_transience_policy_t = typename get_transience_policy<T>::type; |
36 | |
37 | /*! |
38 | * Metafunction that returns wether to *prefer fewer bigger objects* |
39 | * to use for a given *heap policy*. |
40 | */ |
41 | template <typename HeapPolicy> |
42 | struct get_prefer_fewer_bigger_objects |
43 | : std::integral_constant<bool, |
44 | std::is_same< |
45 | HeapPolicy, |
46 | heap_policy<cpp_heap> |
47 | >::value> |
48 | {}; |
49 | |
50 | template <typename T> |
51 | constexpr auto get_prefer_fewer_bigger_objects_v = |
52 | get_prefer_fewer_bigger_objects<T>::value; |
53 | |
54 | /*! |
55 | * Metafunction that returns wether to use *transient R-Values* |
56 | * for a given *refcount policy*. |
57 | */ |
58 | template <typename RefcountPolicy> |
59 | struct get_use_transient_rvalues |
60 | : std::integral_constant<bool, |
61 | !std::is_same< |
62 | RefcountPolicy, |
63 | no_refcount_policy>::value> |
64 | {}; |
65 | |
66 | template <typename T> |
67 | constexpr auto get_use_transient_rvalues_v = get_use_transient_rvalues<T>::value; |
68 | |
69 | /*! |
70 | * This is a default implementation of a *memory policy*. A memory |
71 | * policy is just a bag of other policies plus some flags with hints |
72 | * to the user about the best way to use these strategies. |
73 | * |
74 | * @tparam HeapPolicy A *heap policy*, for example, @ref heap_policy. |
75 | * @tparam RefcountPolicy A *reference counting policy*, for example, |
76 | * @ref refcount_policy. |
77 | * @tparam TransiencePolicy A *transience policy*, for example, |
78 | * @ref no_transience_policy. |
79 | * @tparam PreferFewerBiggerObjects Boolean flag indicating whether |
80 | * the user should prefer to allocate memory in bigger chungs |
81 | * --e.g. by putting various objects in the same memory |
82 | * region-- or not. |
83 | * @tparam UseTransientRValues Boolean flag indicating whether |
84 | * immutable containers should try to modify contents in-place |
85 | * when manipulating an r-value reference. |
86 | */ |
87 | template <typename HeapPolicy, |
88 | typename RefcountPolicy, |
89 | typename TransiencePolicy = get_transience_policy_t<RefcountPolicy>, |
90 | bool PreferFewerBiggerObjects = get_prefer_fewer_bigger_objects_v<HeapPolicy>, |
91 | bool UseTransientRValues = get_use_transient_rvalues_v<RefcountPolicy>> |
92 | struct memory_policy |
93 | { |
94 | using heap = HeapPolicy; |
95 | using refcount = RefcountPolicy; |
96 | using transience = TransiencePolicy; |
97 | |
98 | static constexpr bool prefer_fewer_bigger_objects = |
99 | PreferFewerBiggerObjects; |
100 | |
101 | static constexpr bool use_transient_rvalues = |
102 | UseTransientRValues; |
103 | |
104 | using transience_t = typename transience::template apply<heap>::type; |
105 | }; |
106 | |
107 | /*! |
108 | * The default *heap policy* just uses the standard heap with a |
109 | * @ref free_list_heap_policy. If `IMMER_NO_FREE_LIST` is defined to `1` |
110 | * then it just uses the standard heap. |
111 | */ |
112 | #if IMMER_NO_FREE_LIST |
113 | using default_heap_policy = heap_policy<debug_size_heap<cpp_heap>>; |
114 | #else |
115 | #if IMMER_NO_THREAD_SAFETY |
116 | using default_heap_policy = unsafe_free_list_heap_policy<cpp_heap>; |
117 | #else |
118 | using default_heap_policy = free_list_heap_policy<cpp_heap>; |
119 | #endif |
120 | #endif |
121 | |
122 | /*! |
123 | * By default we use thread safe reference counting. |
124 | */ |
125 | #if IMMER_NO_THREAD_SAFETY |
126 | using default_refcount_policy = unsafe_refcount_policy; |
127 | #else |
128 | using default_refcount_policy = refcount_policy; |
129 | #endif |
130 | |
131 | /*! |
132 | * The default memory policy. |
133 | */ |
134 | using default_memory_policy = memory_policy< |
135 | default_heap_policy, |
136 | default_refcount_policy>; |
137 | |
138 | } // namespace immer |
139 | |