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 : #include "init_callback_manager.h"
12 : #include "acl/acl_base.h"
13 : #include "acl_rt_impl_base.h"
14 :
15 : namespace acl {
16 : namespace {
17 : template <typename CallbackMapT, typename CallbackFuncT>
18 24 : aclError UnregisterCallbackImpl(CallbackMapT &callbackMap, std::recursive_mutex &mutex,
19 : aclRegisterCallbackType type, CallbackFuncT cbFunc)
20 : {
21 24 : if (cbFunc == nullptr) {
22 0 : return ACL_ERROR_INVALID_PARAM;
23 : }
24 24 : std::lock_guard<std::recursive_mutex> lock(mutex);
25 24 : if (callbackMap.count(type) == 0U) {
26 6 : return ACL_ERROR_INTERNAL_ERROR;
27 : }
28 18 : const auto range = callbackMap.equal_range(type);
29 20 : for (auto it = range.first; it != range.second; ++it) {
30 18 : if (it->second.first == cbFunc) {
31 16 : (void)callbackMap.erase(it);
32 16 : return ACL_SUCCESS;
33 : }
34 : }
35 2 : return ACL_ERROR_INTERNAL_ERROR;
36 24 : }
37 :
38 : template <typename CallbackMapT, typename NotifyInvokerT>
39 238 : aclError NotifyCallbackImpl(CallbackMapT &callbackMap, std::recursive_mutex &mutex,
40 : aclRegisterCallbackType type, const NotifyInvokerT ¬ifyInvoker)
41 : {
42 238 : std::lock_guard<std::recursive_mutex> lock(mutex);
43 238 : const auto range = callbackMap.equal_range(type);
44 244 : for (auto it = range.first; it != range.second; ++it) {
45 20 : const aclError ret = notifyInvoker(it->second);
46 20 : if (ret != ACL_SUCCESS) {
47 14 : return ret;
48 : }
49 : }
50 224 : return ACL_SUCCESS;
51 238 : }
52 : } // namespace
53 :
54 283 : InitCallbackManager &InitCallbackManager::GetInstance()
55 : {
56 : // 单例模式上下文不做判空和捕获异常,内存分配失败这种极端情况让程序正常终止,比引入更复杂的错误处理逻辑更合理
57 : // 这里单例在堆上申请且内存不显式释放,是考虑到so卸载顺序的问题,延长单例的生命周期确保不引入异常
58 283 : static InitCallbackManager *instance = new InitCallbackManager();
59 283 : return *instance;
60 : }
61 :
62 1 : InitCallbackManager::InitCallbackManager(){}
63 :
64 18 : aclError InitCallbackManager::RegInitCallback(aclRegisterCallbackType type, aclInitCallbackFunc cbFunc, void *userData)
65 : {
66 18 : if (cbFunc == nullptr) {
67 1 : return ACL_ERROR_INVALID_PARAM;
68 : }
69 17 : std::lock_guard<std::recursive_mutex> lock(mutex_);
70 17 : if (type != ACL_REG_TYPE_OTHER && initCallbackMap_.count(type) != 0U) {
71 2 : return ACL_ERROR_INTERNAL_ERROR;
72 : }
73 15 : initCallbackMap_.insert({type, {cbFunc, userData}});
74 : // 已经初始化的情况下,需要立即执行
75 15 : if (GetAclInitFlag()) {
76 4 : auto &configData = GetConfigPathStr();
77 4 : (void)cbFunc(configData.c_str(), configData.size(), userData);
78 : }
79 15 : return ACL_SUCCESS;
80 17 : }
81 :
82 10 : aclError InitCallbackManager::UnRegInitCallback(aclRegisterCallbackType type, aclInitCallbackFunc cbFunc)
83 : {
84 10 : return UnregisterCallbackImpl(initCallbackMap_, mutex_, type, cbFunc);
85 : }
86 :
87 120 : aclError InitCallbackManager::NotifyInitCallback(aclRegisterCallbackType type,
88 : const char *configStr, size_t len)
89 : {
90 240 : return NotifyCallbackImpl(initCallbackMap_, mutex_, type,
91 240 : [configStr, len](const std::pair<aclInitCallbackFunc, void *> &callbackEntry) {
92 10 : return callbackEntry.first(configStr, len, callbackEntry.second);
93 240 : });
94 : }
95 :
96 20 : aclError InitCallbackManager::RegFinalizeCallback(aclRegisterCallbackType type, aclFinalizeCallbackFunc cbFunc,
97 : void *userData)
98 : {
99 20 : if (cbFunc == nullptr) {
100 1 : return ACL_ERROR_INVALID_PARAM;
101 : }
102 19 : std::lock_guard<std::recursive_mutex> lock(mutex_);
103 19 : if (type != ACL_REG_TYPE_OTHER && finalizeCallbackMap_.count(type) != 0U) {
104 2 : return ACL_ERROR_INTERNAL_ERROR;
105 : }
106 17 : finalizeCallbackMap_.insert({type, {cbFunc, userData}});
107 17 : return ACL_SUCCESS;
108 19 : }
109 :
110 14 : aclError InitCallbackManager::UnRegFinalizeCallback(aclRegisterCallbackType type, aclFinalizeCallbackFunc cbFunc)
111 : {
112 14 : return UnregisterCallbackImpl(finalizeCallbackMap_, mutex_, type, cbFunc);
113 : }
114 :
115 118 : aclError InitCallbackManager::NotifyFinalizeCallback(aclRegisterCallbackType type)
116 : {
117 118 : return NotifyCallbackImpl(finalizeCallbackMap_, mutex_, type,
118 118 : [](const std::pair<aclFinalizeCallbackFunc, void *> &callbackEntry) {
119 10 : return callbackEntry.first(callbackEntry.second);
120 236 : });
121 : }
122 : } // namespace acl
|