LCOV - code coverage report
Current view: top level - base_comm/common - rma_buffer_mgr.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.6 % 83 76
Test Date: 2026-08-29 17:38:31 Functions: 65.4 % 130 85

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #ifndef RMA_BUFFER_MGR_H
      12              : #define RMA_BUFFER_MGR_H
      13              : 
      14              : #include <map>
      15              : #include <mutex>
      16              : #include <shared_mutex>
      17              : #include <utility>
      18              : #include "buffer_key.h"
      19              : #include "log.h"
      20              : 
      21              : namespace hcomm {
      22              : template <typename KeyType, typename BufferType, template <typename...> class M = std::map, typename... MapArgs>
      23              : class RmaBufferMgr {
      24              : public:
      25              :     struct BufferWithRef {
      26              :         // BufferType可以是指针的类型
      27              :         BufferType buffer{};
      28              :         uint64_t ref{}; // 引用计数
      29              : 
      30          151 :         BufferWithRef(BufferType buf, uint64_t r) : buffer(buf), ref(r) {}
      31              :     };
      32              : 
      33              :     using AddrType = typename KeyType::AddrType;
      34              :     using SizeType = typename KeyType::SizeType;
      35              : 
      36              :     using MapType = M<KeyType, BufferWithRef, MapArgs...>;
      37              :     using Iterator = typename MapType::iterator;
      38              :     using ConstIterator = typename MapType::const_iterator;
      39              : 
      40              :     template <typename... BufferArgs>
      41              :     // 禁止直接调用,请使用加锁版本的 AddWithoutCheck 替代
      42          151 :     std::pair<Iterator, bool> AddToTree(const KeyType& key, BufferArgs&&... bufferArgs)
      43              :     {
      44          151 :         auto result = intervalTree_.emplace(
      45          151 :             std::piecewise_construct, std::forward_as_tuple(key),
      46          302 :             std::forward_as_tuple(BufferWithRef{BufferType{std::forward<BufferArgs>(bufferArgs)...}, 1}));
      47          151 :         if (!result.second) {
      48           31 :             result.first->second.ref++;
      49              :             // 翻转
      50           31 :             if (result.first->second.ref == 0) {
      51            0 :                 HCCL_ERROR("Error: ref = 0, ref++ flipped");
      52            0 :                 throw std::logic_error("ref++ = 0, ref++ flipped");
      53           31 :             } else if (result.first->second.ref > 1) {
      54           31 :                 HCCL_INFO(
      55              :                     "Memory is already registered, just increase the reference count, "
      56              :                     "current memory reference count[%llu], %s.",
      57              :                     result.first->second.ref, key.ToString().c_str());
      58              :             }
      59              :         }
      60              : 
      61          151 :         return result;
      62              :     }
      63              : 
      64              :     template <typename... BufferArgs>
      65          127 :     std::pair<Iterator, bool> AddWithoutCheck(const KeyType& key, BufferArgs&&... bufferArgs)
      66              :     {
      67          127 :         std::unique_lock<std::shared_mutex> lock(mtx_);
      68          254 :         return AddToTree(key, std::forward<BufferArgs>(bufferArgs)...);
      69          127 :     }
      70              : 
      71              :     // 1.添加成功:输入key是表中某一最相近key的空集。 计数+1,返回添加成功的迭代器,及true
      72              :     // 2.添加已存在:输入key是表中某一最相近key的全集。 计数+1,返回添加该key的迭代器,及false
      73              :     // 3.添加失败:输入key是表中某一个最相近key的交集、子集、超集。返回空迭代器,及false
      74              :     template <typename... BufferArgs>
      75           25 :     std::pair<Iterator, bool> Add(const KeyType& key, BufferArgs&&... bufferArgs)
      76              :     {
      77           25 :         std::unique_lock<std::shared_mutex> lock(mtx_);
      78           25 :         auto overlapResult = CheckOverlap(key);
      79           25 :         if (overlapResult.second) {
      80            3 :             HCCL_ERROR("Error: Buffer key overlaps with existing buffer key.");
      81            1 :             return std::make_pair(intervalTree_.end(), false);
      82              :         }
      83           24 :         return AddToTree(key, std::forward<BufferArgs>(bufferArgs)...);
      84           25 :     }
      85              : 
      86              :     // 1.查询成功:输入key是表中某一最相近key的子集、全集。 返回true,最相近key的bufferType
      87              :     // 2.查询失败:输入key是表中某一个最相近key的空集、交集。返回false,空bufferType
      88          150 :     std::pair<bool, BufferType> Find(const KeyType& key) const
      89              :     {
      90          150 :         std::shared_lock<std::shared_mutex> lock(mtx_);
      91          150 :         auto it = intervalTree_.lower_bound(key);
      92          150 :         if (it != intervalTree_.end() && (it->first == key || it->first.IsSuperset(key))) {
      93           80 :             return std::make_pair(true, it->second.buffer);
      94              :         }
      95              : 
      96           70 :         if (it != intervalTree_.begin()) {
      97            7 :             auto prevIt = std::prev(it);
      98            7 :             if (prevIt->first.IsSuperset(key)) {
      99            1 :                 return std::make_pair(true, prevIt->second.buffer);
     100              :             }
     101            6 :             if (it != intervalTree_.end()) {
     102            2 :                 HCCL_WARNING(
     103              :                     "Key[%s] not found. The near key is [%s] or [%s].", key.ToString().c_str(),
     104              :                     it->first.ToString().c_str(), prevIt->first.ToString().c_str());
     105              :             } else {
     106            4 :                 HCCL_WARNING(
     107              :                     "Key[%s] not found. The near key is [%s]", key.ToString().c_str(),
     108              :                     prevIt->first.ToString().c_str());
     109              :             }
     110              :         } else {
     111           63 :             if (it != intervalTree_.end()) {
     112            0 :                 HCCL_WARNING(
     113              :                     "Key[%s] not found. The near key is [%s]", key.ToString().c_str(), it->first.ToString().c_str());
     114              :             } else {
     115           63 :                 HCCL_WARNING("Key[%s] not found. There is no key in table.", key.ToString().c_str());
     116              :             }
     117              :         }
     118              : 
     119           69 :         return std::make_pair(false, BufferType{}); // 未找到
     120          150 :     }
     121              : 
     122              :     // 1.删除成功:输入key是表中某一最相近key的全集。 计数-1且之后为0。  返回true
     123              :     // 2.删除引用数-1但未删除:输入key是表中某一最相近key的全集。 计数-1且之后大于0。 返回false
     124              :     // 3.删除失败:输入key是表中某一个最相近key的交集、子集、超集、空集。——抛出NOT_FOUND异常
     125           93 :     bool Del(const KeyType& key)
     126              :     {
     127           93 :         std::unique_lock<std::shared_mutex> lock(mtx_);
     128           93 :         auto it = intervalTree_.find(key);
     129           93 :         if (it == intervalTree_.end()) {
     130            9 :             HCCL_ERROR("Error: Buffer key not found.");
     131            9 :             throw std::out_of_range("Del NOT_FOUND");
     132              :         }
     133              : 
     134           84 :         if (--(it->second.ref) == 0) {
     135           56 :             intervalTree_.erase(it);
     136           56 :             return true;
     137              :         }
     138              :         // 引用计数大于0,不删除
     139           28 :         HCCL_RUN_INFO(
     140              :             "Memory reference count is larger than 0, (used by other RemoteRank), do not deregister memory."
     141              :             "current memory reference count[%llu], %s.",
     142              :             it->second.ref, key.ToString().c_str());
     143           28 :         return false;
     144           93 :     }
     145              : 
     146           77 :     bool IsInTree(const KeyType& key)
     147              :     {
     148           77 :         std::shared_lock<std::shared_mutex> lock(mtx_);
     149           77 :         auto it = intervalTree_.find(key);
     150           77 :         if (it == intervalTree_.end()) {
     151           52 :             return false;
     152              :         }
     153           25 :         return true;
     154           77 :     }
     155              : 
     156           69 :     ConstIterator Begin() { return intervalTree_.begin(); }
     157              : 
     158            6 :     ConstIterator Next(ConstIterator it) { return std::next(it); }
     159              : 
     160           85 :     ConstIterator End() { return intervalTree_.end(); }
     161           13 :     size_t size() const { return intervalTree_.size(); }
     162              :     void PrintContents() const
     163              :     {
     164              :         std::shared_lock<std::shared_mutex> lock(mtx_);
     165              :         for (const auto& pair : intervalTree_) {
     166              :             HCCL_INFO("Key: %s, Value: %p", pair.first.ToString().c_str(), pair.second.buffer.get());
     167              :         }
     168              :     }
     169              : 
     170              :     template <typename Fn>
     171            1 :     void ForEach(Fn&& fn) const
     172              :     {
     173            1 :         std::shared_lock<std::shared_mutex> lock(mtx_);
     174            2 :         for (const auto& pair : intervalTree_) {
     175            1 :             std::forward<Fn>(fn)(pair.first, pair.second.buffer);
     176              :         }
     177            1 :     }
     178              : 
     179              : private:
     180              :     MapType intervalTree_;
     181              :     mutable std::shared_mutex mtx_{};
     182              : 
     183           25 :     std::pair<Iterator, bool> CheckOverlap(const KeyType& key)
     184              :     {
     185           25 :         auto it = intervalTree_.lower_bound(key);
     186           25 :         if (it != intervalTree_.end()) {
     187              :             // 情况1:addr_ == it->first.addr_ && size_ == it->first.size_
     188            0 :             if (it->first == key) {
     189            0 :                 return std::make_pair(it, false);
     190              :             }
     191              : 
     192              :             // 情况2:addr_ == it->first.addr_ && size_ < it->first.size_。it->first.IsSubset(key)非必须
     193              :             // 情况3:addr_ < it->first.addr_
     194            0 :             if (it->first.IsSuperset(key) || it->first.IsIntersect(key)) {
     195            0 :                 return std::make_pair(it, true);
     196              :             }
     197              :         }
     198              : 
     199              :         // 剩下的是空集
     200           25 :         if (it != intervalTree_.begin()) {
     201            2 :             auto prevIt = std::prev(it);
     202              :             // 情况4:addr_ > prevIt->first.addr_
     203              :             // 情况5: 1) addr_ > prevIt->first.addr_的子集情况;
     204              :             // 2) addr_ == prevIt->first.addr_,size_ > prevIt->first.size
     205            2 :             if (prevIt->first.IsIntersect(key) || prevIt->first.IsSubset(key) || prevIt->first.IsSuperset(key)) {
     206            1 :                 return std::make_pair(prevIt, true);
     207              :             }
     208              : 
     209              :             // 6. 剩下的是空集
     210            1 :             return std::make_pair(prevIt, false);
     211              :         }
     212              : 
     213              :         // 剩下的是空集
     214           23 :         return std::make_pair(it, false);
     215              :     }
     216              : };
     217              : } // namespace hcomm
     218              : 
     219              : #endif
        

Generated by: LCOV version 2.0-1