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-08-06 15:29:52 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(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 2.0-1