LCOV - code coverage report
Current view: top level - runtime/c/c_base/src - ref_obj.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 33 54 61.1 %
Date: 2026-08-27 13:24:42 Functions: 5 8 62.5 %

          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             : #include "ref_obj.h"
      11             : 
      12             : #ifdef __cplusplus
      13             : extern "C" {
      14             : #endif
      15             : 
      16             : #define REF_OBJ_UPDATING 0x8000000000000000UL
      17             : #define TRY_LOOP_MAX 0x80000000UL
      18             : 
      19             : typedef struct {
      20             :     int step;
      21             :     uint64_t oldValTrigger;
      22             : } RefObjUpdate;
      23             : 
      24           0 : void InitRefObj(RefObj *obj)
      25             : {
      26           0 :     obj->refCount = 0;
      27           0 :     obj->obj = NULL;
      28           0 : }
      29             : 
      30          32 : static bool ObjRefCount(RefObj *obj, const RefObjUpdate *update,
      31             :     void(*pfnHook)(RefObj *, const void *, void *), void *appInfo, const void *usrData)
      32             : {
      33             :     uint64_t oldVal;
      34             :     uint64_t newVal;
      35          32 :     uint64_t tryCount = 0UL;
      36          32 :     uint64_t perSchedYield = 0x3FFU;
      37             :     do {
      38          32 :         tryCount++;
      39          32 :         if ((tryCount & perSchedYield) == 0U) {
      40           0 :             (void)mmSchedYield();
      41             :         }
      42          32 :         oldVal = obj->refCount;
      43          32 :         if ((oldVal & REF_OBJ_UPDATING) != 0) {
      44           0 :             continue;
      45             :         }
      46             :         // 防溢出
      47          32 :         if (((update->step < 0) && (oldVal < (uint64_t)(0L - update->step))) ||
      48          32 :             ((update->step > 0) && (oldVal >= REF_OBJ_UPDATING - update->step))) {
      49           0 :             return false;
      50             :         }
      51          32 :         newVal = (oldVal == update->oldValTrigger) ? REF_OBJ_UPDATING : (oldVal + update->step);
      52          32 :         if (mmCompareAndSwap64(&obj->refCount, oldVal, newVal)) {
      53          32 :             if (oldVal == update->oldValTrigger) {
      54          30 :                 pfnHook(obj, usrData, appInfo);
      55             :             }
      56          32 :             return true;
      57             :         }
      58           0 :     } while (tryCount < TRY_LOOP_MAX);
      59           0 :     return false;
      60             : }
      61             : 
      62           0 : static void CreateRefObjVal(RefObj *obj, const void *userData, void *fnCreateObj)
      63             : {
      64             :     (void)userData;
      65           0 :     obj->obj = ((FnCreateRefObjValue)fnCreateObj)(obj);
      66           0 :     mmSetData64(&obj->refCount, 1);
      67           0 : }
      68             : 
      69          15 : static void CreateRefObjValWithUserData(RefObj *obj, const void *userData, void *fnCreateObj)
      70             : {
      71          15 :     obj->obj = ((FnCreateRefObjValueWithUserData)fnCreateObj)(obj, userData);
      72          15 :     mmSetData64(&obj->refCount, 1);
      73          15 : }
      74             : 
      75          15 : static void DestroyRefObjVal(RefObj *obj, const void *userData, void *fnDestroyObj)
      76             : {
      77             :     (void)userData;
      78          15 :     mmSetData64(&obj->refCount, 0);
      79          15 :     if (fnDestroyObj != NULL) {
      80          12 :         ((FnDestroyRefObjValue)fnDestroyObj)(obj);
      81             :     }
      82          15 : }
      83             : 
      84           0 : void* GetObjRef(RefObj *obj, FnCreateRefObjValue fnCreateObj)
      85             : {
      86           0 :     RefObjUpdate update = {1, 0};
      87           0 :     if (!ObjRefCount(obj, &update, CreateRefObjVal, fnCreateObj, NULL)) {
      88           0 :         return NULL;
      89             :     }
      90           0 :     if (obj->obj == NULL) {
      91           0 :         ReleaseObjRef(obj, NULL);
      92             :     }
      93           0 :     return obj->obj;
      94             : }
      95             : 
      96          16 : void* GetObjRefWithUserData(RefObj *obj, const void *userData, FnCreateRefObjValueWithUserData fnCreateObj)
      97             : {
      98          16 :     RefObjUpdate update = {1, 0};
      99          16 :     if (!ObjRefCount(obj, &update, CreateRefObjValWithUserData, fnCreateObj, userData)) {
     100           0 :         return NULL;
     101             :     }
     102          16 :     if (obj->obj == NULL) {
     103           3 :         ReleaseObjRef(obj, NULL);
     104             :     }
     105          16 :     return obj->obj;
     106             : }
     107             : 
     108          16 : void ReleaseObjRef(RefObj *obj, FnDestroyRefObjValue fnDestroyObj)
     109             : {
     110          16 :     RefObjUpdate update = {-1, 1};
     111          16 :     (void)ObjRefCount(obj, &update, DestroyRefObjVal, fnDestroyObj, NULL);
     112          16 : }
     113             : 
     114             : #ifdef __cplusplus
     115             : }
     116             : #endif

Generated by: LCOV version 1.14