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

Commit

Permalink
Fix the static init fiasco
Browse files Browse the repository at this point in the history
  • Loading branch information
bremoran committed Feb 17, 2016
1 parent 86c8504 commit b3ba411
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 173 deletions.
57 changes: 38 additions & 19 deletions core-util/v2/detail/allocators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,68 @@
#define FUNCTIONAL_DETAIL_ALLOCATORS_HPP

#include "interface.hpp"

#include "core-util/ExtendablePoolAllocator.h"
#include "ualloc/ualloc.h"

#include <cstdint>
namespace functional {
namespace detail {

class ContainerAllocator : public mbed::util::ExtendablePoolAllocator {
public:
ContainerAllocator(size_t initial_elements, size_t new_pool_elements, size_t element_size,
UAllocTraits_t alloc_traits, unsigned alignment = MBED_UTIL_POOL_ALLOC_DEFAULT_ALIGN)
: mbed::util::ExtendablePoolAllocator()
{
this->init(initial_elements, new_pool_elements, element_size, alloc_traits, alignment);
}
template <typename FunctionType>
bool free(FunctionInterface<FunctionType> * ptr) {
void free(FunctionInterface<FunctionType> * ptr) {
ptr->~FunctionInterface<FunctionType>();
mbed::util::ExtendablePoolAllocator::free(ptr);
return true;
}
ContainerAllocator(std::size_t initial_elements, std::size_t new_pool_elements, std::size_t element_size) :
mbed::util::ExtendablePoolAllocator()
{
this->init(initial_elements, new_pool_elements, element_size, UAllocTraits_t{.flags = UALLOC_TRAITS_NEVER_FREE},
MBED_UTIL_POOL_ALLOC_DEFAULT_ALIGN);
}
};

template <std::size_t ALLOC_SIZE>
class ContainerAllocatorWrapper {
public:
static const std::size_t size = ALLOC_SIZE;
static ContainerAllocator & instance();
};

#if YOTTA_CONFIG_CORE_UTIL_FUNCTIONAL_FUNCTOR_SIZE
#define FUNCTOR_SIZE YOTTA_CONFIG_CORE_UTIL_FUNCTIONAL_FUNCTOR_SIZE
#else
namespace alloc_size {
class BaseClass {
public:
virtual void base_function(){}
};
class VirtualClass : public BaseClass {
virtual void base_function(){}
};
class UnknownClass;

#ifndef YOTTA_CONFIG_CORE_UTIL_FUNCTIONAL_FUNCTOR_SIZE
/*
* Optimization note: This size was chosen to allow a Function to bind a DNS response.
* This size was chosen to allow a Function to bind a DNS response.
* 4 bytes for a reference count
* 4 bytes for the vtable pointers
* 4 bytes for the base Function
* 128/8 bytes for an IPv6 address
* 4 bytes for a char* pointer.
* 4 bytes of padding to round out to 8-byte alignment.
*
* This size should be optimized further by examining application requirements.
*/
#define FUNCTOR_SIZE (4 + 4 + (128/8) + 4 + 4)
#define YOTTA_CONFIG_CORE_UTIL_FUNCTIONAL_FUNCTOR_SIZE \
((sizeof(std::uint32_t) + sizeof(VirtualClass) + sizeof(UnknownClass *) + 128/8 + sizeof(char *) + 7) & ~7)
#endif

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

extern ContainerAllocator StaticFPAllocator;
extern ContainerAllocator MemberFPAllocator;
extern ContainerAllocator FunctorFPAllocator;

using StaticFPAllocator = ContainerAllocatorWrapper<alloc_size::staticfp>;
using MemberFPAllocator = ContainerAllocatorWrapper<alloc_size::memberfp>;
using FunctorFPAllocator = ContainerAllocatorWrapper<alloc_size::functorfp>;

} // detail
} // functional
Expand Down
26 changes: 14 additions & 12 deletions core-util/v2/detail/capture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "interface.hpp"
#include "allocators.hpp"

#include "core-util/assert.h"

namespace functional {
namespace detail {

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

template <typename FunctionType, ContainerAllocator & Allocator, typename... CapturedTypes>
template <typename FunctionType, ContainerAllocator & (*Allocator)(), typename... CapturedTypes>
class CaptureFirst;

template <typename ReturnType, typename... ArgTypes, ContainerAllocator & Allocator, typename... CapturedTypes>
template <typename ReturnType, typename... ArgTypes, ContainerAllocator & (*Allocator)(), typename... CapturedTypes>
class CaptureFirst <ReturnType(ArgTypes...), Allocator, CapturedTypes...>
: public FunctionInterface <ReturnType(ArgTypes...)> {
public:
Expand All @@ -58,12 +60,12 @@ class CaptureFirst <ReturnType(ArgTypes...), Allocator, CapturedTypes...>
return f(
polyfill::forward<CapturedTypes>(
polyfill::get<S,CapturedTypes...>(storage)
)...,
)...,
polyfill::forward<ArgTypes>(Args)...);
}

virtual ContainerAllocator * get_allocator() {
return & Allocator;
virtual ContainerAllocator & get_allocator() {
return Allocator();
}
protected:
/*
Expand All @@ -77,10 +79,10 @@ class CaptureFirst <ReturnType(ArgTypes...), Allocator, CapturedTypes...>
polyfill::tuple<CapturedTypes...> storage;
};

template <typename FunctionType, ContainerAllocator & Allocator, typename... CapturedTypes>
template <typename FunctionType, ContainerAllocator & (*Allocator)(), typename... CapturedTypes>
class CaptureLast;

template <typename ReturnType, typename... ArgTypes, ContainerAllocator & Allocator, typename... CapturedTypes>
template <typename ReturnType, typename... ArgTypes, ContainerAllocator & (*Allocator)(), typename... CapturedTypes>
class CaptureLast <ReturnType(ArgTypes...), Allocator, CapturedTypes...>
: public FunctionInterface <ReturnType(ArgTypes...)> {
public:
Expand All @@ -96,8 +98,8 @@ class CaptureLast <ReturnType(ArgTypes...), Allocator, CapturedTypes...>
return f(polyfill::forward<ArgTypes>(Args)..., polyfill::forward<CapturedTypes>(polyfill::get<S,CapturedTypes...>(storage))...);
}

virtual ContainerAllocator * get_allocator() {
return & Allocator;
virtual ContainerAllocator & get_allocator() {
return Allocator();
}
protected:

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

template <typename ReturnType, typename... ArgTypes, typename... ParentTypes, typename... CapturedTypes>
Function<ReturnType(ArgTypes...)> bind_last(Function<ReturnType(ArgTypes...)> &&, Function<ReturnType(ParentTypes...)>& f, CapturedTypes... CapturedArgs) {
using CaptureFP = CaptureLast<ReturnType(ArgTypes...), FunctorFPAllocator, CapturedTypes...>;
static_assert(sizeof(CaptureFP) <= FUNCTOR_SIZE, "Size of bound arguments is too large" );
CaptureFP * newf = reinterpret_cast<CaptureFP *>(detail::FunctorFPAllocator.alloc());
using CaptureFP = CaptureLast<ReturnType(ArgTypes...), FunctorFPAllocator::instance, CapturedTypes...>;
static_assert(sizeof(CaptureFP) <= alloc_size::functorfp, "Size of bound arguments is too large" );
CaptureFP * newf = reinterpret_cast<CaptureFP *>(detail::FunctorFPAllocator::instance().alloc());
CORE_UTIL_ASSERT_MSG(newf, "Function container memory allocation failed");
new(newf) CaptureFP(f,polyfill::forward<CapturedTypes>(CapturedArgs)...);
return Function<ReturnType(ArgTypes...)>(static_cast<FunctionInterface<ReturnType(ArgTypes...)>*>(newf));
Expand Down
14 changes: 4 additions & 10 deletions core-util/v2/detail/functor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ namespace functional {
namespace detail {


template <typename F, typename FunctionType, ContainerAllocator & Allocator>
template <typename F, typename FunctionType, ContainerAllocator & (*Allocator)()>
class FunctorContainer;

template <typename F, typename ReturnType, typename... ArgTypes, ContainerAllocator & Allocator>
template <typename F, typename ReturnType, typename... ArgTypes, ContainerAllocator & (*Allocator)()>
class FunctorContainer <F, ReturnType(ArgTypes...), Allocator> : public FunctionInterface <ReturnType(ArgTypes...)> {
public:
FunctorContainer(const F & f) : f(f) {}
Expand All @@ -35,15 +35,9 @@ class FunctorContainer <F, ReturnType(ArgTypes...), Allocator> : public Function
virtual ReturnType operator () (ArgTypes&&... Args) {
return f(polyfill::forward<ArgTypes>(Args)...);
}
virtual ContainerAllocator * get_allocator() {
return &Allocator;
virtual ContainerAllocator & get_allocator() {
return Allocator();
}

// virtual void deallocate(FunctionInterface<ReturnType(ArgTypes...)> *ptr){
// (void)ptr;
// this->~FunctionInterface();
// Allocator.free(this);
// }
protected:
F f;
};
Expand Down
2 changes: 1 addition & 1 deletion core-util/v2/detail/interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class FunctionInterface <ReturnType(ArgTypes...)> {
public:
FunctionInterface() : refcnt(0) {}
virtual ReturnType operator () (ArgTypes&&... Args) = 0;
virtual ContainerAllocator *get_allocator() = 0;
virtual ContainerAllocator & get_allocator() = 0;
inline uint32_t inc()
{
return mbed::util::atomic_incr(&refcnt, static_cast<uint32_t>(1));
Expand Down
4 changes: 2 additions & 2 deletions core-util/v2/detail/member.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ class MemberContainer <C, ReturnType(ArgTypes...)> : public FunctionInterface <R
virtual ReturnType operator () (ArgTypes&&... Args) {
return (obj->*fp)(polyfill::forward<ArgTypes>(Args)...);
}
virtual ContainerAllocator * get_allocator() {
return & MemberFPAllocator;
virtual ContainerAllocator & get_allocator() {
return MemberFPAllocator::instance();
}

// virtual void deallocate(FunctionInterface<ReturnType(ArgTypes...)> *ptr) {
Expand Down
57 changes: 21 additions & 36 deletions core-util/v2/detail/polyfill.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#define CORE_UTIL_V2_DETAIL_POLYFILL_HPP

namespace polyfill {
// From ARM Compiler armcc User Guide {
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472k/chr1407404265784.html
template< class T > struct remove_reference {typedef T type;};
template< class T > struct remove_reference<T&> {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};
Expand All @@ -34,6 +36,9 @@ forward(typename remove_reference<T>::type& a) noexcept
{
return static_cast<T&&>(a);
}
/// } From ARM Compiler armcc User Guide


template<class T>
T&&
forward(typename remove_reference<T>::type&& a) noexcept
Expand Down Expand Up @@ -64,7 +69,6 @@ struct conditional<false, T0, T1> {
using type = T1;
};


template <bool, typename T = void>
struct enable_if_impl {};

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

template <class Condition, typename T = void>
struct enable_if_c : public enable_if_impl<Condition::value, T> {};

template <typename T0, typename T1>
struct align_gt {
static constexpr bool value = __alignof__(T0) > __alignof__(T1);
Expand All @@ -95,7 +96,7 @@ struct enable_if_align_le : enable_if<align_le<T0,T1>::value, T> {};



template <size_t I, typename T0, typename... T>
template <unsigned I, typename T0, typename... T>
struct tuple_element {
using type = typename tuple_element<I-1,T...>::type;
};
Expand All @@ -105,62 +106,46 @@ struct tuple_element<0,T0,T...> {
using type = T0;
};

template <typename Enable, typename... T>
template <typename... T>
struct tuple_impl;

template <typename T0>
struct tuple_impl<void, T0> {
struct tuple_impl<T0> {
T0 t0;
tuple_impl(const T0 &t0) : t0(forward<const T0 &>(t0)) {}
template <size_t I>
template <unsigned I>
typename tuple_element<I,T0>::type & get() {
static_assert(I == 0, "tuple range exceeded");
return t0;
}
};

template <typename T0, typename T1, typename... T>
struct tuple_impl<typename enable_if_align_gt<T0, T1>::type, T0, T1, T...> {
template <typename T0, typename... T>
struct tuple_impl<T0, T...> {
T0 t0;
tuple_impl<void, T1, T...> t;
tuple_impl<T...> t;

tuple_impl(const T0 &t0, const T1 &t1, const T&... t) :
t0(forward<const T0 &>(t0)), t(forward<const T1 &>(t1), forward<const T &>(t)...) {}
template <size_t I>
typename enable_if<I != 0, typename tuple_element<I,T0,T1,T...>::type>::type & get() {
tuple_impl(const T0 &t0, const T&... t) :
t0(forward<const T0 &>(t0)), t(forward<const T &>(t)...) {}
template <unsigned I>
typename enable_if<I != 0, typename tuple_element<I, T0, T...>::type>::type & get() {
return t.get<I-1>();
}
template <size_t I>
typename enable_if<I == 0, typename tuple_element<I,T0,T1,T...>::type>::type & get() {
template <unsigned I>
typename enable_if<I == 0, typename tuple_element<I, T0, T...>::type>::type & get() {
return t0;
}
};

template <typename T0, typename T1, typename... T>
struct tuple_impl<typename enable_if_align_le<T0, T1>::type, T0, T1, T...> {
tuple_impl<void, T1, T...> t;
T0 t0;

tuple_impl(const T0 &t0, const T1 &t1, const T&... t) :
t(forward<const T1 &>(t1), forward<const T &>(t)...), t0(forward<const T0 &>(t0)) {}
template <size_t I>
typename enable_if<I != 0, typename tuple_element<I,T0,T1,T...>::type>::type & get() {
return t.get<I-1>();
}
template <size_t I>
typename enable_if<I == 0, typename tuple_element<I,T0,T1,T...>::type>::type & get() {
return t0;
}
};


template <typename... T>
struct tuple : public tuple_impl<void, T...> {
tuple(const T&... t) : tuple_impl<void, T...>(forward<const T &>(t)...) {}
struct tuple : public tuple_impl<T...> {
tuple(const T&... t) : tuple_impl<T...>(forward<const T &>(t)...) {}
tuple(){}
};

template <size_t I, typename... T>
template <unsigned I, typename... T>
constexpr typename tuple_element<I, T...>::type & get(tuple<T...> & t) {
return t.get<I>();
}
Expand Down
4 changes: 2 additions & 2 deletions core-util/v2/detail/static.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class StaticContainer <ReturnType(ArgTypes...)> : public FunctionInterface <Retu
virtual ReturnType operator () (ArgTypes&&... Args) {
return fp(polyfill::forward<ArgTypes>(Args)...);
}
virtual ContainerAllocator * get_allocator() {
return & StaticFPAllocator;
virtual ContainerAllocator & get_allocator() {
return StaticFPAllocator::instance();
}

// virtual void deallocate(FunctionInterface<ReturnType(ArgTypes...)> *ptr) {
Expand Down
Loading

0 comments on commit b3ba411

Please sign in to comment.