@@ -7,6 +7,7 @@ import Foundation
7
7
import OpenTelemetryApi
8
8
9
9
public class TracerProviderSdk : TracerProvider {
10
+ private var tracerLock = pthread_rwlock_t ( )
10
11
private var tracerProvider = [ InstrumentationLibraryInfo: TracerSdk] ( )
11
12
internal var sharedState : TracerSharedState
12
13
internal static let emptyName = " unknown "
@@ -19,6 +20,7 @@ public class TracerProviderSdk: TracerProvider {
19
20
sampler: Sampler = Samplers . parentBased ( root: Samplers . alwaysOn) ,
20
21
spanProcessors: [ SpanProcessor ] = [ ] )
21
22
{
23
+ pthread_rwlock_init ( & tracerLock, nil )
22
24
sharedState = TracerSharedState ( clock: clock,
23
25
idGenerator: idGenerator,
24
26
resource: resource,
@@ -27,6 +29,10 @@ public class TracerProviderSdk: TracerProvider {
27
29
spanProcessors: spanProcessors)
28
30
}
29
31
32
+ deinit {
33
+ pthread_rwlock_destroy ( & tracerLock)
34
+ }
35
+
30
36
public func get( instrumentationName: String , instrumentationVersion: String ? = nil ) -> Tracer {
31
37
if sharedState. hasBeenShutdown {
32
38
return DefaultTracer . instance
@@ -39,20 +45,24 @@ public class TracerProviderSdk: TracerProvider {
39
45
instrumentationName = TracerProviderSdk . emptyName
40
46
}
41
47
let instrumentationLibraryInfo = InstrumentationLibraryInfo ( name: instrumentationName, version: instrumentationVersion ?? " " )
42
- if let tracer = tracerProvider [ instrumentationLibraryInfo] {
43
- return tracer
44
- } else {
45
- // Re-check if the value was added since the previous check, this can happen if multiple
46
- // threads try to access the same named tracer during the same time. This way we ensure that
47
- // we create only one TracerSdk per name.
48
- if let tracer = tracerProvider [ instrumentationLibraryInfo] {
49
- // A different thread already added the named Tracer, just reuse.
50
- return tracer
48
+
49
+ if pthread_rwlock_rdlock ( & tracerLock) == 0 {
50
+ let existingTracer = tracerProvider [ instrumentationLibraryInfo]
51
+ pthread_rwlock_unlock ( & tracerLock)
52
+
53
+ if existingTracer != nil {
54
+ return existingTracer!
51
55
}
52
- let tracer = TracerSdk ( sharedState: sharedState, instrumentationLibraryInfo: instrumentationLibraryInfo)
56
+ }
57
+
58
+ let tracer = TracerSdk ( sharedState: sharedState, instrumentationLibraryInfo: instrumentationLibraryInfo)
59
+
60
+ if pthread_rwlock_wrlock ( & tracerLock) == 0 {
53
61
tracerProvider [ instrumentationLibraryInfo] = tracer
54
- return tracer
62
+ pthread_rwlock_unlock ( & tracerLock )
55
63
}
64
+
65
+ return tracer
56
66
}
57
67
58
68
/// Returns the active Clock.
0 commit comments