Skip to content

Commit dcb9823

Browse files
committed
This fixes the problems when using containers in global variables
Because of initialization order issues, before this change, it could happen that a global container using a free_list as part of its memory policy would be initialized before the state of the free list. This fixes the problem, thus addressing issue #37
1 parent 546d0de commit dcb9823

3 files changed

Lines changed: 34 additions & 34 deletions

File tree

immer/heap/free_list_heap.hpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ struct free_list_heap : Base
4949

5050
free_list_node* n;
5151
do {
52-
n = head_.data;
52+
n = head().data;
5353
if (!n) {
5454
auto p = base_t::allocate(Size + sizeof(free_list_node));
5555
return static_cast<free_list_node*>(p);
5656
}
57-
} while (!head_.data.compare_exchange_weak(n, n->next));
58-
head_.count.fetch_sub(1u, std::memory_order_relaxed);
57+
} while (!head().data.compare_exchange_weak(n, n->next));
58+
head().count.fetch_sub(1u, std::memory_order_relaxed);
5959
return n;
6060
}
6161

@@ -67,14 +67,14 @@ struct free_list_heap : Base
6767

6868
// we use relaxed, because we are fine with temporarily having
6969
// a few more/less buffers in free list
70-
if (head_.count.load(std::memory_order_relaxed) >= Limit) {
70+
if (head().count.load(std::memory_order_relaxed) >= Limit) {
7171
base_t::deallocate(Size + sizeof(free_list_node), data);
7272
} else {
7373
auto n = static_cast<free_list_node*>(data);
7474
do {
75-
n->next = head_.data;
76-
} while (!head_.data.compare_exchange_weak(n->next, n));
77-
head_.count.fetch_add(1u, std::memory_order_relaxed);
75+
n->next = head().data;
76+
} while (!head().data.compare_exchange_weak(n->next, n));
77+
head().count.fetch_add(1u, std::memory_order_relaxed);
7878
}
7979
}
8080

@@ -85,10 +85,11 @@ struct free_list_heap : Base
8585
std::atomic<std::size_t> count;
8686
};
8787

88-
static head_t head_;
88+
static head_t& head()
89+
{
90+
static head_t head_{{nullptr}, {0}};
91+
return head_;
92+
}
8993
};
9094

91-
template <std::size_t S, std::size_t L, typename B>
92-
typename free_list_heap<S,L,B>::head_t free_list_heap<S,L,B>::head_ {{nullptr}, {0}};
93-
9495
} // namespace immer

immer/heap/thread_local_free_list_heap.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ struct thread_local_free_list_storage
3636
~head_t() { Heap::clear(); }
3737
};
3838

39-
thread_local static head_t head;
39+
static head_t& head()
40+
{
41+
thread_local static head_t head_{nullptr, 0};
42+
return head_;
43+
}
4044
};
4145

42-
template <typename Heap>
43-
thread_local typename thread_local_free_list_storage<Heap>::head_t
44-
thread_local_free_list_storage<Heap>::head {nullptr, 0};
45-
4646
} // namespace detail
4747

4848
/*!

immer/heap/unsafe_free_list_heap.hpp

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,13 @@ struct unsafe_free_list_storage
3636
std::size_t count;
3737
};
3838

39-
static head_t head;
39+
static head_t& head()
40+
{
41+
static head_t head_ {nullptr, 0};
42+
return head_;
43+
}
4044
};
4145

42-
template <typename Heap>
43-
typename unsafe_free_list_storage<Heap>::head_t
44-
unsafe_free_list_storage<Heap>::head {nullptr, 0};
45-
46-
4746
template <template<class>class Storage,
4847
std::size_t Size,
4948
std::size_t Limit,
@@ -61,13 +60,13 @@ class unsafe_free_list_heap_impl : Base
6160
assert(size <= sizeof(free_list_node) + Size);
6261
assert(size >= sizeof(free_list_node));
6362

64-
auto n = storage::head.data;
63+
auto n = storage::head().data;
6564
if (!n) {
6665
auto p = base_t::allocate(Size + sizeof(free_list_node));
6766
return static_cast<free_list_node*>(p);
6867
}
69-
--storage::head.count;
70-
storage::head.data = n->next;
68+
--storage::head().count;
69+
storage::head().data = n->next;
7170
return n;
7271
}
7372

@@ -77,23 +76,23 @@ class unsafe_free_list_heap_impl : Base
7776
assert(size <= sizeof(free_list_node) + Size);
7877
assert(size >= sizeof(free_list_node));
7978

80-
if (storage::head.count >= Limit)
79+
if (storage::head().count >= Limit)
8180
base_t::deallocate(Size + sizeof(free_list_node), data);
8281
else {
8382
auto n = static_cast<free_list_node*>(data);
84-
n->next = storage::head.data;
85-
storage::head.data = n;
86-
++storage::head.count;
83+
n->next = storage::head().data;
84+
storage::head().data = n;
85+
++storage::head().count;
8786
}
8887
}
8988

9089
static void clear()
9190
{
92-
while (storage::head.data) {
93-
auto n = storage::head.data->next;
94-
base_t::deallocate(Size + sizeof(free_list_node), storage::head.data);
95-
storage::head.data = n;
96-
--storage::head.count;
91+
while (storage::head().data) {
92+
auto n = storage::head().data->next;
93+
base_t::deallocate(Size + sizeof(free_list_node), storage::head().data);
94+
storage::head().data = n;
95+
--storage::head().count;
9796
}
9897
}
9998
};

0 commit comments

Comments
 (0)