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
20namespace immer {
21
22/*!
23 * Metafunction that returns the best *transience policy* to use for a
24 * given *refcount policy*.
25 */
26template <typename RefcountPolicy>
27struct 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
34template <typename T>
35using 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 */
41template <typename HeapPolicy>
42struct 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
50template <typename T>
51constexpr 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 */
58template <typename RefcountPolicy>
59struct get_use_transient_rvalues
60 : std::integral_constant<bool,
61 !std::is_same<
62 RefcountPolicy,
63 no_refcount_policy>::value>
64{};
65
66template <typename T>
67constexpr 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 */
87template <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>>
92struct 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
113using default_heap_policy = heap_policy<debug_size_heap<cpp_heap>>;
114#else
115#if IMMER_NO_THREAD_SAFETY
116using default_heap_policy = unsafe_free_list_heap_policy<cpp_heap>;
117#else
118using 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
126using default_refcount_policy = unsafe_refcount_policy;
127#else
128using default_refcount_policy = refcount_policy;
129#endif
130
131/*!
132 * The default memory policy.
133 */
134using default_memory_policy = memory_policy<
135 default_heap_policy,
136 default_refcount_policy>;
137
138} // namespace immer
139