/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef HIPERF_HASHLIST_H #define HIPERF_HASHLIST_H #include namespace OHOS { namespace Developtools { namespace HiPerf { class Link { public: Link() = default; ~Link() = default; Link(const Link &link) : prev_ {link.prev_}, next_ {link.next_} {} Link(Link &&link) : prev_ {link.prev_}, next_ {link.next_} { link.prev_ = nullptr; link.next_ = nullptr; } Link &operator=(const Link &link) { prev_ = link.prev_; next_ = link.next_; return *this; } Link &operator=(Link &&link) { prev_ = link.prev_; link.prev_ = nullptr; next_ = link.next_; link.next_ = nullptr; return *this; } Link *prev_ {nullptr}; Link *next_ {nullptr}; }; template class LinkNode { public: Link link_ {}; Key key_ {}; Val val_ {}; explicit LinkNode() = default; ~LinkNode() = default; explicit LinkNode(const Key &key); explicit LinkNode(const Key &key, const Val &val); explicit LinkNode(const Key &key, Val &&val); LinkNode(const LinkNode &node); LinkNode(LinkNode &&node); LinkNode &operator=(const LinkNode &node); LinkNode &operator=(LinkNode &&node); static LinkNode *GetLinkNode(Val *pval); static LinkNode *GetLinkNode(Link *plink); }; template class HashList { public: class Iterator { public: Iterator() = default; ~Iterator() = default; explicit Iterator(LinkNode *pnode, HashList *phashList); explicit Iterator(const LinkNode *pnode, const HashList *phashList); Iterator(const Iterator &itr); Iterator(Iterator &&itr); Iterator &operator=(const Iterator &itr); Iterator &operator=(Iterator &&itr); Iterator &operator++() noexcept; Iterator operator++(int) noexcept; Iterator &operator--() noexcept; Iterator operator--(int) noexcept; bool operator<(const Iterator &itr) const noexcept; bool operator==(const Iterator &itr) const noexcept; Val &operator*(); const Val &operator*() const; Val *operator->(); const Val *operator->() const; void swap(HashList::Iterator &other); LinkNode *GetNode() const { return pnode_; } private: bool IsDangled() const noexcept { return phashList_ == nullptr; } LinkNode *pnode_ {nullptr}; HashList *phashList_ {nullptr}; }; class ReverseIterator { public: ReverseIterator() = default; ~ReverseIterator() = default; explicit ReverseIterator(LinkNode *pnode, HashList *phashList); explicit ReverseIterator(const LinkNode *pnode, const HashList *phashList); ReverseIterator(const ReverseIterator &itr); ReverseIterator(ReverseIterator &&itr); ReverseIterator &operator=(const ReverseIterator &itr); ReverseIterator &operator=(ReverseIterator &&itr); ReverseIterator &operator++() noexcept; ReverseIterator operator++(int) noexcept; ReverseIterator &operator--() noexcept; ReverseIterator operator--(int) noexcept; bool operator<(const ReverseIterator &itr) const noexcept; bool operator==(const ReverseIterator &itr) const noexcept; Val &operator*(); const Val &operator*() const; Val *operator->(); const Val *operator->() const; void swap(HashList::ReverseIterator &other); LinkNode *GetNode() { return pnode_; } private: bool IsDangled() const noexcept { return phashList_ == nullptr; } LinkNode *pnode_ {nullptr}; HashList *phashList_ {nullptr}; }; public: explicit HashList(const std::size_t numItem = 0); ~HashList(); HashList(const HashList &source) = delete; HashList &operator=(const HashList &source) = delete; HashList(HashList &&source); HashList &operator=(HashList &&source); // capacity inline std::size_t size() const { return valueTab_.size(); } inline bool empty() const { return (dataHead_.next_ == &dataHead_) and (dataHead_.prev_ == &dataHead_); } inline std::size_t capacity() const { return numItem_; } inline bool IsFull() const { return freeHead_.next_ == &freeHead_; } inline std::size_t count(const Key &key) const { return valueTab_.count(key); } int reserve(const std::size_t numItem); // iterators Iterator begin(); const Iterator cbegin() const; Iterator end(); const Iterator cend() const; ReverseIterator rbegin(); const ReverseIterator crbegin() const; ReverseIterator rend(); const ReverseIterator crend() const; // element access Val &front(); const Val &front() const; Val &back(bool prepend = false); Val &operator[](const Key &key); // lookup Iterator find(const Key &key); // modifiers void push_front(const Key &key, const Val &val); void push_front(const Key &key, Val &&val); void push_back(const Key &key, const Val &val); void push_back(const Key &key, Val &&val); void pop_front(); void pop_back(); Iterator erase(const Key &key); Iterator erase(const Iterator pos); Iterator erase(const Iterator first, const Iterator last); private: void MoveToHead(LinkNode *&pnode); void MoveToTail(LinkNode *&pnode); bool MoveNode(const Iterator &pos, LinkNode *&pnode); LinkNode *AllocateNode(const Key &key); LinkNode *AllocateNode(const Key &key, const Val &val); LinkNode *AllocateNode(const Key &key, Val &&val); void ReclaimNode(LinkNode *&pnode); std::size_t numItem_ {0}; LinkNode *pData_ {nullptr}; Link dataHead_ {}; Link freeHead_ {}; std::unordered_map *> valueTab_ {}; }; // implementation of template class LinkNode template LinkNode::LinkNode(const Key &key) : key_ {key} {} template LinkNode::LinkNode(const Key &key, const Val &val) : key_ {key}, val_ {val} {} template LinkNode::LinkNode(const Key &key, Val &&val) : key_ {key}, val_ {std::move(val)} {} template LinkNode::LinkNode(const LinkNode& node) :link_ {node.link_}, key_ {node.key_}, val_ {node.val_} {} template LinkNode::LinkNode(LinkNode&& node) :link_ {std::move(node.link_)}, key_ {std::move(node.key_)}, val_ {std::move(node.val_)} {} template auto LinkNode::operator=(const LinkNode& node) -> LinkNode& { link_ = node.link_; key_ = node.key_; val_ = node.val_; } template auto LinkNode::operator=(LinkNode&& node) -> LinkNode& { link_ = std::move(node.link_); key_ = std::move(node.key_); val_ = std::move(node.val_); } template auto LinkNode::GetLinkNode(Val *pval) -> LinkNode* { if (pval) { LinkNode *pnode {nullptr}; Val* offset = &pnode->val_; auto nodeAddr = reinterpret_cast(pval) - reinterpret_cast(offset); return reinterpret_cast*>(nodeAddr); } return nullptr; } template auto LinkNode::GetLinkNode(Link *plink) -> LinkNode* { if (plink) { LinkNode *pnode {nullptr}; Link* offset = &pnode->link_; auto nodeAddr = reinterpret_cast(plink) - reinterpret_cast(offset); return reinterpret_cast*>(nodeAddr); } return nullptr; } // end of LinkNode // implementation of template class Iterator template HashList::Iterator::Iterator(LinkNode *pnode, HashList *phashList) : pnode_ {pnode}, phashList_ {phashList} { if (phashList_ == nullptr) { pnode_ = nullptr; } } template HashList::Iterator::Iterator(const LinkNode *pnode, const HashList *phashList) : pnode_ {const_cast*>(pnode)}, phashList_ {const_cast(phashList)} { if (phashList_ == nullptr) { pnode_ = nullptr; } } template HashList::Iterator::Iterator(const Iterator& itr) : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} {} template HashList::Iterator::Iterator(Iterator&& itr) : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} { itr.pnode_ = nullptr; itr.phashList_ = nullptr; } template auto HashList::Iterator::operator=(const Iterator& itr) -> HashList::Iterator& { Iterator temp {itr}; swap(temp); return *this; } template auto HashList::Iterator::operator=(Iterator&& itr) -> HashList::Iterator& { Iterator temp {std::move(itr)}; swap(temp); return *this; } template auto HashList::Iterator::operator++() noexcept -> HashList::Iterator & { if (pnode_ == nullptr or phashList_ == nullptr) { phashList_ = nullptr; return *this; } Link* plink = pnode_->link_.next_; if (plink == &phashList_->dataHead_) { pnode_ = nullptr; return *this; } auto pnode = LinkNode::GetLinkNode(plink); pnode_ = pnode; return *this; } template auto HashList::Iterator::operator++(int) noexcept -> HashList::Iterator { Iterator res {*this}; if (pnode_ == nullptr or phashList_ == nullptr) { phashList_ = nullptr; return res; } Link* plink = pnode_->link_.next_; if (plink == &phashList_->dataHead_) { pnode_ = nullptr; return res; } auto pnode = LinkNode::GetLinkNode(plink); pnode_ = pnode; return res; } template auto HashList::Iterator::operator--() noexcept -> HashList::Iterator & { if (phashList_ == nullptr) { return *this; } Link* plink {nullptr}; if (pnode_ == nullptr) { plink = phashList_->dataHead_.prev_; } else { plink = pnode_->link_.prev_; } if (plink == &phashList_->dataHead_) { pnode_ = nullptr; phashList_ = nullptr; return *this; } pnode_ = LinkNode::GetLinkNode(plink); return *this; } template auto HashList::Iterator::operator--(int) noexcept -> HashList::Iterator { Iterator res {*this}; if (phashList_ == nullptr) { return res; } Link* plink {nullptr}; if (pnode_ == nullptr) { plink = phashList_->dataHead_.prev_; } else { plink = pnode_->link_.prev_; } if (plink == &phashList_->dataHead_) { pnode_ = nullptr; phashList_ = nullptr; return res; } pnode_ = LinkNode::GetLinkNode(plink); return res; } template bool HashList::Iterator::operator<(const HashList::Iterator &itr) const noexcept { if (IsDangled() or itr.IsDangled()) { return false; } if (phashList_ != itr.phashList_) { return false; } Iterator tempItr {*this}; if (tempItr == itr) { return false; } while (!tempItr.IsDangled()) { tempItr++; if (tempItr == itr) { return true; } } return false; } template bool HashList::Iterator::operator==(const HashList::Iterator &itr) const noexcept { if (IsDangled() or itr.IsDangled()) { return false; } if (phashList_ != itr.phashList_) { return false; } return pnode_ == itr.pnode_; } template Val& HashList::Iterator::operator*() { return pnode_->val_; } template const Val& HashList::Iterator::operator*() const { return pnode_->val_; } template Val* HashList::Iterator::operator->() { return &pnode_->val_; } template const Val* HashList::Iterator::operator->() const { return &pnode_->val_; } template void HashList::Iterator::swap(HashList::Iterator& other) { using std::swap; swap(pnode_, other.pnode_); swap(phashList_, other.phashList_); } // end of Iterator // Implementation of ReverseIterator template HashList::ReverseIterator::ReverseIterator(LinkNode *pnode, HashList *phashList) : pnode_ {pnode}, phashList_ {phashList} { if (phashList_ == nullptr) { pnode_ = nullptr; } } template HashList::ReverseIterator::ReverseIterator(const LinkNode *pnode, const HashList *phashList) : pnode_ {const_cast *>(pnode)}, phashList_ {const_cast(phashList)} { if (phashList_ == nullptr) { pnode_ = nullptr; } } template HashList::ReverseIterator::ReverseIterator(const ReverseIterator &itr) : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} {} template HashList::ReverseIterator::ReverseIterator(ReverseIterator &&itr) : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} { itr.pnode_ = nullptr; itr.phashList_ = nullptr; } template auto HashList::ReverseIterator::operator=(const ReverseIterator& itr) -> HashList::ReverseIterator& { ReverseIterator temp {itr}; swap(temp); return *this; } template auto HashList::ReverseIterator::operator=(ReverseIterator&& itr) -> HashList::ReverseIterator& { ReverseIterator temp {std::move(itr)}; swap(temp); return *this; } template auto HashList::ReverseIterator::operator++() noexcept -> HashList::ReverseIterator & { if (pnode_ == nullptr or phashList_ == nullptr) { phashList_ = nullptr; return *this; } Link* plink = &pnode_->link_; plink = plink->prev_; if (plink == &phashList_->dataHead_) { pnode_ = nullptr; return *this; } pnode_ = LinkNode::GetLinkNode(plink); return *this; } template auto HashList::ReverseIterator::operator++(int) noexcept -> HashList::ReverseIterator { ReverseIterator res {*this}; if (pnode_ == nullptr or phashList_ == nullptr) { phashList_ = nullptr; return res; } Link* plink = &pnode_->link_; plink = plink->prev_; if (plink == &phashList_->dataHead_) { pnode_ = nullptr; return res; } pnode_ = LinkNode::GetLinkNode(plink); return res; } template auto HashList::ReverseIterator::operator--() noexcept -> HashList::ReverseIterator & { if (phashList_ == nullptr) { return *this; } Link* plink {nullptr}; if (pnode_ == nullptr) { plink = phashList_->dataHead_.next_; } else { plink = pnode_->link_.next_; } if (plink == &phashList_->dataHead_) { pnode_ = nullptr; phashList_ = nullptr; return *this; } pnode_ = LinkNode::GetLinkNode(plink); return *this; } template auto HashList::ReverseIterator::operator--(int) noexcept -> HashList::ReverseIterator { ReverseIterator res {*this}; if (phashList_ == nullptr) { return res; } Link* plink {nullptr}; if (pnode_ == nullptr) { plink = phashList_->dataHead_.next_; } else { plink = pnode_->link_.next_; } if (plink == &phashList_->dataHead_) { pnode_ = nullptr; phashList_ = nullptr; return res; } pnode_ = LinkNode::GetLinkNode(plink); return res; } template bool HashList::ReverseIterator::operator<( const HashList::ReverseIterator &itr) const noexcept { if (IsDangled() or itr.IsDangled()) { return false; } if (phashList_ != itr.phashList_) { return false; } HashList::ReverseIterator tempItr {*this}; if (tempItr == itr) { return false; } while (!tempItr.IsDangled()) { tempItr++; if (tempItr == itr) { return true; } } return false; } template bool HashList::ReverseIterator::operator==( const HashList::ReverseIterator &itr) const noexcept { if (IsDangled() or itr.IsDangled()) { return false; } if (phashList_ != itr.phashList_) { return false; } return pnode_ == itr.pnode_; } template Val& HashList::ReverseIterator::operator*() { return pnode_->val_; } template const Val& HashList::ReverseIterator::operator*() const { return pnode_->val_; } template Val* HashList::ReverseIterator::operator->() { return &pnode_->val_; } template const Val* HashList::ReverseIterator::operator->() const { return &pnode_->val_; } template void HashList::ReverseIterator::swap(HashList::ReverseIterator& other) { using std::swap; swap(pnode_, other.pnode_); swap(phashList_, other.phashList_); } // end of ReverseIterator // implementation of template class HashList template HashList::HashList(const std::size_t numItem) : numItem_ {numItem} { dataHead_.next_ = &dataHead_; dataHead_.prev_ = &dataHead_; if (numItem_) { valueTab_.reserve(numItem_); pData_ = new(std::nothrow) LinkNode[numItem_]; if (pData_) { freeHead_.next_ = &(pData_[0].link_); std::size_t last {numItem_ - 1}; for (std::size_t index = 0; index < last;) { LinkNode &curNnode = pData_[index]; curNnode.link_.next_ = &(pData_[++index].link_); } pData_[last].link_.next_ = &freeHead_; } else { numItem_ = 0; freeHead_.next_ = &freeHead_; freeHead_.prev_ = &freeHead_; } } } template int HashList::reserve(const std::size_t numItem) { if (numItem_ != 0) { return -1; } if (numItem) { numItem_ = numItem; valueTab_.reserve(numItem_); pData_ = new(std::nothrow) LinkNode[numItem_]; dataHead_.next_ = &dataHead_; dataHead_.prev_ = &dataHead_; if (pData_) { freeHead_.next_ = &(pData_[0].link_); std::size_t last {numItem_ - 1}; for (std::size_t index = 0; index < last;) { LinkNode &curNnode = pData_[index]; curNnode.link_.next_ = &(pData_[++index].link_); } pData_[last].link_.next_ = &freeHead_; } else { numItem_ = 0; freeHead_.next_ = &freeHead_; freeHead_.prev_ = &freeHead_; } } return numItem_; } template HashList::~HashList() { if (pData_) { delete[] pData_; pData_ = nullptr; } valueTab_.clear(); dataHead_.next_ = &dataHead_; dataHead_.prev_ = &dataHead_; freeHead_.next_ = nullptr; freeHead_.prev_ = nullptr; numItem_ = 0; } template HashList::HashList(HashList &&source) : numItem_ {source.numItem_}, pData_ {source.pData_}, dataHead_ {std::move(source.dataHead_)}, freeHead_ {std::move(source.freeHead_)}, valueTab_ {std::move(source.valueTab_)} { source.pData_ = nullptr; } template auto HashList::operator=(HashList &&source) -> HashList& { if (this == &source) { return *this; } if (pData_) { delete[] pData_; pData_ = nullptr; } numItem_ = source.numItem_; pData_ = source.pData_; source.pData_ = nullptr; dataHead_ = std::move(source.dataHead_); freeHead_ = std::move(source.freeHead_); valueTab_ = std::move(source.valueTab_); return *this; } template auto HashList::begin() -> HashList::Iterator { if (empty()) { return end(); } return Iterator(LinkNode::GetLinkNode(dataHead_.next_), this); } template auto HashList::cbegin() const -> const HashList::Iterator { if (empty()) { return cend(); } return Iterator(LinkNode::GetLinkNode(dataHead_.next_), this); } template auto HashList::end() -> HashList::Iterator { return Iterator(nullptr, this); } template auto HashList::cend() const -> const HashList::Iterator { return Iterator(nullptr, this); } template auto HashList::rbegin() -> HashList::ReverseIterator { if (empty()) { return rend(); } return ReverseIterator(LinkNode::GetLinkNode(dataHead_.prev_), this); } template auto HashList::crbegin() const -> const HashList::ReverseIterator { if (empty()) { return crend(); } return ReverseIterator(LinkNode::GetLinkNode(dataHead_.prev_), this); } template auto HashList::rend() -> HashList::ReverseIterator { return ReverseIterator(nullptr, this); } template auto HashList::crend() const -> const HashList::ReverseIterator { return ReverseIterator(nullptr, this); } template Val& HashList::front() { LinkNode *pnode = LinkNode::GetLinkNode(dataHead_.next_); return pnode->val_; } template const Val& HashList::front() const { return front(); } template Val& HashList::back(bool prepend) { auto pnode = LinkNode::GetLinkNode(dataHead_.prev_); if (prepend) { MoveToHead(pnode); } return pnode->val_; } template Val& HashList::operator[](const Key &key) { LinkNode *pnode {nullptr}; if (valueTab_.find(key) == valueTab_.end()) { pnode = AllocateNode(key); valueTab_[key] = pnode; } else { pnode = valueTab_[key]; } if (pnode == nullptr) { static Val val = Val(); return val; } else { MoveToHead(pnode); } return pnode->val_; } template auto HashList::find(const Key &key) -> HashList::Iterator { const auto &itr = valueTab_.find(key); if (itr == valueTab_.end()) { return end(); } return Iterator(itr->second, this); } template void HashList::push_front(const Key& key, const Val& val) { if (valueTab_.find(key) == valueTab_.end()) { LinkNode* pnode = AllocateNode(key, val); MoveToHead(pnode); valueTab_[pnode->key_] = pnode; } else { MoveToHead(valueTab_[key]); this->operator[](key) = val; } } template void HashList::push_front(const Key& key, Val&& val) { if (valueTab_.find(key) == valueTab_.end()) { LinkNode* pnode = AllocateNode(key, std::move(val)); MoveToHead(pnode); valueTab_[pnode->key_] = pnode; } else { MoveToHead(valueTab_[key]); this->operator[](key) = val; } } template void HashList::push_back(const Key& key, const Val& val) { if (valueTab_.find(key) == valueTab_.end()) { LinkNode* pnode = AllocateNode(key, val); MoveToTail(pnode); valueTab_[pnode->key_] = pnode; } else { MoveToTail(valueTab_[key]); this->operator[](key) = val; } } template void HashList::push_back(const Key& key, Val&& val) { if (valueTab_.find(key) == valueTab_.end()) { LinkNode* pnode = AllocateNode(key, std::move(val)); MoveToTail(pnode); valueTab_[pnode->key_] = pnode; } else { MoveToTail(valueTab_[key]); this->operator[](key) = val; } } template void HashList::pop_front() { if (empty()) { return; } LinkNode* pnode = LinkNode::GetLinkNode(dataHead_.next_); valueTab_.erase(pnode->key_); ReclaimNode(pnode); } template void HashList::pop_back() { if (empty()) { return; } LinkNode* pnode = LinkNode::GetLinkNode(dataHead_.prev_); if (pnode != nullptr) { valueTab_.erase(pnode->key_); ReclaimNode(pnode); } } template auto HashList::erase(const Key& key) -> HashList::Iterator { if (valueTab_.find(key) == valueTab_.end()) { return end(); } LinkNode *pnode = valueTab_[key]; valueTab_.erase(key); Link* plink = pnode->link_.next_; Iterator tempItr {LinkNode::GetLinkNode(plink), this}; ReclaimNode(pnode); return tempItr; } template auto HashList::erase(const Iterator pos) -> HashList::Iterator { // assume pos is valid, otherwise the result is undefined Iterator tempItr {pos}; ++tempItr; LinkNode *pnode = pos.GetNode(); valueTab_.erase(pnode->key_); ReclaimNode(pnode); return tempItr; } template auto HashList::erase(const Iterator first, const Iterator last) -> HashList::Iterator { // assume pos is valid, otherwise the result is undefined if (first <= last) { Iterator curPos {first}; while (curPos < last) { curPos = erase(curPos); } return last; } return end(); } template bool HashList::MoveNode(const Iterator& pos, LinkNode *&pnode) { LinkNode *curNode = pos.GetNode(); if (curNode == pnode) { return true; } if (pnode->link_.next_ == &curNode->link_) { return true; } Link* prevLink = pnode->link_.prev_; Link* nextLink = pnode->link_.next_; if (prevLink and nextLink) { prevLink->next_ = nextLink; nextLink->prev_ = prevLink; } Link *currLink = &curNode->link_; prevLink = currLink->prev_; nextLink = &pnode->link_; prevLink->next_ = nextLink; nextLink->prev_ = prevLink; nextLink->next_ = currLink; currLink->prev_ = nextLink; return true; } template void HashList::MoveToHead(LinkNode *&pnode) { if (pnode->link_.prev_ and pnode->link_.next_) { Link* prev = pnode->link_.prev_; Link* next = pnode->link_.next_; prev->next_ = next; next->prev_ = prev; } pnode->link_.next_ = dataHead_.next_; dataHead_.next_->prev_ = &pnode->link_; dataHead_.next_ = &pnode->link_; pnode->link_.prev_ = &dataHead_; } template void HashList::MoveToTail(LinkNode *&pnode) { if (pnode->link_.prev_ and pnode->link_.next_) { Link* prev = pnode->link_.prev_; Link* next = pnode->link_.next_; prev->next_ = next; next->prev_ = prev; } pnode->link_.prev_ = dataHead_.prev_; dataHead_.prev_->next_ = &pnode->link_; pnode->link_.next_ = &dataHead_; dataHead_.prev_ = &pnode->link_; } template auto HashList::AllocateNode(const Key &key) ->LinkNode * { if (IsFull()) { pop_back(); } LinkNode *pnode = LinkNode::GetLinkNode(freeHead_.next_); freeHead_.next_ = freeHead_.next_->next_; if (pnode != nullptr) { pnode->link_.next_ = nullptr; pnode->link_.prev_ = nullptr; pnode->key_ = key; pnode->val_ = Val(); } return pnode; } template auto HashList::AllocateNode(const Key &key, const Val &val) ->LinkNode * { if (IsFull()) { pop_back(); } LinkNode *pnode = LinkNode::GetLinkNode(freeHead_.next_); freeHead_.next_ = freeHead_.next_->next_; pnode->link_.next_ = nullptr; pnode->link_.prev_ = nullptr; pnode->key_ = key; pnode->val_ = val; return pnode; } template auto HashList::AllocateNode(const Key &key, Val &&val) ->LinkNode * { if (IsFull()) { pop_back(); } LinkNode *pnode = LinkNode::GetLinkNode(freeHead_.next_); freeHead_.next_ = freeHead_.next_->next_; pnode->link_.next_ = nullptr; pnode->link_.prev_ = nullptr; pnode->key_ = key; pnode->val_ = std::move(val); return pnode; } template void HashList::ReclaimNode(LinkNode *&pnode) { Link *prevLink = pnode->link_.prev_; Link *nextLink = pnode->link_.next_; prevLink->next_ = nextLink; nextLink->prev_ = prevLink; pnode->link_.prev_ = nullptr; pnode->link_.next_ = freeHead_.next_; freeHead_.next_ = &pnode->link_; return; } } // namespace HiPerf } // namespace Developtools } // namespace OHOS #endif // HIPERF_HASHLIST_H