From: 박종현/동작제어Lab(SR)/Staff Engineer/삼성전자 Date: Fri, 14 Dec 2018 05:41:47 +0000 (+0900) Subject: [coco] Introduce object casting helpers (#2673) X-Git-Tag: nncc_backup~1071 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8936091958d3b8f6bf0a2eaf78904a13f9ef1356;p=platform%2Fcore%2Fml%2Fnnfw.git [coco] Introduce object casting helpers (#2673) This commit introduces the following object casting helpers: - isa - cast - safe_cast Signed-off-by: Jonghyun Park --- diff --git a/contrib/coco/core/include/coco/IR/Object.h b/contrib/coco/core/include/coco/IR/Object.h index 3fa6f12..29a0535 100644 --- a/contrib/coco/core/include/coco/IR/Object.h +++ b/contrib/coco/core/include/coco/IR/Object.h @@ -101,6 +101,36 @@ private: UseSet _uses; }; +/** + * @brief Check whether a given object is of type T + * + * The example below shows how to use this "isa" helper: + * auto obj = new FeatureObject{}; + * + * if (isa()) + * { + * std::cout << "FeatureObject" << std::endl; + * } + */ +template bool isa(const Object *); + +/** + * @brief Cast a generic object as a specific one + * + * "cast(o)" accepts only a valid object pointer "o" that "isa(o)" holds + * - Then, "cast(o)" always returns a valid object pointer. + */ +template T *cast(Object *); + +/** + * @brief Cast a generic object as a specific one + * + * Unlike "cast", "safe_cast" accepts any object pointer + * - "safe_cast(nullptr)" returns "nullptr" + * - "safe_cast(o)" returns "nullptr" if "isa(o)" does not hold + */ +template T *safe_cast(Object *); + // @brief Return the producer of a given object if it exists Object::Producer *producer(const Object *); diff --git a/contrib/coco/core/src/IR/FeatureObject.test.cpp b/contrib/coco/core/src/IR/FeatureObject.test.cpp index 7cd875a..f647626 100644 --- a/contrib/coco/core/src/IR/FeatureObject.test.cpp +++ b/contrib/coco/core/src/IR/FeatureObject.test.cpp @@ -32,6 +32,13 @@ namespace class FeatureObjectTest : public ::testing::Test { protected: + coco::FeatureObject *allocate() + { + auto o = new coco::FeatureObject{}; + _allocated.emplace_back(o); + return o; + } + // TODO Deprecate this method coco::FeatureObject *allocate(const coco::FeatureShape &shape) { @@ -107,3 +114,12 @@ TEST_F(FeatureObjectTest, asFeature) ASSERT_NE(mutable_object->asFeature(), nullptr); ASSERT_EQ(mutable_object->asFeature(), immutable_object->asFeature()); } + +TEST_F(FeatureObjectTest, casting_helpers) +{ + auto obj = allocate(); + + ASSERT_TRUE(coco::isa(obj)); + ASSERT_EQ(coco::cast(obj), obj); + ASSERT_EQ(coco::safe_cast(obj), obj); +} diff --git a/contrib/coco/core/src/IR/KernelObject.test.cpp b/contrib/coco/core/src/IR/KernelObject.test.cpp index f0dff27..64f4d54 100644 --- a/contrib/coco/core/src/IR/KernelObject.test.cpp +++ b/contrib/coco/core/src/IR/KernelObject.test.cpp @@ -31,6 +31,13 @@ namespace class KernelObjectTest : public ::testing::Test { protected: + coco::KernelObject *allocate() + { + auto o = new coco::KernelObject{}; + _allocated.emplace_back(o); + return o; + } + coco::KernelObject *allocate(const kernel::Shape &shape) { auto o = new coco::KernelObject{shape}; @@ -69,6 +76,15 @@ TEST_F(KernelObjectTest, asKernel) ASSERT_EQ(mutable_object->asKernel(), immutable_object->asKernel()); } +TEST_F(KernelObjectTest, casting_helpers) +{ + auto obj = allocate(); + + ASSERT_TRUE(coco::isa(obj)); + ASSERT_EQ(coco::cast(obj), obj); + ASSERT_EQ(coco::safe_cast(obj), obj); +} + // TODO Rewrite this test as a test for GenericKernelLayout #if 0 TEST_F(KernelObjectTest, at) diff --git a/contrib/coco/core/src/IR/Object.cpp b/contrib/coco/core/src/IR/Object.cpp index 08ae90c..6a51a61 100644 --- a/contrib/coco/core/src/IR/Object.cpp +++ b/contrib/coco/core/src/IR/Object.cpp @@ -76,4 +76,41 @@ Object::ConsumerSet consumers(const Object *obj) return res; } + +/** + * Casting Helpers + * + * TODO Use Macro to reduce code duplication + */ +template <> bool isa(const Object *o) { return o->asFeature() != nullptr; } +template <> bool isa(const Object *o) { return o->asKernel() != nullptr; } + +template <> FeatureObject *cast(Object *o) +{ + assert(o != nullptr); + auto res = o->asFeature(); + assert(res != nullptr); + return res; +} + +template <> KernelObject *cast(Object *o) +{ + assert(o != nullptr); + auto res = o->asKernel(); + assert(res != nullptr); + return res; +} + +template <> FeatureObject *safe_cast(Object *o) +{ + // NOTE o may be nullptr + return (o == nullptr) ? nullptr : o->asFeature(); +} + +template <> KernelObject *safe_cast(Object *o) +{ + // NOTE o may be nullptr + return (o == nullptr) ? nullptr : o->asKernel(); +} + } // namespace coco diff --git a/contrib/coco/core/src/IR/Object.test.cpp b/contrib/coco/core/src/IR/Object.test.cpp index 0341508..dd3466c 100644 --- a/contrib/coco/core/src/IR/Object.test.cpp +++ b/contrib/coco/core/src/IR/Object.test.cpp @@ -106,3 +106,9 @@ TEST_F(ObjectTest, destructor) ASSERT_EQ(deps.size(), 0); } } + +TEST_F(ObjectTest, safe_cast) +{ + ASSERT_EQ(coco::safe_cast(nullptr), nullptr); + ASSERT_EQ(coco::safe_cast(nullptr), nullptr); +}