Skip to content

Commit

Permalink
Allow Locked to store non-Sendable elements (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
atdrendel authored Nov 3, 2022
1 parent ab58ad5 commit 32f43e5
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 13 deletions.
12 changes: 7 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
name: CI

on: push

jobs:
test:
runs-on: macos-12

steps:
- uses: actions/checkout@v2
# Available environments: https://github.com/actions/virtual-environments/blob/main/images/macos/macos-12-Readme.md#xcode
- run: xcversion select 13.4
- run: swift package resolve
- run: swift test --skip-update
- uses: actions/checkout@v3
- name: Select Xcode 14
run: sudo xcode-select -s /Applications/Xcode_14.1.app
- name: Test
run: swift test
8 changes: 6 additions & 2 deletions Sources/Synchronized/Locked.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

public struct Locked<Element: Sendable>: @unchecked Sendable {
public struct Locked<Element> {
private final class Lock: ManagedBuffer<Element, os_unfair_lock> {
deinit {
withUnsafeMutablePointerToElements { lock in
Expand All @@ -13,7 +13,9 @@ public struct Locked<Element: Sendable>: @unchecked Sendable {

public init(_ element: Element) {
buffer = Lock.create(minimumCapacity: 1) { buffer in
buffer.withUnsafeMutablePointerToElements { $0.initialize(to: os_unfair_lock()) }
buffer.withUnsafeMutablePointerToElements {
$0.initialize(to: os_unfair_lock())
}
return element
}
}
Expand All @@ -26,3 +28,5 @@ public struct Locked<Element: Sendable>: @unchecked Sendable {
}
}
}

extension Locked: @unchecked Sendable where Element: Sendable {}
11 changes: 11 additions & 0 deletions Tests/SynchronizedTests/SynchronizedTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ final class SynchronizedTests: XCTestCase {
XCTAssertThrowsError(try lock.locked { throw TestError.locked })
}

func testLockedElementDoesNotNeedToBeSendable() {
class ThreadUnsafe {
var name: String
init(name: String) { self.name = name }
}

let unsafe = Locked(ThreadUnsafe(name: "something"))
unsafe.access { $0.name = "else" }
XCTAssertEqual("else", unsafe.access { $0.name })
}

func testCounterWithLock() {
let iterations = 100_000
let counter = Counter()
Expand Down
20 changes: 14 additions & 6 deletions bin/format.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
#!/usr/bin/env bash
# https://sharats.me/posts/shell-script-best-practices/

set -e
set -o errexit
set -o nounset
set -o pipefail
if [[ "${TRACE-0}" == "1" ]]; then
set -o xtrace
fi

SELF=`realpath $0`
DIR=`dirname $SELF`
DEV_DIR=`echo ${DIR%/*}`
if [[ "${1-}" =~ ^-*h(elp)?$ ]]; then
echo 'Usage: ./format.sh'
exit
fi

pushd "$DEV_DIR" &>/dev/null
DIR=`dirname "$0"`
pushd "$DIR/.." &>/dev/null

if command -v swiftformat >/dev/null 2>&1; then
swiftformat --quiet --config .swiftformat .
else
echo "warning: Install swiftformat by running 'brew install swiftformat'"
echo "warning: Install swiftformat by running 'brew install swiftformat'" >&2
fi

popd &>/dev/null

0 comments on commit 32f43e5

Please sign in to comment.