LCOV - code coverage report
Current view: top level - runtime_compact/c_base/src - ref_obj.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 61.1 % 54 33
Test Date: 2026-07-28 10:53:01 Functions: 62.5 % 8 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(
      31              :     RefObj* obj, const RefObjUpdate* update, void (*pfnHook)(RefObj*, const void*, void*), void* appInfo,
      32              :     const void* usrData)
      33              : {
      34              :     uint64_t oldVal;
      35              :     uint64_t newVal;
      36           32 :     uint64_t tryCount = 0UL;
      37           32 :     uint64_t perSchedYield = 0x3FFU;
      38              :     do {
      39           32 :         tryCount++;
      40           32 :         if ((tryCount & perSchedYield) == 0U) {
      41            0 :             (void)mmSchedYield();
      42              :         }
      43           32 :         oldVal = obj->refCount;
      44           32 :         if ((oldVal & REF_OBJ_UPDATING) != 0) {
      45            0 :             continue;
      46              :         }
      47              :         // 防溢出
      48           32 :         if (((update->step < 0) && (oldVal < (uint64_t)(0L - update->step))) ||
      49           32 :             ((update->step > 0) && (oldVal >= REF_OBJ_UPDATING - update->step))) {
      50            0 :             return false;
      51              :         }
      52           32 :         newVal = (oldVal == update->oldValTrigger) ? REF_OBJ_UPDATING : (oldVal + update->step);
      53           32 :         if (mmCompareAndSwap64(&obj->refCount, oldVal, newVal)) {
      54           32 :             if (oldVal == update->oldValTrigger) {
      55           30 :                 pfnHook(obj, usrData, appInfo);
      56              :             }
      57           32 :             return true;
      58              :         }
      59            0 :     } while (tryCount < TRY_LOOP_MAX);
      60            0 :     return false;
      61              : }
      62              : 
      63            0 : static void CreateRefObjVal(RefObj* obj, const void* userData, void* fnCreateObj)
      64              : {
      65              :     (void)userData;
      66            0 :     obj->obj = ((FnCreateRefObjValue)fnCreateObj)(obj);
      67            0 :     mmSetData64(&obj->refCount, 1);
      68            0 : }
      69              : 
      70           15 : static void CreateRefObjValWithUserData(RefObj* obj, const void* userData, void* fnCreateObj)
      71              : {
      72           15 :     obj->obj = ((FnCreateRefObjValueWithUserData)fnCreateObj)(obj, userData);
      73           15 :     mmSetData64(&obj->refCount, 1);
      74           15 : }
      75              : 
      76           15 : static void DestroyRefObjVal(RefObj* obj, const void* userData, void* fnDestroyObj)
      77              : {
      78              :     (void)userData;
      79           15 :     mmSetData64(&obj->refCount, 0);
      80           15 :     if (fnDestroyObj != NULL) {
      81           12 :         ((FnDestroyRefObjValue)fnDestroyObj)(obj);
      82              :     }
      83           15 : }
      84              : 
      85            0 : void* GetObjRef(RefObj* obj, FnCreateRefObjValue fnCreateObj)
      86              : {
      87            0 :     RefObjUpdate update = {1, 0};
      88            0 :     if (!ObjRefCount(obj, &update, CreateRefObjVal, fnCreateObj, NULL)) {
      89            0 :         return NULL;
      90              :     }
      91            0 :     if (obj->obj == NULL) {
      92            0 :         ReleaseObjRef(obj, NULL);
      93              :     }
      94            0 :     return obj->obj;
      95              : }
      96              : 
      97           16 : void* GetObjRefWithUserData(RefObj* obj, const void* userData, FnCreateRefObjValueWithUserData fnCreateObj)
      98              : {
      99           16 :     RefObjUpdate update = {1, 0};
     100           16 :     if (!ObjRefCount(obj, &update, CreateRefObjValWithUserData, fnCreateObj, userData)) {
     101            0 :         return NULL;
     102              :     }
     103           16 :     if (obj->obj == NULL) {
     104            3 :         ReleaseObjRef(obj, NULL);
     105              :     }
     106           16 :     return obj->obj;
     107              : }
     108              : 
     109           16 : void ReleaseObjRef(RefObj* obj, FnDestroyRefObjValue fnDestroyObj)
     110              : {
     111           16 :     RefObjUpdate update = {-1, 1};
     112           16 :     (void)ObjRefCount(obj, &update, DestroyRefObjVal, fnDestroyObj, NULL);
     113           16 : }
     114              : 
     115              : #ifdef __cplusplus
     116              : }
     117              : #endif
        

Generated by: LCOV version 2.0-1