Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Testing fixing approaches for tsan RxAtomic issues #1860

Merged
merged 12 commits into from
Jan 31, 2019
57 changes: 46 additions & 11 deletions Platform/AtomicInt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,60 @@

import RxAtomic

typealias AtomicInt = RxAtomic.AtomicInt

extension AtomicInt {
typealias RxAtomicInt = RxAtomic.AtomicInt
final class AtomicInt {

var value: RxAtomicInt

@inline(__always)
init() {
self.value = RxAtomic.AtomicInt()
RxAtomicInt.initialize(&self.value, 0)
}

@inline(__always)
init(_ initialValue: Int32) {
self.init()
self.initialize(initialValue)
self.value = RxAtomic.AtomicInt()
RxAtomicInt.initialize(&self.value, initialValue)
}


@discardableResult
@inline(__always)
func add(_ value: Int32) -> Int32 {
return RxAtomicInt.add(&self.value, value)
}

@discardableResult
@inline(__always)
func sub(_ value: Int32) -> Int32 {
return RxAtomicInt.sub(&self.value, value)
}

@discardableResult
@inline(__always)
func fetchOr(_ mask: Int32) -> Int32 {
return RxAtomicInt.fetchOr(&self.value, mask)
}

@inline(__always)
func load() -> Int32 {
return RxAtomicInt.load(&self.value)
}

@discardableResult
mutating func increment() -> Int32 {
@inline(__always)
func increment() -> Int32 {
return self.add(1)
}

@discardableResult
mutating func decrement() -> Int32 {
@inline(__always)
func decrement() -> Int32 {
return self.sub(1)
}

mutating func isFlagSet(_ mask: Int32) -> Bool {

@inline(__always)
func isFlagSet(_ mask: Int32) -> Bool {
return (self.load() & mask) != 0
}
}
Expand Down
8 changes: 8 additions & 0 deletions Rx.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2675,6 +2675,7 @@
};
C8165ABB21891AFF00494BEF = {
CreatedOnToolsVersion = 10.1;
LastSwiftMigration = 1010;
};
C83508C21C386F6F0027C24C = {
CreatedOnToolsVersion = 7.2;
Expand Down Expand Up @@ -3832,6 +3833,7 @@
C8165AC121891B0000494BEF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
Expand All @@ -3842,12 +3844,15 @@
PRODUCT_BUNDLE_IDENTIFIER = io.rx.RxAtomic;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.2;
};
name = Debug;
};
C8165AC221891B0000494BEF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
Expand All @@ -3858,12 +3863,14 @@
PRODUCT_BUNDLE_IDENTIFIER = io.rx.RxAtomic;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
};
name = Release;
};
C8165AC321891B0000494BEF /* Release-Tests */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
Expand All @@ -3874,6 +3881,7 @@
PRODUCT_BUNDLE_IDENTIFIER = io.rx.RxAtomic;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
};
name = "Release-Tests";
};
Expand Down
10 changes: 5 additions & 5 deletions RxAtomic/include/RxAtomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,27 @@

#define Atomic(swift_type, llvm_type) \
typedef struct { volatile atomic_##llvm_type atom; } Atomic##swift_type;\
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.initialize(self:_:)) \
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.initialize(_:_:)) \
void Atomic##swift_type##_Initialize(Atomic##swift_type * _Nonnull self, llvm_type value) { \
atomic_init(&self->atom, value);\
}\
\
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.load(self:)) \
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.load(_:)) \
llvm_type Atomic##swift_type##_Load(Atomic##swift_type * _Nonnull self) { \
return atomic_load(&self->atom);\
}\
\
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.fetchOr(self:_:)) \
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.fetchOr(_:_:)) \
llvm_type Atomic##swift_type##_FetchOr(Atomic##swift_type * _Nonnull self, llvm_type mask) { \
return atomic_fetch_or(&self->atom, mask);\
}\
\
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.add(self:_:)) \
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.add(_:_:)) \
llvm_type Atomic##swift_type##_Add(Atomic##swift_type * _Nonnull self, llvm_type value) { \
return atomic_fetch_add(&self->atom, value);\
}\
\
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.sub(self:_:)) \
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.sub(_:_:)) \
llvm_type Atomic##swift_type##_Sub(Atomic##swift_type * _Nonnull self, llvm_type value) { \
return atomic_fetch_sub(&self->atom, value);\
}\
Expand Down
10 changes: 5 additions & 5 deletions Sources/RxAtomic/include/RxAtomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,27 @@

