Skip to content
This repository was archived by the owner on Jan 15, 2021. It is now read-only.

Commit b3ba411

Browse files
committed
Fix the static init fiasco
1 parent 86c8504 commit b3ba411

File tree

10 files changed

+251
-173
lines changed

10 files changed

+251
-173
lines changed

core-util/v2/detail/allocators.hpp

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,49 +17,68 @@
1717
#define FUNCTIONAL_DETAIL_ALLOCATORS_HPP
1818

1919
#include "interface.hpp"
20+
2021
#include "core-util/ExtendablePoolAllocator.h"
2122
#include "ualloc/ualloc.h"
2223

24+
#include <cstdint>
2325
namespace functional {
2426
namespace detail {
2527

2628
class ContainerAllocator : public mbed::util::ExtendablePoolAllocator {
2729
public:
28-
ContainerAllocator(size_t initial_elements, size_t new_pool_elements, size_t element_size,
29-
UAllocTraits_t alloc_traits, unsigned alignment = MBED_UTIL_POOL_ALLOC_DEFAULT_ALIGN)
30-
: mbed::util::ExtendablePoolAllocator()
31-
{
32-
this->init(initial_elements, new_pool_elements, element_size, alloc_traits, alignment);
33-
}
3430
template <typename FunctionType>
35-
bool free(FunctionInterface<FunctionType> * ptr) {
31+
void free(FunctionInterface<FunctionType> * ptr) {
3632
ptr->~FunctionInterface<FunctionType>();
3733
mbed::util::ExtendablePoolAllocator::free(ptr);
38-
return true;
3934
}
35+
ContainerAllocator(std::size_t initial_elements, std::size_t new_pool_elements, std::size_t element_size) :
36+
mbed::util::ExtendablePoolAllocator()
37+
{
38+
this->init(initial_elements, new_pool_elements, element_size, UAllocTraits_t{.flags = UALLOC_TRAITS_NEVER_FREE},
39+
MBED_UTIL_POOL_ALLOC_DEFAULT_ALIGN);
40+
}
41+
};
42+
43+
template <std::size_t ALLOC_SIZE>
44+
class ContainerAllocatorWrapper {
45+
public:
46+
static const std::size_t size = ALLOC_SIZE;
47+
static ContainerAllocator & instance();
4048
};
4149

42-
#if YOTTA_CONFIG_CORE_UTIL_FUNCTIONAL_FUNCTOR_SIZE
43-
#define FUNCTOR_SIZE YOTTA_CONFIG_CORE_UTIL_FUNCTIONAL_FUNCTOR_SIZE
44-
#else
50+
namespace alloc_size {
51+
class BaseClass {
52+
public:
53+
virtual void base_function(){}
54+
};
55+
class VirtualClass : public BaseClass {
56+
virtual void base_function(){}
57+
};
58+
class UnknownClass;
59+
60+
#ifndef YOTTA_CONFIG_CORE_UTIL_FUNCTIONAL_FUNCTOR_SIZE
4561
/*
46-
* Optimization note: This size was chosen to allow a Function to bind a DNS response.
62+
* This size was chosen to allow a Function to bind a DNS response.
63+
* 4 bytes for a reference count
4764
* 4 bytes for the vtable pointers
4865
* 4 bytes for the base Function
4966
* 128/8 bytes for an IPv6 address
5067
* 4 bytes for a char* pointer.
5168
* 4 bytes of padding to round out to 8-byte alignment.
52-
*
53-
* This size should be optimized further by examining application requirements.
5469
*/
55-
#define FUNCTOR_SIZE (4 + 4 + (128/8) + 4 + 4)
70+
#define YOTTA_CONFIG_CORE_UTIL_FUNCTIONAL_FUNCTOR_SIZE \
71+
((sizeof(std::uint32_t) + sizeof(VirtualClass) + sizeof(UnknownClass *) + 128/8 + sizeof(char *) + 7) & ~7)
5672
#endif
5773

74+
const std::size_t staticfp = sizeof(std::uint32_t) + sizeof(VirtualClass) + sizeof(void(*)());
75+
const std::size_t memberfp = sizeof(std::uint32_t) + sizeof(VirtualClass) + sizeof(UnknownClass *) + sizeof(void (UnknownClass::*)());
76+
const std::size_t functorfp = YOTTA_CONFIG_CORE_UTIL_FUNCTIONAL_FUNCTOR_SIZE;
77+
}
5878

59-
extern ContainerAllocator StaticFPAllocator;
60-
extern ContainerAllocator MemberFPAllocator;
61-
extern ContainerAllocator FunctorFPAllocator;
62-
79+
using StaticFPAllocator = ContainerAllocatorWrapper<alloc_size::staticfp>;
80+
using MemberFPAllocator = ContainerAllocatorWrapper<alloc_size::memberfp>;
81+
using FunctorFPAllocator = ContainerAllocatorWrapper<alloc_size::functorfp>;
6382

6483
} // detail
6584
} // functional

core-util/v2/detail/capture.hpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "interface.hpp"
2222
#include "allocators.hpp"
2323

24+
#include "core-util/assert.h"
25+
2426
namespace functional {
2527
namespace detail {
2628

@@ -38,10 +40,10 @@ struct generator<0, S...> {
3840
};
3941
} // namespace index
4042

41-
template <typename FunctionType, ContainerAllocator & Allocator, typename... CapturedTypes>
43+
template <typename FunctionType, ContainerAllocator & (*Allocator)(), typename... CapturedTypes>
4244
class CaptureFirst;
4345

44-
template <typename ReturnType, typename... ArgTypes, ContainerAllocator & Allocator, typename... CapturedTypes>
46+
template <typename ReturnType, typename... ArgTypes, ContainerAllocator & (*Allocator)(), typename... CapturedTypes>
4547
class CaptureFirst <ReturnType(ArgTypes...), Allocator, CapturedTypes...>
4648
: public FunctionInterface <ReturnType(ArgTypes...)> {
4749
public:
@@ -58,12 +60,12 @@ class CaptureFirst <ReturnType(ArgTypes...), Allocator, CapturedTypes...>
5860
return f(
5961
polyfill::forward<CapturedTypes>(
6062
polyfill::get<S,CapturedTypes...>(storage)
61-
)...,
63+
)...,
6264
polyfill::forward<ArgTypes>(Args)...);
6365
}
6466

65-
virtual ContainerAllocator * get_allocator() {
66-
return & Allocator;
67+
virtual ContainerAllocator & get_allocator() {
68+
return Allocator();
6769
}
6870
protected:
6971
/*
@@ -77,10 +79,10 @@ class CaptureFirst <ReturnType(ArgTypes...), Allocator, CapturedTypes...>
7779
polyfill::tuple<CapturedTypes...> storage;
7880
};
7981

80-
template <typename FunctionType, ContainerAllocator & Allocator, typename... CapturedTypes>
82+
template <typename FunctionType, ContainerAllocator & (*Allocator)(), typename... CapturedTypes>
8183
class CaptureLast;
8284

83-
template <typename ReturnType, typename... ArgTypes, ContainerAllocator & Allocator, typename... CapturedTypes>
85+
template <typename ReturnType, typename... ArgTypes, ContainerAllocator & (*Allocator)(), typename... CapturedTypes>
8486
class CaptureLast <ReturnType(ArgTypes...), Allocator, CapturedTypes...>
8587
: public FunctionInterface <ReturnType(ArgTypes...)> {
8688
public:
@@ -96,8 +98,8 @@ class CaptureLast <ReturnType(ArgTypes...), Allocator, CapturedTypes...>
9698
return f(polyfill::forward<ArgTypes>(Args)..., polyfill::forward<CapturedTypes>(polyfill::get<S,CapturedTypes...>(storage))...);
9799
}
98100

99-
virtual ContainerAllocator * get_allocator() {
100-
return & Allocator;
101+
virtual ContainerAllocator & get_allocator() {
102+
return Allocator();
101103
}
102104
protected:
103105

@@ -136,9 +138,9 @@ struct RemoveLastArgs <ReturnType(Types0...), ReturnType(Transfer1, Types1...),
136138

137139
template <typename ReturnType, typename... ArgTypes, typename... ParentTypes, typename... CapturedTypes>
138140
Function<ReturnType(ArgTypes...)> bind_last(Function<ReturnType(ArgTypes...)> &&, Function<ReturnType(ParentTypes...)>& f, CapturedTypes... CapturedArgs) {
139-
using CaptureFP = CaptureLast<ReturnType(ArgTypes...), FunctorFPAllocator, CapturedTypes...>;
140-
static_assert(sizeof(CaptureFP) <= FUNCTOR_SIZE, "Size of bound arguments is too large" );
141-
CaptureFP * newf = reinterpret_cast<CaptureFP *>(detail::FunctorFPAllocator.alloc());
141+
using CaptureFP = CaptureLast<ReturnType(ArgTypes...), FunctorFPAllocator::instance, CapturedTypes...>;
142+
static_assert(sizeof(CaptureFP) <= alloc_size::functorfp, "Size of bound arguments is too large" );
143+
CaptureFP * newf = reinterpret_cast<CaptureFP *>(detail::FunctorFPAllocator::instance().alloc());
142144
CORE_UTIL_ASSERT_MSG(newf, "Function container memory allocation failed");
143145
new(newf) CaptureFP(f,polyfill::forward<CapturedTypes>(CapturedArgs)...);
144146
return Function<ReturnType(ArgTypes...)>(static_cast<FunctionInterface<ReturnType(ArgTypes...)>*>(newf));

core-util/v2/detail/functor.hpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ namespace functional {
2323
namespace detail {
2424

2525

26-
template <typename F, typename FunctionType, ContainerAllocator & Allocator>
26+
template <typename F, typename FunctionType, ContainerAllocator & (*Allocator)()>
2727
class FunctorContainer;
2828

29-
template <typename F, typename ReturnType, typename... ArgTypes, ContainerAllocator & Allocator>
29+
template <typename F, typename ReturnType, typename... ArgTypes, ContainerAllocator & (*Allocator)()>
3030
class FunctorContainer <F, ReturnType(ArgTypes...), Allocator> : public FunctionInterface <ReturnType(ArgTypes...)> {
3131
public:
3232
FunctorContainer(const F & f) : f(f) {}
@@ -35,15 +35,9 @@ class FunctorContainer <F, ReturnType(ArgTypes...), Allocator> : public Function
3535
virtual ReturnType operator () (ArgTypes&&... Args) {
3636
return f(polyfill::forward<ArgTypes>(Args)...);
3737
}
38-
virtual ContainerAllocator * get_allocator() {
39-
return &Allocator;
38+
virtual ContainerAllocator & get_allocator() {
39+
return Allocator();
4040
}
41-
42-
// virtual void deallocate(FunctionInterface<ReturnType(ArgTypes...)> *ptr){
43-
// (void)ptr;
44-
// this->~FunctionInterface();
45-
// Allocator.free(this);
46-
// }
4741
protected:
4842
F f;
4943
};

core-util/v2/detail/interface.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class FunctionInterface <ReturnType(ArgTypes...)> {
3333
public:
3434
FunctionInterface() : refcnt(0) {}
3535
virtual ReturnType operator () (ArgTypes&&... Args) = 0;
36-
virtual ContainerAllocator *get_allocator() = 0;
36+
virtual ContainerAllocator & get_allocator() = 0;
3737
inline uint32_t inc()
3838
{
3939
return mbed::util::atomic_incr(&refcnt, static_cast<uint32_t>(1));

core-util/v2/detail/member.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ class MemberContainer <C, ReturnType(ArgTypes...)> : public FunctionInterface <R
3535
virtual ReturnType operator () (ArgTypes&&... Args) {
3636
return (obj->*fp)(polyfill::forward<ArgTypes>(Args)...);
3737
}
38-
virtual ContainerAllocator * get_allocator() {
39-
return & MemberFPAllocator;
38+
virtual ContainerAllocator & get_allocator() {
39+
return MemberFPAllocator::instance();
4040
}
4141

4242
// virtual void deallocate(FunctionInterface<ReturnType(ArgTypes...)> *ptr) {

core-util/v2/detail/polyfill.hpp

Lines changed: 21 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#define CORE_UTIL_V2_DETAIL_POLYFILL_HPP
1818

1919
namespace polyfill {
20+
// From ARM Compiler armcc User Guide {
21+
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472k/chr1407404265784.html
2022
template< class T > struct remove_reference {typedef T type;};
2123
template< class T > struct remove_reference<T&> {typedef T type;};
2224
template< class T > struct remove_reference<T&&> {typedef T type;};
@@ -34,6 +36,9 @@ forward(typename remove_reference<T>::type& a) noexcept
3436
{
3537
return static_cast<T&&>(a);
3638
}
39+
/// } From ARM Compiler armcc User Guide
40+
41+
3742
template<class T>
3843
T&&
3944
forward(typename remove_reference<T>::type&& a) noexcept
@@ -64,7 +69,6 @@ struct conditional<false, T0, T1> {
6469
using type = T1;
6570
};
6671

67-
6872
template <bool, typename T = void>
6973
struct enable_if_impl {};
7074

@@ -76,9 +80,6 @@ struct enable_if_impl<true, T> {
7680
template <bool B, typename T = void>
7781
struct enable_if : public enable_if_impl<B, T> {};
7882

79-
template <class Condition, typename T = void>
80-
struct enable_if_c : public enable_if_impl<Condition::value, T> {};
81-
8283
template <typename T0, typename T1>
8384
struct align_gt {
8485
static constexpr bool value = __alignof__(T0) > __alignof__(T1);
@@ -95,7 +96,7 @@ struct enable_if_align_le : enable_if<align_le<T0,T1>::value, T> {};
9596

9697

9798

98-
template <size_t I, typename T0, typename... T>
99+
template <unsigned I, typename T0, typename... T>
99100
struct tuple_element {
100101
using type = typename tuple_element<I-1,T...>::type;
101102
};
@@ -105,62 +106,46 @@ struct tuple_element<0,T0,T...> {
105106
using type = T0;
106107
};
107108

108-
template <typename Enable, typename... T>
109+
template <typename... T>
109110
struct tuple_impl;
110111

111112
template <typename T0>
112-
struct tuple_impl<void, T0> {
113+
struct tuple_impl<T0> {
113114
T0 t0;
114115
tuple_impl(const T0 &t0) : t0(forward<const T0 &>(t0)) {}
115-
template <size_t I>
116+
template <unsigned I>
116117
typename tuple_element<I,T0>::type & get() {
117118
static_assert(I == 0, "tuple range exceeded");
118119
return t0;
119120
}
120121
};
121122

122-
template <typename T0, typename T1, typename... T>
123-
struct tuple_impl<typename enable_if_align_gt<T0, T1>::type, T0, T1, T...> {
123+
template <typename T0, typename... T>
124+
struct tuple_impl<T0, T...> {
124125
T0 t0;
125-
tuple_impl<void, T1, T...> t;
126+
tuple_impl<T...> t;
126127

127-
tuple_impl(const T0 &t0, const T1 &t1, const T&... t) :
128-
t0(forward<const T0 &>(t0)), t(forward<const T1 &>(t1), forward<const T &>(t)...) {}
129-
template <size_t I>
130-
typename enable_if<I != 0, typename tuple_element<I,T0,T1,T...>::type>::type & get() {
128+
tuple_impl(const T0 &t0, const T&... t) :
129+
t0(forward<const T0 &>(t0)), t(forward<const T &>(t)...) {}
130+
template <unsigned I>
131+
typename enable_if<I != 0, typename tuple_element<I, T0, T...>::type>::type & get() {
131132
return t.get<I-1>();
132133
}
133-
template <size_t I>
134-
typename enable_if<I == 0, typename tuple_element<I,T0,T1,T...>::type>::type & get() {
134+
template <unsigned I>
135+
typename enable_if<I == 0, typename tuple_element<I, T0, T...>::type>::type & get() {
135136
return t0;
136137
}
137138
};
138139

139-
template <typename T0, typename T1, typename... T>
140-
struct tuple_impl<typename enable_if_align_le<T0, T1>::type, T0, T1, T...> {
141-
tuple_impl<void, T1, T...> t;
142-
T0 t0;
143-
144-
tuple_impl(const T0 &t0, const T1 &t1, const T&... t) :
145-
t(forward<const T1 &>(t1), forward<const T &>(t)...), t0(forward<const T0 &>(t0)) {}
146-
template <size_t I>
147-
typename enable_if<I != 0, typename tuple_element<I,T0,T1,T...>::type>::type & get() {
148-
return t.get<I-1>();
149-
}
150-
template <size_t I>
151-
typename enable_if<I == 0, typename tuple_element<I,T0,T1,T...>::type>::type & get() {
152-
return t0;
153-
}
154-
};
155140

156141

157142
template <typename... T>
158-
struct tuple : public tuple_impl<void, T...> {
159-
tuple(const T&... t) : tuple_impl<void, T...>(forward<const T &>(t)...) {}
143+
struct tuple : public tuple_impl<T...> {
144+
tuple(const T&... t) : tuple_impl<T...>(forward<const T &>(t)...) {}
160145
tuple(){}
161146
};
162147

163-
template <size_t I, typename... T>
148+
template <unsigned I, typename... T>
164149
constexpr typename tuple_element<I, T...>::type & get(tuple<T...> & t) {
165150
return t.get<I>();
166151
}

core-util/v2/detail/static.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ class StaticContainer <ReturnType(ArgTypes...)> : public FunctionInterface <Retu
3434
virtual ReturnType operator () (ArgTypes&&... Args) {
3535
return fp(polyfill::forward<ArgTypes>(Args)...);
3636
}
37-
virtual ContainerAllocator * get_allocator() {
38-
return & StaticFPAllocator;
37+
virtual ContainerAllocator & get_allocator() {
38+
return StaticFPAllocator::instance();
3939
}
4040

4141
// virtual void deallocate(FunctionInterface<ReturnType(ArgTypes...)> *ptr) {

0 commit comments

Comments
 (0)