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 @@ ...@@ -12,6 +12,7 @@
#include <memory> #include <memory>
#include <atomic> #include <atomic>
#include "optional.h" #include "optional.h"
#include "typeid.h"
namespace Async { namespace Async {
...@@ -119,13 +120,15 @@ namespace Async { ...@@ -119,13 +120,15 @@ namespace Async {
}; };
struct Core { struct Core {
Core(State state) Core(State state, TypeId id)
: state(state) : state(state)
, id(id)
{ } { }
State state; State state;
std::exception_ptr exc; std::exception_ptr exc;
std::vector<std::shared_ptr<Request>> requests; std::vector<std::shared_ptr<Request>> requests;
TypeId id;
virtual void* memory() = 0; virtual void* memory() = 0;
...@@ -136,16 +139,21 @@ namespace Async { ...@@ -136,16 +139,21 @@ namespace Async {
if (isVoid()) if (isVoid())
throw Error("Can not construct a void core"); throw Error("Can not construct a void core");
if (id != TypeId::of<T>()) {
throw Error("Bad value type");
}
void *mem = memory(); void *mem = memory();
new (mem) T(std::forward<Args>(args)...); new (mem) T(std::forward<Args>(args)...);
state = State::Fulfilled; state = State::Fulfilled;
} }
}; };
template<typename T> template<typename T>
struct CoreT : public Core { struct CoreT : public Core {
CoreT() CoreT()
: Core(State::Pending) : Core(State::Pending, TypeId::of<T>())
{ } { }
template<class Other> template<class Other>
...@@ -173,7 +181,7 @@ namespace Async { ...@@ -173,7 +181,7 @@ namespace Async {
template<> template<>
struct CoreT<void> : public Core { struct CoreT<void> : public Core {
CoreT() CoreT()
: Core(State::Pending) : Core(State::Pending, TypeId::of<void>())
{ } { }
bool isVoid() const { return true; } 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 ) ...@@ -9,3 +9,7 @@ add_test( headers_test run_headers_test )
add_executable( run_async_test async_test.cc ) add_executable( run_async_test async_test.cc )
target_link_libraries(run_async_test gtest gtest_main net) target_link_libraries(run_async_test gtest gtest_main net)
add_test( async_test run_async_test ) 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) { ...@@ -58,6 +58,13 @@ TEST(async_test, basic_test) {
ASSERT_TRUE(p6.isRejected()); 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) { TEST(async_test, void_promise) {
Async::Promise<void> p1( Async::Promise<void> p1(
[](Async::Resolver& resolve, Async::Rejection& reject) { [](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