#define Atomic(swift_type, llvm_type) \
typedef struct { volatile atomic_##llvm_type atom; } Atomic##swift_type;\
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.initialize(self:_:)) \
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.initialize(_:_:)) \
void Atomic##swift_type##_Initialize(Atomic##swift_type * _Nonnull self, llvm_type value) { \
atomic_init(&self->atom, value);\
}\
\
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.load(self:)) \
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.load(_:)) \
llvm_type Atomic##swift_type##_Load(Atomic##swift_type * _Nonnull self) { \
return atomic_load(&self->atom);\
}\
\
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.fetchOr(self:_:)) \
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.fetchOr(_:_:)) \
llvm_type Atomic##swift_type##_FetchOr(Atomic##swift_type * _Nonnull self, llvm_type mask) { \
return atomic_fetch_or(&self->atom, mask);\
}\
\
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.add(self:_:)) \
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.add(_:_:)) \
llvm_type Atomic##swift_type##_Add(Atomic##swift_type * _Nonnull self, llvm_type value) { \
return atomic_fetch_add(&self->atom, value);\
}\
\
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.sub(self:_:)) \
static __inline__ __attribute__((__always_inline__)) SWIFT_NAME(Atomic##swift_type.sub(_:_:)) \
llvm_type Atomic##swift_type##_Sub(Atomic##swift_type * _Nonnull self, llvm_type value) { \
return atomic_fetch_sub(&self->atom, value);\
}\
Expand Down
22 changes: 11 additions & 11 deletions Tests/RxSwiftTests/AtomicTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ public class AtomicTests: XCTestCase {}

extension AtomicTests {
func testAtomicInitialValue() {
var atomic = AtomicPrimitive(4)
let atomic = AtomicPrimitive(4)
XCTAssertEqual(atomic.load(), 4)
}

func testAtomicInitialDefaultValue() {
var atomic = AtomicPrimitive()
let atomic = AtomicPrimitive()
XCTAssertEqual(atomic.load(), 0)
}
}
Expand All @@ -64,7 +64,7 @@ extension AtomicTests {
private static let concurrency = 8

func testFetchOrSetsBits() {
var atomic = AtomicPrimitive()
let atomic = AtomicPrimitive()
XCTAssertEqual(atomic.fetchOr(0), 0)
XCTAssertEqual(atomic.fetchOr(4), 0)
XCTAssertEqual(atomic.fetchOr(8), 4)
Expand All @@ -74,9 +74,9 @@ extension AtomicTests {
func testFetchOrConcurrent() {
let queue = DispatchQueue.global(qos: .default)
for _ in 0 ..< AtomicTests.repeatCount {
var atomic = AtomicPrimitive(0)
let atomic = AtomicPrimitive(0)

var counter = AtomicPrimitive(0)
let counter = AtomicPrimitive(0)

var expectations = [XCTestExpectation]()

Expand Down Expand Up @@ -105,7 +105,7 @@ extension AtomicTests {
}

func testAdd() {
var atomic = AtomicPrimitive(0)
let atomic = AtomicPrimitive(0)
XCTAssertEqual(atomic.add(4), 0)
XCTAssertEqual(atomic.add(3), 4)
XCTAssertEqual(atomic.add(10), 7)
Expand All @@ -114,9 +114,9 @@ extension AtomicTests {
func testAddConcurrent() {
let queue = DispatchQueue.global(qos: .default)
for _ in 0 ..< AtomicTests.repeatCount {
var atomic = AtomicPrimitive(0)
let atomic = AtomicPrimitive(0)

var counter = AtomicPrimitive(0)
let counter = AtomicPrimitive(0)

var expectations = [XCTestExpectation]()

Expand Down Expand Up @@ -144,7 +144,7 @@ extension AtomicTests {
}

func testSub() {
var atomic = AtomicPrimitive(0)
let atomic = AtomicPrimitive(0)
XCTAssertEqual(atomic.sub(-4), 0)
XCTAssertEqual(atomic.sub(-3), 4)
XCTAssertEqual(atomic.sub(-10), 7)
Expand All @@ -153,9 +153,9 @@ extension AtomicTests {
func testSubConcurrent() {
let queue = DispatchQueue.global(qos: .default)
for _ in 0 ..< AtomicTests.repeatCount {
var atomic = AtomicPrimitive(0)
let atomic = AtomicPrimitive(0)

var counter = AtomicPrimitive(0)
let counter = AtomicPrimitive(0)

var expectations = [XCTestExpectation]()

Expand Down
2 changes: 1 addition & 1 deletion Tests/RxSwiftTests/DisposableTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ extension DisposableTest {
}

func testSingleAssignmentDisposable_stress() {
var count = AtomicInt(0)
let count = AtomicInt(0)

let queue = DispatchQueue(label: "dispose", qos: .default, attributes: [.concurrent])

Expand Down
4 changes: 2 additions & 2 deletions Tests/RxSwiftTests/Observable+ObserveOnTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ extension ObservableObserveOnTest {
}

func testObserveOnDispatchQueue_DispatchQueueSchedulerIsSerial() {
var numberOfConcurrentEvents = AtomicInt(0)
var numberOfExecutions = AtomicInt(0)
let numberOfConcurrentEvents = AtomicInt(0)
let numberOfExecutions = AtomicInt(0)
runDispatchQueueSchedulerTests { scheduler in
XCTAssert(Resources.numberOfSerialDispatchQueueObservables == 0)
let action = { (s: Void) -> Disposable in
Expand Down