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 : #ifndef ADUMP_COMMON_ADUMP_PLATFORM_REGISTRY_H
11 : #define ADUMP_COMMON_ADUMP_PLATFORM_REGISTRY_H
12 :
13 : #include <functional>
14 : #include <map>
15 : #include <memory>
16 : #include <mutex>
17 : #include <new>
18 : #include "adump_dsmi.h"
19 :
20 : namespace Adx {
21 :
22 : // 每个平台接口域(FeaturesSupport / Coredump / ExceptionDump / DataDump)各自拥有一份
23 : // 独立的注册表,按接口类型 Iface 特化。平台只注册它支持的域;某平台在某域未注册,即表示
24 : // 该域能力在此平台不可用,对应 Manager::Get() 返回 nullptr。
25 : //
26 : // 并发说明:同一进程内可能有多个模块(如 runtime 与 GE)通过 adump 接口触发注册,注册
27 : // (写 map)与查询(读 map)可能来自不同线程并发发生,而 std::map 的并发读写属未定义行为。
28 : // 因此这里用每个 Iface 独立的静态互斥锁保护 map 的所有读写;函数内局部静态量的初始化
29 : // 由 C++11 保证线程安全,规避了跨翻译单元静态初始化顺序问题。
30 : template<typename Iface>
31 : class PlatformReflection {
32 : public:
33 : using Factory = std::function<std::shared_ptr<Iface>()>;
34 :
35 : template<typename T>
36 36 : static void RegisterPlatform(PlatformType type)
37 : {
38 36 : std::lock_guard<std::mutex> lock(GetMutex());
39 86 : GetPlatformMap()[type] = []() -> std::shared_ptr<Iface> {
40 50 : return std::shared_ptr<Iface>(new (std::nothrow) T);
41 : };
42 36 : }
43 :
44 466 : static std::shared_ptr<Iface> CreatePlatform(PlatformType type)
45 : {
46 466 : Factory factory;
47 : {
48 466 : std::lock_guard<std::mutex> lock(GetMutex());
49 466 : auto& map = GetPlatformMap();
50 466 : auto it = map.find(type);
51 466 : if (it == map.end()) {
52 416 : return nullptr;
53 : }
54 50 : factory = it->second; // 锁内取出工厂,锁外再构造对象,避免持锁做堆分配
55 466 : }
56 50 : return factory ? factory() : nullptr;
57 466 : }
58 :
59 : private:
60 : // 函数内局部静态 map,规避跨翻译单元静态初始化顺序问题。
61 502 : static std::map<PlatformType, Factory>& GetPlatformMap()
62 : {
63 502 : static std::map<PlatformType, Factory> map;
64 502 : return map;
65 : }
66 :
67 : // 保护 GetPlatformMap() 读写的互斥锁,与 map 一样按 Iface 独立且惰性初始化。
68 502 : static std::mutex& GetMutex()
69 : {
70 : static std::mutex mtx;
71 502 : return mtx;
72 : }
73 : };
74 :
75 : template<typename Iface, typename T>
76 : class PlatformRegister {
77 : public:
78 36 : explicit PlatformRegister(PlatformType type)
79 : {
80 36 : PlatformReflection<Iface>::template RegisterPlatform<T>(type);
81 36 : }
82 : };
83 :
84 : // 一行注册某平台实现类 platformClass 到接口域 Iface 的工厂。
85 : // 各平台 .cpp 顶部按支持的域写若干行;不支持的域不写。
86 : #define ADUMP_PLATFORM_REGISTER(Iface, platformType, platformClass) \
87 : static Adx::PlatformRegister<Iface, platformClass> \
88 : g_adumpReg_##Iface##_##platformClass(platformType)
89 :
90 : } // namespace Adx
91 : #endif // ADUMP_COMMON_ADUMP_PLATFORM_REGISTRY_H
|