• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2023 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF FuncObject KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <exception>
18 #include <typeinfo>
19 #include <type_traits>
20 #include <typeindex>
21 #include <utility>
22 #include "utils/log_adapter.h"
23 
24 namespace mindspore::runtime {
25 class FuncObject {
26  public:
27   FuncObject() = default;
28   template <typename T>
FuncObject(const T & value)29   explicit FuncObject(const T &value)
30       : object_(new Object<typename std::remove_cv_t<typename std::decay_t<const T>>>(value)) {}
FuncObject(const FuncObject & other)31   FuncObject(const FuncObject &other) : object_(other.object_ ? other.object_->clone() : nullptr) {}
FuncObject(FuncObject && other)32   FuncObject(FuncObject &&other) : object_(other.object_) { other.object_ = nullptr; }
33   template <typename T>
FuncObject(T && value)34   FuncObject(T &&value) : object_(new Object<typename std::decay_t<T>>(static_cast<T &&>(value))) {}
35 
~FuncObject()36   ~FuncObject() {
37     delete object_;
38     object_ = nullptr;
39   }
40 
41  public:
swap(FuncObject & rhs)42   FuncObject &swap(FuncObject &rhs) {
43     std::swap(object_, rhs.object_);
44     return *this;
45   }
46 
47   template <typename T>
48   FuncObject &operator=(T &&rhs) {
49     // cppcheck-suppress *
50     (void)FuncObject(static_cast<T &&>(rhs)).swap(*this);
51     return *this;
52   }
53 
type()54   const std::type_info &type() const { return object_ ? object_->type() : typeid(void); }
55 
56   template <typename T>
57   friend T *Cast(FuncObject *func_object);
58 
59  private:
60   class Handle {
61    public:
~Handle()62     virtual ~Handle() {}
63     virtual const std::type_info &type() const = 0;
64     virtual Handle *clone() const = 0;
65   };
66 
67   template <typename T>
68   class Object : public Handle {
69    public:
70     Object &operator=(const Object &) = delete;
71 
Object(const T & value)72     explicit Object(const T &value) : handle_(value) {}
Object(T && value)73     explicit Object(T &&value) : handle_(static_cast<T &&>(value)) {}
type()74     const std::type_info &type() const override { return typeid(T); }
clone()75     Handle *clone() const override { return new Object(handle_); }
76     T handle_;
77   };
78 
79   Handle *object_{nullptr};
80 };
81 
82 template <bool, typename T1, typename T2>
83 struct If {
84   using type = T2;
85 };
86 
87 template <typename T1, typename T2>
88 struct If<true, T1, T2> {
89   using type = T1;
90 };
91 
92 template <bool b, typename T1, typename T2>
93 using If_t = typename If<b, T1, T2>::type;
94 
95 template <typename T>
96 T *Cast(FuncObject *func_object) {
97   return func_object && func_object->type() == typeid(T)
98            ? &(static_cast<FuncObject::Object<typename std::remove_cv_t<T>> *>(func_object->object_)->handle_)
99            : nullptr;
100 }
101 
102 template <typename T>
103 // cppcheck-suppress *
104 T FuncCast(FuncObject &func_object) {
105   using object_type = typename std::remove_reference_t<T>;
106   object_type *result = Cast<object_type>(&func_object);
107   if (!result) {
108     MS_LOG(EXCEPTION) << "Can not convert from " << func_object.type().name() << " to " << typeid(T).name();
109   }
110   using ref_type = If_t<std::is_reference_v<T>, T, std::add_lvalue_reference_t<T>>;
111   return static_cast<ref_type>(*result);
112 }
113 
114 }  // namespace mindspore::runtime
115