Files
Max Desiatov e054a884ef Add support for SwiftWasm with CI and tests (#191)
WebAssembly support for atomics and multi-threading isn't fully standardized yet, and it not supported in SwiftWasm at the moment. Because of this Dispatch is unavailable, and all Combine-related Foundation stuff is unavailable too. Tests related to this are disabled. Locking functions are replaced with no-op shims.
2020-11-02 22:02:39 +00:00

129 lines
2.4 KiB
Swift

//
// TestingThreadSafety.swift
//
//
// Created by Sergej Jaskiewicz on 11.06.2019.
//
#if !WASI
import Dispatch
#endif
import Foundation
import XCTest
func race(times: Int = 100, _ bodies: () -> Void...) {
#if WASI
for body in bodies {
for _ in 0..<times {
body()
}
}
#else
DispatchQueue.concurrentPerform(iterations: bodies.count) {
for _ in 0..<times {
bodies[$0]()
}
}
#endif
}
final class Atomic<Value> {
#if !WASI
let lock = NSLock()
#endif
private var _value: Value
init(_ initialValue: Value) {
_value = initialValue
}
var value: Value {
#if !WASI
lock.lock()
defer { lock.unlock() }
#endif
return _value
}
func set(_ newValue: Value) {
#if !WASI
lock.lock()
defer { lock.unlock() }
#endif
_value = newValue
}
func `do`(_ body: (inout Value) throws -> Void) rethrows {
#if !WASI
lock.lock()
defer { lock.unlock() }
#endif
try body(&_value)
}
}
extension Atomic where Value: Equatable {
static func == (lhs: Atomic<Value>, rhs: Value) -> Bool {
return lhs.value == rhs
}
static func == (lhs: Value, rhs: Atomic<Value>) -> Bool {
return rhs == lhs
}
}
extension Atomic where Value: AdditiveArithmetic {
static func += (lhs: Atomic<Value>, rhs: Value) {
lhs.do { $0 += rhs }
}
static func -= (lhs: Atomic<Value>, rhs: Value) {
lhs.do { $0 -= rhs }
}
}
extension Atomic where Value: Collection {
var count: Int {
return value.count
}
var isEmpty: Bool {
return value.isEmpty
}
subscript(index: Value.Index) -> Value.Element {
return value[index]
}
func dropFirst(_ k: Int = 1) -> Value.SubSequence {
return value.dropFirst(k)
}
func dropLast(_ k: Int = 1) -> Value.SubSequence {
return value.dropLast(k)
}
}
extension Atomic where Value: RangeReplaceableCollection {
func append(_ element: Value.Element) {
self.do {
$0.append(element)
}
}
}
func XCTAssertEqual<Value: Equatable>(
_ expression1: @autoclosure () throws -> Atomic<Value>,
_ expression2: @autoclosure () throws -> Value,
_ message: @autoclosure () -> String = ""
) {
XCTAssertEqual(try expression1().value, try expression2(), message())
}