remove ostd::Function after all (never supported allocators properly anyway)

master
Daniel Kolesa 2017-01-29 18:38:37 +01:00
parent 2c7f98f57e
commit 58a361e6e0
2 changed files with 17 additions and 448 deletions

View File

@ -19,11 +19,11 @@ namespace detail {
SignalBase(SignalBase const &ev):
p_class(ev.p_class), p_nfuncs(ev.p_nfuncs)
{
using Func = Function<void(C &, A...)>;
byte *bufp = new byte[sizeof(Func) * p_nfuncs];
Func *nbuf = reinterpret_cast<Func *>(bufp);
using func_t = std::function<void(C &, A...)>;
byte *bufp = new byte[sizeof(func_t) * p_nfuncs];
func_t *nbuf = reinterpret_cast<func_t *>(bufp);
for (Size i = 0; i < p_nfuncs; ++i)
new (&nbuf[i]) Func(ev.p_funcs[i]);
new (&nbuf[i]) func_t(ev.p_funcs[i]);
p_funcs = nbuf;
}
@ -34,13 +34,13 @@ namespace detail {
}
SignalBase &operator=(SignalBase const &ev) {
using Func = Function<void(C &, A...)>;
using func_t = std::function<void(C &, A...)>;
p_class = ev.p_class;
p_nfuncs = ev.p_nfuncs;
byte *bufp = new byte[sizeof(Func) * p_nfuncs];
Func *nbuf = reinterpret_cast<Func *>(bufp);
byte *bufp = new byte[sizeof(func_t) * p_nfuncs];
func_t *nbuf = reinterpret_cast<func_t *>(bufp);
for (Size i = 0; i < p_nfuncs; ++i) {
new (&nbuf[i]) Func(ev.p_funcs[i]);
new (&nbuf[i]) func_t(ev.p_funcs[i]);
}
p_funcs = nbuf;
return *this;
@ -55,7 +55,8 @@ namespace detail {
void clear() {
for (Size i = 0; i < p_nfuncs; ++i) {
p_funcs[i].~Function<void(C &, A...)>();
using func = std::function<void(C &, A...)>;
p_funcs[i].~func();
}
delete[] reinterpret_cast<byte *>(p_funcs);
p_funcs = nullptr;
@ -64,20 +65,20 @@ namespace detail {
template<typename F>
Size connect(F &&func) {
using Func = Function<void(C &, A...)>;
using func_t = std::function<void(C &, A...)>;
for (Size i = 0; i < p_nfuncs; ++i) {
if (!p_funcs[i]) {
p_funcs[i] = std::forward<F>(func);
return i;
}
}
byte *bufp = new byte[sizeof(Func) * (p_nfuncs + 1)];
Func *nbuf = reinterpret_cast<Func *>(bufp);
byte *bufp = new byte[sizeof(func_t) * (p_nfuncs + 1)];
func_t *nbuf = reinterpret_cast<func_t *>(bufp);
for (Size i = 0; i < p_nfuncs; ++i) {
new (&nbuf[i]) Func(std::move(p_funcs[i]));
p_funcs[i].~Func();
new (&nbuf[i]) func_t(std::move(p_funcs[i]));
p_funcs[i].~func_t();
}
new (&nbuf[p_nfuncs]) Func(std::forward<F>(func));
new (&nbuf[p_nfuncs]) func_t(std::forward<F>(func));
delete[] reinterpret_cast<byte *>(p_funcs);
p_funcs = nbuf;
return p_nfuncs++;
@ -122,7 +123,7 @@ namespace detail {
private:
C *p_class;
Function<void(C &, A...)> *p_funcs;
std::function<void(C &, A...)> *p_funcs;
Size p_nfuncs;
};
} /* namespace detail */

View File

@ -1,7 +1,6 @@
/* Function objects for OctaSTD.
*
* This file is part of OctaSTD. See COPYING.md for futher information.
* Portions of this file are originally adapted from the libc++ project.
*/
#ifndef OSTD_FUNCTIONAL_HH
@ -440,437 +439,6 @@ typename ToHash<T>::Result to_hash(T const &v) {
return ToHash<T>()(v);
}
/* function impl adapted from libc++
*/
template<typename>
class Function;
namespace detail {
template<typename T>
inline bool func_is_not_null(T const &) {
return true;
}
template<typename T>
inline bool func_is_not_null(T *ptr) {
return ptr;
}
template<typename R, typename C>
inline bool func_is_not_null(R C::*ptr) {
return ptr;
}
template<typename T>
inline bool func_is_not_null(Function<T> const &f) {
return !!f;
}
template<typename R>
struct FuncInvokeVoidReturnWrapper {
template<typename ...A>
static R call(A &&...args) {
return func_invoke(std::forward<A>(args)...);
}
};
template<>
struct FuncInvokeVoidReturnWrapper<void> {
template<typename ...A>
static void call(A &&...args) {
func_invoke(std::forward<A>(args)...);
}
};
template<typename T>
class FuncBase;
template<typename R, typename ...A>
class FuncBase<R(A...)> {
FuncBase(FuncBase const &);
FuncBase &operator=(FuncBase const &);
public:
FuncBase() {}
virtual ~FuncBase() {}
virtual FuncBase *clone() const = 0;
virtual void clone(FuncBase *) const = 0;
virtual void destroy() noexcept = 0;
virtual void destroy_deallocate() noexcept = 0;
virtual R operator()(A &&...args) = 0;
};
template<typename F, typename A, typename AT>
class FuncCore;
template<typename F, typename A, typename R, typename ...AT>
class FuncCore<F, A, R(AT...)>: public FuncBase<R(AT...)> {
CompressedPair<F, A> f_stor;
public:
explicit FuncCore(F &&f):
f_stor(
std::piecewise_construct,
std::forward_as_tuple(std::move(f)),
std::forward_as_tuple()
)
{}
explicit FuncCore(F const &f, A const &a):
f_stor(
std::piecewise_construct,
std::forward_as_tuple(f),
std::forward_as_tuple(a)
)
{}
explicit FuncCore(F const &f, A &&a):
f_stor(
std::piecewise_construct,
std::forward_as_tuple(f),
std::forward_as_tuple(std::move(a))
)
{}
explicit FuncCore(F &&f, A &&a):
f_stor(
std::piecewise_construct,
std::forward_as_tuple(std::move(f)),
std::forward_as_tuple(std::move(a))
)
{}
virtual FuncBase<R(AT...)> *clone() const;
virtual void clone(FuncBase<R(AT...)> *) const;
virtual void destroy() noexcept;
virtual void destroy_deallocate() noexcept;
virtual R operator()(AT &&...args);
};
template<typename F, typename A, typename R, typename ...AT>
FuncBase<R(AT...)> *FuncCore<F, A, R(AT...)>::clone() const {
using AA = AllocatorRebind<A, FuncCore>;
AA a(f_stor.second());
using D = AllocatorDestructor<AA>;
std::unique_ptr<FuncCore, D> hold(a.allocate(1), D(a, 1));
::new(hold.get()) FuncCore(f_stor.first(), A(a));
return hold.release();
}
template<typename F, typename A, typename R, typename ...AT>
void FuncCore<F, A, R(AT...)>::clone(FuncBase<R(AT...)> *p) const {
::new (p) FuncCore(f_stor.first(), f_stor.second());
}
template<typename F, typename A, typename R, typename ...AT>
void FuncCore<F, A, R(AT...)>::destroy() noexcept {
f_stor.~CompressedPair<F, A>();
}
template<typename F, typename A, typename R, typename ...AT>
void FuncCore<F, A, R(AT...)>::destroy_deallocate() noexcept {
using AA = AllocatorRebind<A, FuncCore>;
AA a(f_stor.second());
f_stor.~CompressedPair<F, A>();
a.deallocate(this, 1);
}
template<typename F, typename A, typename R, typename ...AT>
R FuncCore<F, A, R(AT...)>::operator()(AT &&...args) {
using Invoker = FuncInvokeVoidReturnWrapper<R>;
return Invoker::call(f_stor.first(), std::forward<AT>(args)...);
}
} /* namespace detail */
template<typename R, typename ...Args>
class Function<R(Args...)> {
using Base = detail::FuncBase<R(Args...)>;
AlignedStorage<3 * sizeof(void *)> p_buf;
Base *p_f;
static inline Base *as_base(void *p) {
return reinterpret_cast<Base *>(p);
}
template<
typename F,
bool = !IsSame<F, Function> && detail::IsInvokable<F &, Args...>
>
struct CallableBase;
template<typename F>
struct CallableBase<F, true> {
static constexpr bool value =
IsSame<R, void> || IsConvertible<detail::InvokeOf<F &, Args...>, R>;
};
template<typename F>
struct CallableBase<F, false> {
static constexpr bool value = false;
};
template<typename F>
static constexpr bool Callable = CallableBase<F>::value;
public:
using Result = R;
Function() noexcept: p_f(nullptr) {}
Function(Nullptr) noexcept: p_f(nullptr) {}
Function(Function const &);
Function(Function &&) noexcept;
template<
typename F, typename = EnableIf<Callable<F> && !IsSame<F, Function>>
>
Function(F);
template<typename A>
Function(AllocatorArg, A const &) noexcept: p_f(nullptr) {}
template<typename A>
Function(AllocatorArg, A const &, Nullptr) noexcept: p_f(nullptr) {}
template<typename A>
Function(AllocatorArg, A const &, Function const &);
template<typename A>
Function(AllocatorArg, A const &, Function &&);
template<typename F, typename A, typename = EnableIf<Callable<F>>>
Function(AllocatorArg, A const &, F);
Function &operator=(Function const &f) {
Function(f).swap(*this);
return *this;
}
Function &operator=(Function &&) noexcept;
Function &operator=(Nullptr) noexcept;
template<typename F>
EnableIf<
Callable<Decay<F>> && !IsSame<RemoveReference<F>, Function>,
Function &
> operator=(F &&f) {
Function(std::forward<F>(f)).swap(*this);
return *this;
}
~Function();
void swap(Function &) noexcept;
explicit operator bool() const noexcept { return p_f; }
/* deleted overloads close possible hole in the type system */
template<typename RR, typename ...AA>
bool operator==(Function<RR(AA...)> &) const = delete;
template<typename RR, typename ...AA>
bool operator!=(Function<RR(AA...)> &) const = delete;
R operator()(Args ...a) const {
return (*p_f)(std::forward<Args>(a)...);
}
};
template<typename R, typename ...Args>
Function<R(Args...)>::Function(Function const &f) {
if (!f.p_f) {
p_f = nullptr;
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
p_f = as_base(&p_buf);
f.p_f->clone(p_f);
} else {
p_f = f.p_f->clone();
}
}
template<typename R, typename ...Args>
template<typename A>
Function<R(Args...)>::Function(
AllocatorArg, A const &, Function const &f
) {
if (!f.p_f) {
p_f = nullptr;
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
p_f = as_base(&p_buf);
f.p_f->clone(p_f);
} else {
p_f = f.p_f->clone();
}
}
template<typename R, typename ...Args>
Function<R(Args...)>::Function(Function &&f) noexcept {
if (!f.p_f) {
p_f = nullptr;
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
p_f = as_base(&p_buf);
f.p_f->clone(p_f);
} else {
p_f = f.p_f;
f.p_f = nullptr;
}
}
template<typename R, typename ...Args>
template<typename A>
Function<R(Args...)>::Function(
AllocatorArg, A const &, Function &&f
) {
if (!f.p_f) {
p_f = nullptr;
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
p_f = as_base(&p_buf);
f.p_f->clone(p_f);
} else {
p_f = f.p_f;
f.p_f = nullptr;
}
}
template<typename R, typename ...Args>
template<typename F, typename>
Function<R(Args...)>::Function(F f): p_f(nullptr) {
if (!detail::func_is_not_null(f)) {
return;
}
using FF = detail::FuncCore<F, Allocator<F>, R(Args...)>;
if ((sizeof(FF) <= sizeof(p_buf)) && IsNothrowCopyConstructible<F>) {
p_f = ::new(static_cast<void *>(&p_buf)) FF(std::move(f));
return;
}
using AA = Allocator<FF>;
AA a;
using D = detail::AllocatorDestructor<AA>;
std::unique_ptr<FF, D> hold(a.allocate(1), D(a, 1));
::new(hold.get()) FF(std::move(f), Allocator<F>(a));
p_f = hold.release();
}
template<typename R, typename ...Args>
template<typename F, typename A, typename>
Function<R(Args...)>::Function(AllocatorArg, A const &a, F f):
p_f(nullptr)
{
if (!detail::func_is_not_null(f)) {
return;
}
using FF = detail::FuncCore<F, A, R(Args...)>;
using AA = AllocatorRebind<A, FF>;
AA aa(a);
if (
(sizeof(FF) <= sizeof(p_buf)) && IsNothrowCopyConstructible<F> &&
IsNothrowCopyConstructible<AA>
) {
p_f = ::new(static_cast<void *>(&p_buf)) FF(std::move(f), A(aa));
return;
}
using D = detail::AllocatorDestructor<AA>;
std::unique_ptr<FF, D> hold(aa.allocate(1), D(aa, 1));
::new(hold.get()) FF(std::move(f), A(aa));
p_f = hold.release();
}
template<typename R, typename ...Args>
Function<R(Args...)> &Function<R(Args...)>::operator=(Function &&f)
noexcept
{
if (static_cast<void *>(p_f) == &p_buf) {
p_f->destroy();
} else if (p_f) {
p_f->destroy_deallocate();
}
if (f.p_f == nullptr) {
p_f = nullptr;
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
p_f = as_base(&p_buf);
f.p_f->clone(p_f);
} else {
p_f = f.p_f;
f.p_f = nullptr;
}
return *this;
}
template<typename R, typename ...Args>
Function<R(Args...)> &Function<R(Args...)>::operator=(Nullptr) noexcept {
if (static_cast<void *>(p_f) == &p_buf) {
p_f->destroy();
} else if (p_f) {
p_f->destroy_deallocate();
}
p_f = nullptr;
return *this;
}
template<typename R, typename ...Args>
Function<R(Args...)>::~Function() {
if (static_cast<void *>(p_f) == &p_buf) {
p_f->destroy();
} else if (p_f) {
p_f->destroy_deallocate();
}
}
template<typename R, typename ...Args>
void Function<R(Args...)>::swap(Function &f) noexcept {
if (
(static_cast<void *>(p_f) == &p_buf) &&
(static_cast<void *>(f.p_f) == &f.p_buf)
) {
/* both in small storage */
AlignedStorage<sizeof(p_buf)> tmpbuf;
Base *t = as_base(&tmpbuf);
p_f->clone(t);
p_f->destroy();
p_f = nullptr;
f.p_f->clone(as_base(&p_buf));
f.p_f->destroy();
f.p_f = nullptr;
p_f = as_base(&p_buf);
t->clone(as_base(&f.p_buf));
t->destroy();
f.p_f = as_base(&f.p_buf);
} else if (static_cast<void *>(p_f) == &p_buf) {
/* ours in small storage */
p_f->clone(as_base(&f.p_buf));
p_f->destroy();
p_f = f.p_f;
f.p_f = as_base(&f.p_buf);
} else if (static_cast<void *>(f.p_f) == &f.p_buf) {
/* the other in small storage */
f.p_f->clone(as_base(&p_buf));
f.p_f->destroy();
f.p_f = p_f;
p_f = as_base(&p_buf);
} else {
using std::swap;
swap(p_f, f.p_f);
}
}
template<typename R, typename ...Args>
inline void swap(Function<R(Args...)> &a, Function<R(Args...)> &b) {
a.swap(b);
}
template<typename R, typename ...Args>
inline bool operator==(Function<R(Args...)> const &f, Nullptr) noexcept {
return !f;
}
template<typename R, typename ...Args>
inline bool operator==(Nullptr, Function<R(Args...)> const &f) noexcept {
return !f;
}
template<typename R, typename ...Args>
inline bool operator!=(Function<R(Args...)> const &f, Nullptr) noexcept {
return bool(f);
}
template<typename R, typename ...Args>
inline bool operator!=(Nullptr, Function<R(Args...)> const &f) noexcept {
return bool(f);
}
} /* namespace ostd */
#endif