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(
19 : CallbackMapT& callbackMap, std::recursive_mutex& mutex, 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(
40 : CallbackMapT& callbackMap, std::recursive_mutex& mutex, aclRegisterCallbackType type,
41 : const NotifyInvokerT& notifyInvoker)
42 : {
43 238 : std::lock_guard<std::recursive_mutex> lock(mutex);
44 238 : const auto range = callbackMap.equal_range(type);
45 244 : for (auto it = range.first; it != range.second; ++it) {
46 20 : const aclError ret = notifyInvoker(it->second);
47 20 : if (ret != ACL_SUCCESS) {
48 14 : return ret;
49 : }
50 : }
51 224 : return ACL_SUCCESS;
52 238 : }
53 : } // namespace
54 :
55 283 : InitCallbackManager& InitCallbackManager::GetInstance()
56 : {
57 : // 单例模式上下文不做判空和捕获异常,内存分配失败这种极端情况让程序正常终止,比引入更复杂的错误处理逻辑更合理
58 : // 这里单例在堆上申请且内存不显式释放,是考虑到so卸载顺序的问题,延长单例的生命周期确保不引入异常
59 283 : static InitCallbackManager* instance = new InitCallbackManager();
60 283 : return *instance;
61 : }
62 :
63 1 : InitCallbackManager::InitCallbackManager() {}
64 :
65 18 : aclError InitCallbackManager::RegInitCallback(aclRegisterCallbackType type, aclInitCallbackFunc cbFunc, void* userData)
66 : {
67 18 : if (cbFunc == nullptr) {
68 1 : return ACL_ERROR_INVALID_PARAM;
69 : }
70 17 : std::lock_guard<std::recursive_mutex> lock(mutex_);
71 17 : if (type != ACL_REG_TYPE_OTHER && initCallbackMap_.count(type) != 0U) {
72 2 : return ACL_ERROR_INTERNAL_ERROR;
73 : }
74 15 : initCallbackMap_.insert({type, {cbFunc, userData}});
75 : // 已经初始化的情况下,需要立即执行
76 15 : if (GetAclInitFlag()) {
77 4 : auto& configData = GetConfigPathStr();
78 4 : (void)cbFunc(configData.c_str(), configData.size(), userData);
79 : }
80 15 : return ACL_SUCCESS;
81 17 : }
82 :
83 10 : aclError InitCallbackManager::UnRegInitCallback(aclRegisterCallbackType type, aclInitCallbackFunc cbFunc)
84 : {
85 10 : return UnregisterCallbackImpl(initCallbackMap_, mutex_, type, cbFunc);
86 : }
87 :
88 120 : aclError InitCallbackManager::NotifyInitCallback(aclRegisterCallbackType type, const char* configStr, size_t len)
89 : {
90 240 : return NotifyCallbackImpl(
91 240 : initCallbackMap_, mutex_, type, [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(
97 : aclRegisterCallbackType type, aclFinalizeCallbackFunc cbFunc, 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 236 : return NotifyCallbackImpl(
118 236 : finalizeCallbackMap_, mutex_, type, [](const std::pair<aclFinalizeCallbackFunc, void*>& callbackEntry) {
119 10 : return callbackEntry.first(callbackEntry.second);
120 236 : });
121 : }
122 : } // namespace acl
|