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_REF_FIELD_H 17 #define COMMON_INTERFACES_OBJECTS_REF_FIELD_H 18 19 #include <atomic> 20 #include <functional> 21 #include "objects/base_state_word.h" 22 23 namespace common { 24 class BaseObject; 25 26 template <bool isAtomic = false> 27 class RefField { 28 public: 29 static constexpr uint64_t TAG_WEAK = 0x01ULL; 30 static constexpr MAddress REF_UNDEFINED = 0x02ULL; 31 // size in bytes GetSize()32 static constexpr size_t GetSize() 33 { 34 return sizeof(fieldVal); 35 } 36 37 BaseObject *GetTargetObject(std::memory_order order = std::memory_order_relaxed) const 38 { 39 if (isAtomic) { 40 MAddress value = __atomic_load_n(&fieldVal, order); 41 return reinterpret_cast<BaseObject *>(RefField<>(value).GetAddress() & (~TAG_WEAK)); 42 } else { 43 return reinterpret_cast<BaseObject *>(this->GetAddress() & (~TAG_WEAK)); 44 } 45 } 46 47 MAddress GetFieldValue(std::memory_order order = std::memory_order_relaxed) const 48 { 49 if (isAtomic) { 50 MAddress value = __atomic_load_n(&fieldVal, order); 51 return value; 52 } else { 53 return fieldVal; 54 } 55 } 56 57 void SetTargetObject(const BaseObject *obj, std::memory_order order = std::memory_order_relaxed) 58 { 59 RefField<> newField(obj); 60 MAddress newVal = newField.GetFieldValue(); 61 RefFieldValue oldVal = fieldVal; 62 (void)oldVal; 63 64 if (isAtomic) { 65 __atomic_store_n(&fieldVal, static_cast<RefFieldValue>(newVal), order); 66 } else { 67 fieldVal = static_cast<RefFieldValue>(newVal); 68 } 69 } 70 71 void SetFieldValue(MAddress newVal, std::memory_order order = std::memory_order_relaxed) 72 { 73 RefFieldValue oldVal = fieldVal; 74 (void)oldVal; 75 76 if (isAtomic) { 77 __atomic_store_n(&fieldVal, static_cast<RefFieldValue>(newVal), order); 78 } else { 79 fieldVal = static_cast<RefFieldValue>(newVal); 80 } 81 } 82 ClearRef(MAddress expectedValue)83 bool ClearRef(MAddress expectedValue) 84 { 85 return CompareExchange(expectedValue, REF_UNDEFINED); 86 } 87 88 bool CompareExchange(MAddress expectedValue, MAddress newValue, 89 std::memory_order succOrder = std::memory_order_relaxed, 90 std::memory_order failOrder = std::memory_order_relaxed) 91 { 92 return __atomic_compare_exchange(&fieldVal, &expectedValue, &newValue, false, succOrder, failOrder); 93 } 94 95 bool CompareExchange(const BaseObject *expectedObj, const BaseObject *newObj, 96 std::memory_order succOrder = std::memory_order_relaxed, 97 std::memory_order failOrder = std::memory_order_relaxed) 98 { 99 return CompareExchange(reinterpret_cast<MAddress>(expectedObj), reinterpret_cast<MAddress>(newObj), succOrder, 100 failOrder); 101 } 102 103 MAddress Exchange(MAddress newRef, std::memory_order order = std::memory_order_relaxed) 104 { 105 MAddress ret = 0; 106 __atomic_exchange(&fieldVal, &newRef, &ret, order); 107 return static_cast<MAddress>(ret); 108 } 109 110 MAddress Exchange(const BaseObject *obj, std::memory_order order = std::memory_order_relaxed) 111 { 112 return Exchange(reinterpret_cast<MAddress>(obj), order); 113 } 114 GetAddress()115 MAddress GetAddress() const 116 { 117 return address; 118 } 119 IsWeak()120 bool IsWeak() const 121 { 122 return (address & TAG_WEAK); 123 } 124 125 // bool IsTagged() const { return isTagged == 1; } IsTagged()126 bool IsTagged() const 127 { 128 return false; 129 } GetTagID()130 uint16_t GetTagID() const 131 { 132 return tagID; 133 } 134 135 ~RefField() = default; RefField(MAddress val)136 explicit RefField(MAddress val) : fieldVal(val) {} RefField(const RefField & ref)137 RefField(const RefField &ref) : fieldVal(ref.fieldVal) {} RefField(const BaseObject * obj)138 explicit RefField(const BaseObject *obj) : fieldVal(0) 139 { 140 address = reinterpret_cast<MAddress>(obj); 141 } RefField(const BaseObject * obj,bool forWeak)142 RefField(const BaseObject* obj, bool forWeak) : fieldVal(0) 143 { 144 MAddress tag = forWeak ? TAG_WEAK : 0; 145 address = reinterpret_cast<MAddress>(obj) | tag; 146 } RefField(const BaseObject * obj,uint16_t tagged,uint16_t tagid)147 RefField(const BaseObject *obj, uint16_t tagged, uint16_t tagid) 148 : address(reinterpret_cast<MAddress>(obj)), isTagged(tagged), tagID(tagid), padding(0) 149 { 150 } 151 RefField(RefField && ref)152 RefField(RefField &&ref) : fieldVal(ref.fieldVal) {} 153 RefField() = delete; 154 RefField &operator=(const RefField &) = delete; 155 RefField &operator=(const RefField &&) = delete; 156 157 private: 158 using RefFieldValue = MAddress; 159 160 union { 161 struct { 162 MAddress address : 48; 163 MAddress isTagged : 1; 164 MAddress tagID : 1; 165 MAddress padding : 14; 166 }; 167 RefFieldValue fieldVal; 168 }; 169 }; 170 } // namespace common 171 #endif // COMMON_INTERFACES_OBJECTS_REF_FIELD_H 172