LCOV - code coverage report
Current view: top level - base_comm/common - rma_buffer_mgr.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 90.3 % 72 65
Test Date: 2026-08-18 17:47:01 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 <utility>
      16              : #include "buffer_key.h"
      17              : #include "log.h"
      18              : 
      19              : namespace hcomm {
      20              : template <typename KeyType, typename BufferType, template <typename...> class M = std::map, typename... MapArgs>
      21              : class RmaBufferMgr {
      22              : public:
      23              :     struct BufferWithRef {
      24              :         // BufferType可以是指针的类型
      25              :         BufferType buffer{};
      26              :         uint64_t ref{}; // 引用计数
      27              : 
      28          151 :         BufferWithRef(BufferType buf, uint64_t r) : buffer(buf), ref(r) {}
      29              :     };
      30              : 
      31              :     using AddrType = typename KeyType::AddrType;
      32              :     using SizeType = typename KeyType::SizeType;
      33              : 
      34              :     using MapType = M<KeyType, BufferWithRef, MapArgs...>;
      35              :     using Iterator = typename MapType::iterator;
      36              :     using ConstIterator = typename MapType::const_iterator;
      37              : 
      38              :     template <typename... BufferArgs>
      39          151 :     std::pair<Iterator, bool> AddToTree(const KeyType& key, BufferArgs&&... bufferArgs)
      40              :     {
      41          151 :         auto result = intervalTree_.emplace(
      42          151 :             std::piecewise_construct, std::forward_as_tuple(key),
      43          302 :             std::forward_as_tuple(BufferWithRef{BufferType{std::forward<BufferArgs>(bufferArgs)...}, 1}));
      44          151 :         if (!result.second) {
      45           31 :             result.first->second.ref++;
      46              :             // 翻转
      47           31 :             if (result.first->second.ref == 0) {
      48            0 :                 HCCL_ERROR("Error: ref = 0, ref++ flipped");
      49            0 :                 throw std::logic_error("ref++ = 0, ref++ flipped");
      50           31 :             } else if (result.first->second.ref > 1) {
      51           31 :                 HCCL_INFO(
      52              :                     "Memory is already registered, just increase the reference count, "
      53              :                     "current memory reference count[%llu], %s.",
      54              :                     result.first->second.ref, key.ToString().c_str());
      55              :             }
      56              :         }
      57              : 
      58          151 :         return result;
      59              :     }
      60              : 
      61              :     template <typename... BufferArgs>
      62          127 :     std::pair<Iterator, bool> AddWithoutCheck(const KeyType& key, BufferArgs&&... bufferArgs)
      63              :     {
      64          127 :         return AddToTree(key, std::forward<BufferArgs>(bufferArgs)...);
      65              :     }
      66              : 
      67              :     // 1.添加成功:输入key是表中某一最相近key的空集。 计数+1,返回添加成功的迭代器,及true
      68              :     // 2.添加已存在:输入key是表中某一最相近key的全集。 计数+1,返回添加该key的迭代器,及false
      69              :     // 3.添加失败:输入key是表中某一个最相近key的交集、子集、超集。返回空迭代器,及false
      70              :     template <typename... BufferArgs>
      71           25 :     std::pair<Iterator, bool> Add(const KeyType& key, BufferArgs&&... bufferArgs)
      72              :     {
      73           25 :         auto overlapResult = CheckOverlap(key);
      74           25 :         if (overlapResult.second) {
      75            3 :             HCCL_ERROR("Error: Buffer key overlaps with existing buffer key.");
      76            1 :             return std::make_pair(intervalTree_.end(), false);
      77              :         }
      78           24 :         return AddToTree(key, std::forward<BufferArgs>(bufferArgs)...);
      79              :     }
      80              : 
      81              :     // 1.查询成功:输入key是表中某一最相近key的子集、全集。 返回true,最相近key的bufferType
      82              :     // 2.查询失败:输入key是表中某一个最相近key的空集、交集。返回false,空bufferType
      83          150 :     std::pair<bool, BufferType> Find(const KeyType& key) const
      84              :     {
      85          150 :         auto it = intervalTree_.lower_bound(key);
      86          150 :         if (it != intervalTree_.end() && (it->first == key || it->first.IsSuperset(key))) {
      87           80 :             return std::make_pair(true, it->second.buffer);
      88              :         }
      89              : 
      90           70 :         if (it != intervalTree_.begin()) {
      91            7 :             auto prevIt = std::prev(it);
      92            7 :             if (prevIt->first.IsSuperset(key)) {
      93            1 :                 return std::make_pair(true, prevIt->second.buffer);
      94              :             }
      95            6 :             if (it != intervalTree_.end()) {
      96            2 :                 HCCL_WARNING(
      97              :                     "Key[%s] not found. The near key is [%s] or [%s].", key.ToString().c_str(),
      98              :                     it->first.ToString().c_str(), prevIt->first.ToString().c_str());
      99              :             } else {
     100            4 :                 HCCL_WARNING(
     101              :                     "Key[%s] not found. The near key is [%s]", key.ToString().c_str(),
     102              :                     prevIt->first.ToString().c_str());
     103              :             }
     104              :         } else {
     105           63 :             if (it != intervalTree_.end()) {
     106            0 :                 HCCL_WARNING(
     107              :                     "Key[%s] not found. The near key is [%s]", key.ToString().c_str(), it->first.ToString().c_str());
     108              :             } else {
     109           63 :                 HCCL_WARNING("Key[%s] not found. There is no key in table.", key.ToString().c_str());
     110              :             }
     111              :         }
     112              : 
     113           69 :         return std::make_pair(false, BufferType{}); // 未找到
     114              :     }
     115              : 
     116              :     // 1.删除成功:输入key是表中某一最相近key的全集。 计数-1且之后为0。  返回true
     117              :     // 2.删除引用数-1但未删除:输入key是表中某一最相近key的全集。 计数-1且之后大于0。 返回false
     118              :     // 3.删除失败:输入key是表中某一个最相近key的交集、子集、超集、空集。——抛出NOT_FOUND异常
     119           93 :     bool Del(const KeyType& key)
     120              :     {
     121           93 :         auto it = intervalTree_.find(key);
     122           93 :         if (it == intervalTree_.end()) {
     123            9 :             HCCL_ERROR("Error: Buffer key not found.");
     124            9 :             throw std::out_of_range("Del NOT_FOUND");
     125              :         }
     126              : 
     127           84 :         if (--(it->second.ref) == 0) {
     128           56 :             intervalTree_.erase(it);
     129           56 :             return true;
     130              :         }
     131              :         // 引用计数大于0,不删除
     132           28 :         HCCL_RUN_INFO(
     133              :             "Memory reference count is larger than 0, (used by other RemoteRank), do not deregister memory."
     134              :             "current memory reference count[%llu], %s.",
     135              :             it->second.ref, key.ToString().c_str());
     136           28 :         return false;
     137              :     }
     138              : 
     139           77 :     bool IsInTree(const KeyType& key)
     140              :     {
     141           77 :         auto it = intervalTree_.find(key);
     142           77 :         if (it == intervalTree_.end()) {
     143           52 :             return false;
     144              :         }
     145           25 :         return true;
     146              :     }
     147              : 
     148           69 :     ConstIterator Begin() { return intervalTree_.begin(); }
     149              : 
     150            6 :     ConstIterator Next(ConstIterator it) { return std::next(it); }
     151              : 
     152           85 :     ConstIterator End() { return intervalTree_.end(); }
     153           13 :     size_t size() const { return intervalTree_.size(); }
     154              :     void PrintContents() const
     155              :     {
     156              :         for (const auto& pair : intervalTree_) {
     157              :             HCCL_INFO("Key: %s, Value: %p", pair.first.ToString().c_str(), pair.second.buffer.get());
     158              :         }
     159              :     }
     160              : 
     161              :     template <typename Fn>
     162            1 :     void ForEach(Fn&& fn) const
     163              :     {
     164            2 :         for (const auto& pair : intervalTree_) {
     165            1 :             std::forward<Fn>(fn)(pair.first, pair.second.buffer);
     166              :         }
     167            1 :     }
     168              : 
     169              : private:
     170              :     MapType intervalTree_;
     171              : 
     172           25 :     std::pair<Iterator, bool> CheckOverlap(const KeyType& key)
     173              :     {
     174           25 :         auto it = intervalTree_.lower_bound(key);
     175           25 :         if (it != intervalTree_.end()) {
     176              :             // 情况1:addr_ == it->first.addr_ && size_ == it->first.size_
     177            0 :             if (it->first == key) {
     178            0 :                 return std::make_pair(it, false);
     179              :             }
     180              : 
     181              :             // 情况2:addr_ == it->first.addr_ && size_ < it->first.size_。it->first.IsSubset(key)非必须
     182              :             // 情况3:addr_ < it->first.addr_
     183            0 :             if (it->first.IsSuperset(key) || it->first.IsIntersect(key)) {
     184            0 :                 return std::make_pair(it, true);
     185              :             }
     186              :         }
     187              : 
     188              :         // 剩下的是空集
     189           25 :         if (it != intervalTree_.begin()) {
     190            2 :             auto prevIt = std::prev(it);
     191              :             // 情况4:addr_ > prevIt->first.addr_
     192              :             // 情况5: 1) addr_ > prevIt->first.addr_的子集情况;
     193              :             // 2) addr_ == prevIt->first.addr_,size_ > prevIt->first.size
     194            2 :             if (prevIt->first.IsIntersect(key) || prevIt->first.IsSubset(key) || prevIt->first.IsSuperset(key)) {
     195            1 :                 return std::make_pair(prevIt, true);
     196              :             }
     197              : 
     198              :             // 6. 剩下的是空集
     199            1 :             return std::make_pair(prevIt, false);
     200              :         }
     201              : 
     202              :         // 剩下的是空集
     203           23 :         return std::make_pair(it, false);
     204              :     }
     205              : };
     206              : } // namespace hcomm
     207              : 
     208              : #endif
        

Generated by: LCOV version 2.0-1