• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef COMMON_INTERFACES_OBJECTS_BASE_STATE_WORD_H
17 #define COMMON_INTERFACES_OBJECTS_BASE_STATE_WORD_H
18 
19 #include <stddef.h>
20 #include <cstdint>
21 
22 namespace common {
23 using StateWordType = uint64_t;
24 using MAddress = uint64_t;
25 class TypeInfo;
26 
27 enum class LanguageType : uint64_t {
28     DYNAMIC = 0,
29     STATIC = 1,
30 };
31 
32 class BaseStateWord {
33 public:
34     static constexpr size_t PADDING_WIDTH = 60;
35     static constexpr size_t FORWARD_WIDTH = 2;
36     static constexpr size_t LANGUAGE_WIDTH = 2;
37 
38     BaseStateWord() = default;
BaseStateWord(MAddress header)39     BaseStateWord(MAddress header) : header_(header) {};
40 
41     enum class ForwardState : uint64_t {
42         NORMAL,
43         FORWARDING,
44         FORWARDED,
45         TO_VERSION
46     };
47 
SetForwarding()48     inline void SetForwarding()
49     {
50         state_.forwardState_ = ForwardState::FORWARDING;
51     }
52 
IsForwarding()53     inline bool IsForwarding() const
54     {
55         return state_.forwardState_ == ForwardState::FORWARDING;
56     }
57 
IsToVersion()58     inline bool IsToVersion() const
59     {
60         return state_.forwardState_ == ForwardState::TO_VERSION;
61     }
62 
TryLockBaseStateWord(const BaseStateWord current)63     bool TryLockBaseStateWord(const BaseStateWord current)
64     {
65         if (current.IsForwarding()) {
66             return false;
67         }
68         BaseStateWord newState = BaseStateWord(current.GetHeader());
69         newState.SetForwardState(ForwardState::FORWARDING);
70         return CompareExchangeHeader(current.GetHeader(), newState.GetHeader());
71     }
72 
UnlockStateWord(const ForwardState forwardState)73     void UnlockStateWord(const ForwardState forwardState)
74     {
75         do {
76             BaseStateWord current = AtomicGetBaseStateWord();
77             BaseStateWord newState = BaseStateWord(current.GetHeader());
78             newState.SetForwardState(forwardState);
79             if (CompareExchangeHeader(current.GetHeader(), newState.GetHeader())) {
80                 return;
81             }
82         } while (true);
83     }
84 
SetForwardState(ForwardState state)85     void SetForwardState(ForwardState state)
86     {
87         state_.forwardState_ = state;
88     }
89 
GetForwardState()90     ForwardState GetForwardState() const
91     {
92         return state_.forwardState_;
93     }
94 
GetBaseClassAddress()95     common::StateWordType GetBaseClassAddress() const
96     {
97         return state_.padding_;
98     }
99 
SetFullBaseClassAddress(common::StateWordType address)100     void SetFullBaseClassAddress(common::StateWordType address)
101     {
102         state_.padding_ = address;
103     }
104 private:
105     // Little endian
106     struct State {
107         common::StateWordType padding_     : PADDING_WIDTH;
108         LanguageType language_     : LANGUAGE_WIDTH;
109         ForwardState forwardState_ : FORWARD_WIDTH;
110     };
111 
112     union {
113         State state_;
114         MAddress header_;
115     };
116 
AtomicGetBaseStateWord()117     BaseStateWord AtomicGetBaseStateWord() const
118     {
119         return BaseStateWord(AtomicGetHeader());
120     }
121 
AtomicGetHeader()122     MAddress AtomicGetHeader() const
123     {
124         return __atomic_load_n(&header_, __ATOMIC_ACQUIRE);
125     }
126 
GetHeader()127     MAddress GetHeader() const { return header_; }
128 
CompareExchangeHeader(MAddress expected,MAddress newState)129     bool CompareExchangeHeader(MAddress expected, MAddress newState)
130     {
131 #if defined(__x86_64__)
132         bool success =
133             __atomic_compare_exchange_n(&header_, &expected, newState, true, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
134 #else
135         // due to "Spurious Failure" of compare_exchange_weak, compare_exchange_strong is chosen.
136         bool success =
137             __atomic_compare_exchange_n(&header_, &expected, newState, false, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
138 #endif
139         return success;
140     }
141 
SetForwarded()142     inline void SetForwarded()
143     {
144         state_.forwardState_ = ForwardState::FORWARDED;
145     }
146 
IsForwarded()147     inline bool IsForwarded() const
148     {
149         return state_.forwardState_ == ForwardState::FORWARDED;
150     }
151 
SetLanguageType(LanguageType language)152     inline void SetLanguageType(LanguageType language)
153     {
154         state_.language_ = language;
155     }
156 
IsStatic()157     inline bool IsStatic() const
158     {
159         return state_.language_ == LanguageType::STATIC;
160     }
161 
IsDynamic()162     inline bool IsDynamic() const
163     {
164         return state_.language_ == LanguageType::DYNAMIC;
165     }
166 
167     friend class BaseObject;
168 };
169 static_assert(sizeof(BaseStateWord) == sizeof(uint64_t), "Excepts 8 bytes");
170 }  // namespace common
171 #endif  // COMMON_INTERFACES_OBJECTS_BASE_STATE_WORD_H
172