Commit 4b72479b authored by Mathieu Stefani's avatar Mathieu Stefani

Async: Added a TypeId helper to throw an exception when types are incompatible

parent 06b76563
......@@ -12,6 +12,7 @@
#include <memory>
#include <atomic>
#include "optional.h"
#include "typeid.h"
namespace Async {
......@@ -119,13 +120,15 @@ namespace Async {
};
struct Core {
Core(State state)
Core(State state, TypeId id)
: state(state)
, id(id)
{ }
State state;
std::exception_ptr exc;
std::vector<std::shared_ptr<Request>> requests;
TypeId id;
virtual void* memory() = 0;
......@@ -136,16 +139,21 @@ namespace Async {
if (isVoid())
throw Error("Can not construct a void core");
if (id != TypeId::of<T>()) {
throw Error("Bad value type");
}
void *mem = memory();
new (mem) T(std::forward<Args>(args)...);
state = State::Fulfilled;
}
};
template<typename T>
struct CoreT : public Core {
CoreT()
: Core(State::Pending)
: Core(State::Pending, TypeId::of<T>())
{ }
template<class Other>
......@@ -173,7 +181,7 @@ namespace Async {
template<>
struct CoreT<void> : public Core {
CoreT()
: Core(State::Pending)
: Core(State::Pending, TypeId::of<void>())
{ }
bool isVoid() const { return true; }
......
/* typeid.h
Mathieu Stefani, 30 novembre 2015
Copyright (c) 2015 Datacratic. All rights reserved.
This header provides a TypeId type that holds an unique identifier
for a given type. Basically equivalent to std::type_info except that
it does not rely on RTTI. The identifier is determined at compile-time.
Inspired by Rust's std::TypeId
*/
#pragma once
class TypeId {
public:
template<typename T>
static TypeId of() {
static char const id_ {};
return TypeId(&id_);
}
operator size_t() const {
return reinterpret_cast<size_t>(id_);
}
private:
typedef void const* Id;
TypeId(Id id)
: id_(id)
{ }
Id id_;
};
#define APPLY_OP(lhs, rhs, op) \
static_cast<size_t>(lhs) op static_cast<size_t>(rhs);
inline bool operator==(const TypeId& lhs, const TypeId& rhs) {
return APPLY_OP(lhs, rhs, ==);
}
inline bool operator !=(const TypeId& lhs, const TypeId& rhs) {
return APPLY_OP(lhs, rhs, !=);
}
inline bool operator<(const TypeId& lhs, const TypeId& rhs) {
return APPLY_OP(lhs, rhs, <);
}
#undef APPLY_OP
namespace std {
template<> struct hash<TypeId> {
size_t operator()(const TypeId& id) {
return static_cast<size_t>(id);
}
};
}
......@@ -9,3 +9,7 @@ add_test( headers_test run_headers_test )
add_executable( run_async_test async_test.cc )
target_link_libraries(run_async_test gtest gtest_main net)
add_test( async_test run_async_test )
add_executable( run_typeid_test typeid_test.cc )
target_link_libraries(run_typeid_test gtest gtest_main)
add_test( typeid_test run_typeid_test )
......@@ -58,6 +58,13 @@ TEST(async_test, basic_test) {
ASSERT_TRUE(p6.isRejected());
}
TEST(async_test, error_test) {
Async::Promise<int> p1(
[](Async::Resolver& resolve, Async::Rejection& reject) {
ASSERT_THROW(resolve(10.5), Async::Error);
});
}
TEST(async_test, void_promise) {
Async::Promise<void> p1(
[](Async::Resolver& resolve, Async::Rejection& reject) {
......
#include "gtest/gtest.h"
#include "typeid.h"
TEST(type_id_test, basic_test) {
ASSERT_EQ(TypeId::of<int>(), TypeId::of<int>());
ASSERT_NE(TypeId::of<int>(), TypeId::of<int *>());
ASSERT_NE(TypeId::of<int>(), TypeId::of<int &>());
ASSERT_NE(TypeId::of<int &>(), TypeId::of<int &&>());
ASSERT_EQ(TypeId::of<int &>(), TypeId::of<int &>());
ASSERT_NE(TypeId::of<int &>(), TypeId::of<const int&>());
ASSERT_NE(TypeId::of<int * const>(), TypeId::of<int const*>());
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment