]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | #ifndef OPENTRACING_DYNAMIC_LOAD_H |
2 | #define OPENTRACING_DYNAMIC_LOAD_H | |
3 | ||
4 | #include <opentracing/config.h> | |
5 | #include <opentracing/symbols.h> | |
6 | #include <opentracing/tracer.h> | |
7 | #include <opentracing/tracer_factory.h> | |
8 | #include <opentracing/version.h> | |
9 | #include <system_error> | |
10 | ||
11 | // OpenTracingMakeTracerFactory provides a common hook that can be used to | |
12 | // create an TracerFactory from a dynamically loaded library. Users should | |
13 | // prefer to use the function DynamicallyLoadTracingLibrary over calling it | |
14 | // directly. | |
15 | // | |
16 | // It takes the parameter `opentracing_version` and `opentracing_abi_version` | |
17 | // representing the version of opentracing used by the caller. Upon success it | |
18 | // returns the code `0` and sets `tracer_factory` to point to an instance of | |
19 | // TracerFactory. | |
20 | // | |
21 | // On failure, it returns a non-zero error code and sets `error_category` to | |
22 | // point to an std::error_category for the returned error code. | |
23 | // | |
24 | // Example usage, | |
25 | // | |
26 | // const std::error_category* error_category = nullptr; | |
27 | // std::string error_message; | |
28 | // opentracing::TracerFactory* tracer_factory = nullptr; | |
29 | // int rcode = (*OpenTracingMakeTracerFactory)( | |
30 | // OPENTRACING_VERSION, | |
31 | // OPENTRACING_ABI_VERSION, | |
32 | // &static_cast<const void*>(error_category), | |
33 | // static_cast<void*>(&error_message), | |
34 | // &static_cast<void*>(tracer_factory)); | |
35 | // if (rcode == 0) { | |
36 | // // success | |
37 | // assert(tracer_factory != nullptr); | |
38 | // } else { | |
39 | // // failure | |
40 | // assert(error_category != nullptr); | |
41 | // std::error_code error{rcode, *error_category}; | |
42 | // } | |
43 | using OpenTracingMakeTracerFactoryType = int( | |
44 | const char* opentracing_version, const char* opentracing_abi_version, | |
45 | const void** error_category, void* error_message, void** tracer_factory); | |
46 | ||
47 | #ifdef WIN32 | |
48 | ||
49 | #define OPENTRACING_DECLARE_IMPL_FACTORY(X) \ | |
50 | extern "C" { \ | |
51 | \ | |
52 | extern __declspec(dllexport) \ | |
53 | OpenTracingMakeTracerFactoryType* const OpenTracingMakeTracerFactory; \ | |
54 | \ | |
55 | __declspec(selectany) OpenTracingMakeTracerFactoryType* const \ | |
56 | OpenTracingMakeTracerFactory = X; \ | |
57 | } // extern "C" | |
58 | ||
59 | #else | |
60 | ||
61 | #define OPENTRACING_DECLARE_IMPL_FACTORY(X) \ | |
62 | extern "C" { \ | |
63 | \ | |
64 | __attribute((weak)) extern OpenTracingMakeTracerFactoryType* const \ | |
65 | OpenTracingMakeTracerFactory; \ | |
66 | \ | |
67 | OpenTracingMakeTracerFactoryType* const OpenTracingMakeTracerFactory = X; \ | |
68 | } // extern "C" | |
69 | ||
70 | #endif | |
71 | ||
72 | namespace opentracing { | |
73 | BEGIN_OPENTRACING_ABI_NAMESPACE | |
74 | // Returns the std::error_category class used for opentracing dynamic loading | |
75 | // errors. | |
76 | // | |
77 | // See | |
78 | // http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-1.html | |
79 | // https://ned14.github.io/boost.outcome/md_doc_md_03-tutorial_b.html | |
80 | OPENTRACING_API const std::error_category& dynamic_load_error_category(); | |
81 | ||
82 | // `dynamic_load_failure_error` occurs when dynamically loading a tracer library | |
83 | // fails. Possible reasons could be the library doesn't exist or it is missing | |
84 | // the required symbols. | |
85 | const std::error_code dynamic_load_failure_error(1, | |
86 | dynamic_load_error_category()); | |
87 | ||
88 | // `dynamic_load_not_supported_error` means dynamic loading of tracing libraries | |
89 | // is not supported for the platform used. | |
90 | const std::error_code dynamic_load_not_supported_error( | |
91 | 2, dynamic_load_error_category()); | |
92 | ||
93 | // `incompatible_library_versions_error` occurs if the tracing library | |
94 | // dynamically loaded uses an incompatible version of opentracing. | |
95 | const std::error_code incompatible_library_versions_error( | |
96 | 3, dynamic_load_error_category()); | |
97 | ||
98 | class DynamicLibraryHandle { | |
99 | public: | |
100 | virtual ~DynamicLibraryHandle() = default; | |
101 | }; | |
102 | ||
103 | // Provides a handle to a dynamically loaded tracing library that can be used | |
104 | // to create tracers. | |
105 | // | |
106 | // Note: The handle must not be destructed while any associated tracers are | |
107 | // still in use. | |
108 | // | |
109 | // See TracerFactory | |
110 | class DynamicTracingLibraryHandle { | |
111 | public: | |
112 | DynamicTracingLibraryHandle() = default; | |
113 | ||
114 | DynamicTracingLibraryHandle( | |
115 | std::unique_ptr<const TracerFactory>&& tracer_factory, | |
116 | std::unique_ptr<DynamicLibraryHandle>&& dynamic_library_handle) noexcept; | |
117 | ||
118 | const TracerFactory& tracer_factory() const noexcept { | |
119 | return *tracer_factory_; | |
120 | } | |
121 | ||
122 | private: | |
123 | std::unique_ptr<DynamicLibraryHandle> dynamic_library_handle_; | |
124 | std::unique_ptr<const TracerFactory> tracer_factory_; | |
125 | }; | |
126 | ||
127 | // Dynamically loads a tracing library and returns a handle that can be used | |
128 | // to create tracers. | |
129 | // | |
130 | // Example: | |
131 | // std::string error_message; | |
132 | // auto handle_maybe = DynamicallyLoadTracingLibrary( | |
133 | // "libtracing_vendor.so", | |
134 | // error_message); | |
135 | // if (handle_maybe) { | |
136 | // // success | |
137 | // auto& tracer_factory = handle_maybe->tracer_factory(); | |
138 | // } else { | |
139 | // // failure | |
140 | // std::error_code error = handle_maybe.error(); | |
141 | // // `error_message` may also contain a more descriptive message | |
142 | // } | |
143 | // | |
144 | // See DynamicTracingLibraryHandle, TracerFactory | |
145 | OPENTRACING_API expected<DynamicTracingLibraryHandle> | |
146 | DynamicallyLoadTracingLibrary(const char* shared_library, | |
147 | std::string& error_message) noexcept; | |
148 | END_OPENTRACING_ABI_NAMESPACE | |
149 | } // namespace opentracing | |
150 | ||
151 | #endif // OPENTRACING_DYNAMIC_LOAD_H |