summaryrefslogtreecommitdiffstats
path: root/include/opentracing/dynamic_load.h
blob: f8f9837688b3c036ddd25558112c6e9120086a3c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#ifndef OPENTRACING_DYNAMIC_LOAD_H
#define OPENTRACING_DYNAMIC_LOAD_H

#include <opentracing/config.h>
#include <opentracing/symbols.h>
#include <opentracing/tracer.h>
#include <opentracing/tracer_factory.h>
#include <opentracing/version.h>
#include <system_error>

// OpenTracingMakeTracerFactory provides a common hook that can be used to
// create an TracerFactory from a dynamically loaded library. Users should
// prefer to use the function DynamicallyLoadTracingLibrary over calling it
// directly.
//
// It takes the parameter `opentracing_version` and `opentracing_abi_version`
// representing the version of opentracing used by the caller. Upon success it
// returns the code `0` and sets `tracer_factory` to point to an instance of
// TracerFactory.
//
// On failure, it returns a non-zero error code and sets `error_category` to
// point to an std::error_category for the returned error code.
//
// Example usage,
//
//   const std::error_category* error_category = nullptr;
//   std::string error_message;
//   opentracing::TracerFactory* tracer_factory = nullptr;
//   int rcode = (*OpenTracingMakeTracerFactory)(
//                  OPENTRACING_VERSION,
//                  OPENTRACING_ABI_VERSION,
//                  &static_cast<const void*>(error_category),
//                  static_cast<void*>(&error_message),
//                  &static_cast<void*>(tracer_factory));
//   if (rcode == 0) {
//      // success
//      assert(tracer_factory != nullptr);
//   } else {
//      // failure
//      assert(error_category != nullptr);
//      std::error_code error{rcode, *error_category};
//   }
using OpenTracingMakeTracerFactoryType = int(
    const char* opentracing_version, const char* opentracing_abi_version,
    const void** error_category, void* error_message, void** tracer_factory);

#ifdef WIN32

#define OPENTRACING_DECLARE_IMPL_FACTORY(X)                                 \
  extern "C" {                                                              \
                                                                            \
  extern __declspec(dllexport)                                              \
      OpenTracingMakeTracerFactoryType* const OpenTracingMakeTracerFactory; \
                                                                            \
  __declspec(selectany) OpenTracingMakeTracerFactoryType* const             \
      OpenTracingMakeTracerFactory = X;                                     \
  }  // extern "C"

#else

#define OPENTRACING_DECLARE_IMPL_FACTORY(X)                                 \
  extern "C" {                                                              \
                                                                            \
  __attribute((weak)) extern OpenTracingMakeTracerFactoryType* const        \
      OpenTracingMakeTracerFactory;                                         \
                                                                            \
  OpenTracingMakeTracerFactoryType* const OpenTracingMakeTracerFactory = X; \
  }  // extern "C"

#endif

namespace opentracing {
BEGIN_OPENTRACING_ABI_NAMESPACE
// Returns the std::error_category class used for opentracing dynamic loading
// errors.
//
// See
//   http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-1.html
//   https://ned14.github.io/boost.outcome/md_doc_md_03-tutorial_b.html
OPENTRACING_API const std::error_category& dynamic_load_error_category();

// `dynamic_load_failure_error` occurs when dynamically loading a tracer library
// fails. Possible reasons could be the library doesn't exist or it is missing
// the required symbols.
const std::error_code dynamic_load_failure_error(1,
                                                 dynamic_load_error_category());

// `dynamic_load_not_supported_error` means dynamic loading of tracing libraries
// is not supported for the platform used.
const std::error_code dynamic_load_not_supported_error(
    2, dynamic_load_error_category());

// `incompatible_library_versions_error` occurs if the tracing library
// dynamically loaded uses an incompatible version of opentracing.
const std::error_code incompatible_library_versions_error(
    3, dynamic_load_error_category());

class DynamicLibraryHandle {
 public:
  virtual ~DynamicLibraryHandle() = default;
};

// Provides a handle to a dynamically loaded tracing library that can be used
// to create tracers.
//
// Note: The handle must not be destructed while any associated tracers are
// still in use.
//
// See TracerFactory
class DynamicTracingLibraryHandle {
 public:
  DynamicTracingLibraryHandle() = default;

  DynamicTracingLibraryHandle(
      std::unique_ptr<const TracerFactory>&& tracer_factory,
      std::unique_ptr<DynamicLibraryHandle>&& dynamic_library_handle) noexcept;

  const TracerFactory& tracer_factory() const noexcept {
    return *tracer_factory_;
  }

 private:
  std::unique_ptr<DynamicLibraryHandle> dynamic_library_handle_;
  std::unique_ptr<const TracerFactory> tracer_factory_;
};

// Dynamically loads a tracing library and returns a handle that can be used
// to create tracers.
//
// Example:
//   std::string error_message;
//   auto handle_maybe = DynamicallyLoadTracingLibrary(
//                                 "libtracing_vendor.so",
//                                 error_message);
//   if (handle_maybe) {
//      // success
//      auto& tracer_factory = handle_maybe->tracer_factory();
//   } else {
//      // failure
//      std::error_code error = handle_maybe.error();
//      // `error_message` may also contain a more descriptive message
//   }
//
// See DynamicTracingLibraryHandle, TracerFactory
OPENTRACING_API expected<DynamicTracingLibraryHandle>
DynamicallyLoadTracingLibrary(const char* shared_library,
                              std::string& error_message) noexcept;
END_OPENTRACING_ABI_NAMESPACE
}  // namespace opentracing

#endif  // OPENTRACING_DYNAMIC_LOAD_H