-
Notifications
You must be signed in to change notification settings - Fork 155
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
409f18b
commit 33e1771
Showing
4 changed files
with
216 additions
and
21 deletions.
There are no files selected for viewing
198 changes: 198 additions & 0 deletions
198
Sources/Exporters/OpenTelemetryProtocolHttp/Internal/Locks.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the Swift Metrics API open source project | ||
// | ||
// Copyright (c) 2018-2019 Apple Inc. and the Swift Metrics API project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// See CONTRIBUTORS.txt for the list of Swift Metrics API project authors | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the SwiftNIO open source project | ||
// | ||
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) | ||
import Darwin | ||
#else | ||
import Glibc | ||
#endif | ||
|
||
/// A threading lock based on `libpthread` instead of `libdispatch`. | ||
/// | ||
/// This object provides a lock on top of a single `pthread_mutex_t`. This kind | ||
/// of lock is safe to use with `libpthread`-based threading models, such as the | ||
/// one used by NIO. | ||
internal final class Lock { | ||
fileprivate let mutex: UnsafeMutablePointer<pthread_mutex_t> = UnsafeMutablePointer.allocate(capacity: 1) | ||
|
||
/// Create a new lock. | ||
public init() { | ||
let err = pthread_mutex_init(self.mutex, nil) | ||
precondition(err == 0, "pthread_mutex_init failed with error \(err)") | ||
} | ||
|
||
deinit { | ||
let err = pthread_mutex_destroy(self.mutex) | ||
precondition(err == 0, "pthread_mutex_destroy failed with error \(err)") | ||
self.mutex.deallocate() | ||
} | ||
|
||
/// Acquire the lock. | ||
/// | ||
/// Whenever possible, consider using `withLock` instead of this method and | ||
/// `unlock`, to simplify lock handling. | ||
public func lock() { | ||
let err = pthread_mutex_lock(self.mutex) | ||
precondition(err == 0, "pthread_mutex_lock failed with error \(err)") | ||
} | ||
|
||
/// Release the lock. | ||
/// | ||
/// Whenever possible, consider using `withLock` instead of this method and | ||
/// `lock`, to simplify lock handling. | ||
public func unlock() { | ||
let err = pthread_mutex_unlock(self.mutex) | ||
precondition(err == 0, "pthread_mutex_unlock failed with error \(err)") | ||
} | ||
} | ||
|
||
extension Lock { | ||
/// Acquire the lock for the duration of the given block. | ||
/// | ||
/// This convenience method should be preferred to `lock` and `unlock` in | ||
/// most situations, as it ensures that the lock will be released regardless | ||
/// of how `body` exits. | ||
/// | ||
/// - Parameter body: The block to execute while holding the lock. | ||
/// - Returns: The value returned by the block. | ||
@inlinable | ||
internal func withLock<T>(_ body: () throws -> T) rethrows -> T { | ||
self.lock() | ||
defer { | ||
self.unlock() | ||
} | ||
return try body() | ||
} | ||
|
||
// specialise Void return (for performance) | ||
@inlinable | ||
internal func withLockVoid(_ body: () throws -> Void) rethrows { | ||
try self.withLock(body) | ||
} | ||
} | ||
|
||
/// A threading lock based on `libpthread` instead of `libdispatch`. | ||
/// | ||
/// This object provides a lock on top of a single `pthread_mutex_t`. This kind | ||
/// of lock is safe to use with `libpthread`-based threading models, such as the | ||
/// one used by NIO. | ||
internal final class ReadWriteLock { | ||
fileprivate let rwlock: UnsafeMutablePointer<pthread_rwlock_t> = UnsafeMutablePointer.allocate(capacity: 1) | ||
|
||
/// Create a new lock. | ||
public init() { | ||
let err = pthread_rwlock_init(self.rwlock, nil) | ||
precondition(err == 0, "pthread_rwlock_init failed with error \(err)") | ||
} | ||
|
||
deinit { | ||
let err = pthread_rwlock_destroy(self.rwlock) | ||
precondition(err == 0, "pthread_rwlock_destroy failed with error \(err)") | ||
self.rwlock.deallocate() | ||
} | ||
|
||
/// Acquire a reader lock. | ||
/// | ||
/// Whenever possible, consider using `withLock` instead of this method and | ||
/// `unlock`, to simplify lock handling. | ||
public func lockRead() { | ||
let err = pthread_rwlock_rdlock(self.rwlock) | ||
precondition(err == 0, "pthread_rwlock_rdlock failed with error \(err)") | ||
} | ||
|
||
/// Acquire a writer lock. | ||
/// | ||
/// Whenever possible, consider using `withLock` instead of this method and | ||
/// `unlock`, to simplify lock handling. | ||
public func lockWrite() { | ||
let err = pthread_rwlock_wrlock(self.rwlock) | ||
precondition(err == 0, "pthread_rwlock_wrlock failed with error \(err)") | ||
} | ||
|
||
/// Release the lock. | ||
/// | ||
/// Whenever possible, consider using `withLock` instead of this method and | ||
/// `lock`, to simplify lock handling. | ||
public func unlock() { | ||
let err = pthread_rwlock_unlock(self.rwlock) | ||
precondition(err == 0, "pthread_rwlock_unlock failed with error \(err)") | ||
} | ||
} | ||
|
||
extension ReadWriteLock { | ||
/// Acquire the reader lock for the duration of the given block. | ||
/// | ||
/// This convenience method should be preferred to `lock` and `unlock` in | ||
/// most situations, as it ensures that the lock will be released regardless | ||
/// of how `body` exits. | ||
/// | ||
/// - Parameter body: The block to execute while holding the lock. | ||
/// - Returns: The value returned by the block. | ||
@inlinable | ||
internal func withReaderLock<T>(_ body: () throws -> T) rethrows -> T { | ||
self.lockRead() | ||
defer { | ||
self.unlock() | ||
} | ||
return try body() | ||
} | ||
|
||
/// Acquire the writer lock for the duration of the given block. | ||
/// | ||
/// This convenience method should be preferred to `lock` and `unlock` in | ||
/// most situations, as it ensures that the lock will be released regardless | ||
/// of how `body` exits. | ||
/// | ||
/// - Parameter body: The block to execute while holding the lock. | ||
/// - Returns: The value returned by the block. | ||
@inlinable | ||
internal func withWriterLock<T>(_ body: () throws -> T) rethrows -> T { | ||
self.lockWrite() | ||
defer { | ||
self.unlock() | ||
} | ||
return try body() | ||
} | ||
|
||
// specialise Void return (for performance) | ||
@inlinable | ||
internal func withReaderLockVoid(_ body: () throws -> Void) rethrows { | ||
try self.withReaderLock(body) | ||
} | ||
|
||
// specialise Void return (for performance) | ||
@inlinable | ||
internal func withWriterLockVoid(_ body: () throws -> Void) rethrows { | ||
try self.withWriterLock(body) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters