Change manual ctor to be polymorphic

pull/13288/head
ncteisen 7 years ago
parent 344553c27c
commit 0a69e1ef09
  1. 2
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  2. 6
      src/core/ext/transport/chttp2/transport/internal.h
  3. 125
      src/core/lib/support/manual_constructor.h

@ -274,7 +274,7 @@ static void init_transport(grpc_exec_ctx* exec_ctx, grpc_chttp2_transport* t,
GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) ==
GRPC_CHTTP2_CLIENT_CONNECT_STRLEN);
t->abstract = new D1;
t->abstract.Init<Derived>();
t->abstract->foo();
t->base.vtable = get_vtable();

@ -243,9 +243,9 @@ class AbstractBase {
virtual void foo() { gpr_log(GPR_ERROR, "base"); }
};
class D1 : public AbstractBase {
class Derived : public AbstractBase {
public:
D1() {}
Derived() {}
void foo() override { gpr_log(GPR_ERROR, "derived"); }
};
@ -255,7 +255,7 @@ struct grpc_chttp2_transport {
grpc_endpoint* ep;
char* peer_string;
AbstractBase* abstract;
grpc_core::PolymorphicManualConstructor<AbstractBase, Derived> abstract;
grpc_combiner* combiner;

@ -22,12 +22,137 @@
// manually construct a region of memory with some type
#include <stddef.h>
#include <stdlib.h>
#include <new>
#include <type_traits>
#include <utility>
namespace grpc_core {
#define ASSERT(x) \
if ((x)) \
; \
else \
abort()
template <class Needle, class... Haystack>
class is_one_of;
template <class Needle, class... Haystack>
class is_one_of<Needle, Needle, Haystack...> {
public:
static constexpr const bool value = true;
};
template <class Needle, class A, class... Haystack>
class is_one_of<Needle, A, Haystack...> {
public:
static constexpr const bool value = is_one_of<Needle, Haystack...>::value;
};
template <class Needle>
class is_one_of<Needle> {
public:
static constexpr const bool value = false;
};
template <class... Types>
class max_size_of;
template <class A>
class max_size_of<A> {
public:
static constexpr const size_t value = sizeof(A);
};
template <class A, class... B>
class max_size_of<A, B...> {
public:
static constexpr const size_t value = sizeof(A) > max_size_of<B...>::value
? sizeof(A)
: max_size_of<B...>::value;
};
template <class... Types>
class max_align_of;
template <class A>
class max_align_of<A> {
public:
static constexpr const size_t value = alignof(A);
};
template <class A, class... B>
class max_align_of<A, B...> {
public:
static constexpr const size_t value = alignof(A) > max_align_of<B...>::value
? alignof(A)
: max_align_of<B...>::value;
};
template <class BaseType, class... DerivedTypes>
class PolymorphicManualConstructor {
public:
// No constructor or destructor because one of the most useful uses of
// this class is as part of a union, and members of a union could not have
// constructors or destructors till C++11. And, anyway, the whole point of
// this class is to bypass constructor and destructor.
BaseType* get() { return reinterpret_cast<BaseType*>(&space_); }
const BaseType* get() const {
return reinterpret_cast<const BaseType*>(&space_);
}
BaseType* operator->() { return get(); }
const BaseType* operator->() const { return get(); }
BaseType& operator*() { return *get(); }
const BaseType& operator*() const { return *get(); }
template <class DerivedType>
void Init() {
FinishInit(new (&space_) DerivedType);
}
// Init() constructs the Type instance using the given arguments
// (which are forwarded to Type's constructor).
//
// Note that Init() with no arguments performs default-initialization,
// not zero-initialization (i.e it behaves the same as "new Type;", not
// "new Type();"), so it will leave non-class types uninitialized.
template <class DerivedType, typename... Ts>
void Init(Ts&&... args) {
FinishInit(new (&space_) DerivedType(std::forward<Ts>(args)...));
}
// Init() that is equivalent to copy and move construction.
// Enables usage like this:
// ManualConstructor<std::vector<int>> v;
// v.Init({1, 2, 3});
template <class DerivedType>
void Init(const DerivedType& x) {
FinishInit(new (&space_) DerivedType(x));
}
template <class DerivedType>
void Init(DerivedType&& x) {
FinishInit(new (&space_) DerivedType(std::move(x)));
}
void Destroy() { get()->~BaseType(); }
private:
template <class DerivedType>
void FinishInit(DerivedType* p) {
static_assert(is_one_of<DerivedType, DerivedTypes...>::value,
"DerivedType must be one of the predeclared DerivedTypes");
ASSERT(reinterpret_cast<BaseType*>(static_cast<DerivedType*>(p)) == p);
}
typename std::aligned_storage<
grpc_core::max_size_of<DerivedTypes...>::value,
grpc_core::max_align_of<DerivedTypes...>::value>::type space_;
};
template <typename Type>
class ManualConstructor {
public:

Loading…
Cancel
Save