Skip to content

Commit 1809484

Browse files
authored
Merge pull request ReactiveCocoa#26 from Lightricks/feature/tests-tsan-fix
ReactiveObjCTests: fix TSan issues.
2 parents e1da278 + 9d538c9 commit 1809484

File tree

6 files changed

+51
-42
lines changed

6 files changed

+51
-42
lines changed

ReactiveObjCTests/RACSchedulerSpec.m

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010
@import Nimble;
1111

1212
#import "RACScheduler.h"
13+
14+
#import <ReactiveObjC/EXTScope.h>
15+
#import <stdatomic.h>
16+
1317
#import "RACScheduler+Private.h"
1418
#import "RACQueueScheduler+Subclass.h"
1519
#import "RACDisposable.h"
16-
#import <ReactiveObjC/EXTScope.h>
1720
#import "RACTestExampleScheduler.h"
18-
#import <libkern/OSAtomic.h>
1921

2022
// This shouldn't be used directly. Use the `expectCurrentSchedulers` block
2123
// below instead.
@@ -143,8 +145,8 @@ static void expectCurrentSchedulersInner(NSArray *schedulers, NSMutableArray *cu
143145
});
144146

145147
qck_it(@"should cancel scheduled blocks when disposed", ^{
146-
__block BOOL firstBlockRan = NO;
147-
__block BOOL secondBlockRan = NO;
148+
__block atomic_bool firstBlockRan = NO;
149+
__block atomic_bool secondBlockRan = NO;
148150

149151
// Start off on the scheduler so the enqueued blocks won't run until we
150152
// return.
@@ -167,7 +169,7 @@ static void expectCurrentSchedulersInner(NSArray *schedulers, NSMutableArray *cu
167169
});
168170

169171
qck_it(@"should schedule future blocks", ^{
170-
__block BOOL done = NO;
172+
__block atomic_bool done = NO;
171173

172174
[scheduler after:futureDate() schedule:^{
173175
done = YES;
@@ -178,8 +180,8 @@ static void expectCurrentSchedulersInner(NSArray *schedulers, NSMutableArray *cu
178180
});
179181

180182
qck_it(@"should cancel future blocks when disposed", ^{
181-
__block BOOL firstBlockRan = NO;
182-
__block BOOL secondBlockRan = NO;
183+
__block atomic_bool firstBlockRan = NO;
184+
__block atomic_bool secondBlockRan = NO;
183185

184186
NSDate *date = futureDate();
185187
RACDisposable *disposable = [scheduler after:date schedule:^{
@@ -199,7 +201,7 @@ static void expectCurrentSchedulersInner(NSArray *schedulers, NSMutableArray *cu
199201
});
200202

201203
qck_it(@"should schedule recurring blocks", ^{
202-
__block NSUInteger count = 0;
204+
__block atomic_uint count = 0;
203205

204206
RACDisposable *disposable = [scheduler after:[NSDate date] repeatingEvery:0.05 withLeeway:0 schedule:^{
205207
count++;
@@ -259,8 +261,8 @@ static void expectCurrentSchedulersInner(NSArray *schedulers, NSMutableArray *cu
259261
});
260262

261263
qck_it(@"should execute scheduled blocks immediately if it's in a scheduler already", ^{
262-
__block BOOL done = NO;
263-
__block BOOL executedImmediately = NO;
264+
__block atomic_bool done = NO;
265+
__block atomic_bool executedImmediately = NO;
264266

265267
[[RACScheduler scheduler] schedule:^{
266268
[RACScheduler.subscriptionScheduler schedule:^{
@@ -366,12 +368,12 @@ static void expectCurrentSchedulersInner(NSArray *schedulers, NSMutableArray *cu
366368
});
367369

368370
qck_it(@"should reschedule when invoked asynchronously", ^{
369-
__block NSUInteger count = 0;
371+
__block atomic_uint count = 0;
370372

371373
RACScheduler *asynchronousScheduler = [RACScheduler scheduler];
372374
[RACScheduler.mainThreadScheduler scheduleRecursiveBlock:^(void (^recurse)(void)) {
373375
[asynchronousScheduler after:[NSDate dateWithTimeIntervalSinceNow:0.01] schedule:^{
374-
NSUInteger thisCount = ++count;
376+
atomic_uint thisCount = ++count;
375377
if (thisCount < 3) {
376378
recurse();
377379

@@ -386,7 +388,7 @@ static void expectCurrentSchedulersInner(NSArray *schedulers, NSMutableArray *cu
386388
});
387389

388390
qck_it(@"shouldn't reschedule itself when disposed", ^{
389-
__block NSUInteger count = 0;
391+
__block atomic_uint count = 0;
390392
__block RACDisposable *disposable = [RACScheduler.mainThreadScheduler scheduleRecursiveBlock:^(void (^recurse)(void)) {
391393
++count;
392394

@@ -409,7 +411,7 @@ static void expectCurrentSchedulersInner(NSArray *schedulers, NSMutableArray *cu
409411
});
410412

411413
qck_it(@"should invoke blocks scheduled with -schedule:", ^{
412-
__block BOOL invoked = NO;
414+
__block atomic_bool invoked = NO;
413415
[scheduler schedule:^{
414416
invoked = YES;
415417
}];
@@ -418,7 +420,7 @@ static void expectCurrentSchedulersInner(NSArray *schedulers, NSMutableArray *cu
418420
});
419421

420422
qck_it(@"should invoke blocks scheduled with -after:schedule:", ^{
421-
__block BOOL invoked = NO;
423+
__block atomic_bool invoked = NO;
422424
[scheduler after:[NSDate dateWithTimeIntervalSinceNow:0.01] schedule:^{
423425
invoked = YES;
424426
}];

ReactiveObjCTests/RACSequenceExamples.m

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
#import "RACSequenceExamples.h"
1313

14+
#import <stdatomic.h>
15+
1416
#import "RACScheduler.h"
1517
#import "RACSequence.h"
1618
#import "RACSignal+Operations.h"
@@ -59,8 +61,8 @@ + (void)configure:(Configuration *)configuration {
5961
RACScheduler* scheduler = [RACScheduler schedulerWithPriority:RACSchedulerPriorityHigh];
6062
RACSignal *signal = [sequence signalWithScheduler:scheduler];
6163

62-
__block BOOL flag = YES;
63-
__block BOOL completed = NO;
64+
__block atomic_bool flag = YES;
65+
__block atomic_bool completed = NO;
6466
[signal subscribeNext:^(id x) {
6567
expect(@(flag)).to(beTruthy());
6668
flag = NO;

ReactiveObjCTests/RACSequenceSpec.m

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#import "RACSequenceExamples.h"
1313
#import "RACStreamExamples.h"
1414

15+
#import <stdatomic.h>
16+
1517
#import "NSArray+RACSequenceAdditions.h"
1618
#import "NSObject+RACDeallocating.h"
1719
#import "NSObject+RACPropertySubscribing.h"
@@ -305,7 +307,7 @@
305307
[values addObject:@(i)];
306308
}
307309

308-
__block BOOL finished = NO;
310+
__block atomic_bool finished = NO;
309311
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
310312
@autoreleasepool {
311313
(void)[[values.rac_sequence map:^(id value) {

ReactiveObjCTests/RACSerialDisposableSpec.m

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
#import "RACSerialDisposable.h"
1313

14+
#import <stdatomic.h>
15+
1416
QuickSpecBegin(RACSerialDisposableSpec)
1517

1618
qck_it(@"should initialize with -init", ^{
@@ -138,12 +140,12 @@
138140
});
139141

140142
qck_it(@"should not crash when racing between swapInDisposable and disposable", ^{
141-
__block BOOL stop = NO;
143+
__block atomic_bool stop = NO;
142144
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long long)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
143145
stop = YES;
144146
});
145147

146-
RACSerialDisposable *serialDisposable = [[RACSerialDisposable alloc] init];
148+
RACSerialDisposable *serialDisposable = [[RACSerialDisposable alloc] init];
147149
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
148150
while (!stop) {
149151
[serialDisposable swapInDisposable:[RACDisposable disposableWithBlock:^{}]];

ReactiveObjCTests/RACSignalSpec.m

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#import "RACTestObject.h"
1616

1717
#import <ReactiveObjC/EXTKeyPathCoding.h>
18+
#import <stdatomic.h>
19+
1820
#import "NSObject+RACDeallocating.h"
1921
#import "NSObject+RACPropertySubscribing.h"
2022
#import "RACBehaviorSubject.h"
@@ -33,7 +35,6 @@
3335
#import "RACTestScheduler.h"
3436
#import "RACTuple.h"
3537
#import "RACUnit.h"
36-
#import <libkern/OSAtomic.h>
3738

3839
// Set in a beforeAll below.
3940
static NSError *RACSignalTestError;
@@ -111,7 +112,7 @@ + (void)configure:(Configuration *)configuration {
111112
};
112113

113114
RACSignal *infiniteSignal = [RACSignal createSignal:^(id<RACSubscriber> subscriber) {
114-
__block volatile int32_t done = 0;
115+
__block atomic_int done = 0;
115116

116117
[RACScheduler.mainThreadScheduler schedule:^{
117118
while (!done) {
@@ -120,7 +121,7 @@ + (void)configure:(Configuration *)configuration {
120121
}];
121122

122123
return [RACDisposable disposableWithBlock:^{
123-
OSAtomicIncrement32Barrier(&done);
124+
++done;
124125
}];
125126
}];
126127

@@ -345,21 +346,21 @@ + (void)configure:(Configuration *)configuration {
345346
});
346347

347348
qck_it(@"should have a current scheduler in didSubscribe block", ^{
348-
__block RACScheduler *currentScheduler;
349+
__block atomic_bool hasCurrentScheduler = NO;
349350
RACSignal *signal = [RACSignal createSignal:^ RACDisposable * (id<RACSubscriber> subscriber) {
350-
currentScheduler = RACScheduler.currentScheduler;
351+
hasCurrentScheduler = RACScheduler.currentScheduler != nil;
351352
[subscriber sendCompleted];
352353
return nil;
353354
}];
354355

355356
[signal subscribeNext:^(id x) {}];
356-
expect(currentScheduler).notTo(beNil());
357+
expect(hasCurrentScheduler).to(beTruthy());
357358

358-
currentScheduler = nil;
359+
hasCurrentScheduler = NO;
359360
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
360361
[signal subscribeNext:^(id x) {}];
361362
});
362-
expect(currentScheduler).toEventuallyNot(beNil());
363+
expect(hasCurrentScheduler).toEventually(beTruthy());
363364
});
364365

365366
qck_it(@"should automatically dispose of other subscriptions from +createSignal:", ^{
@@ -860,12 +861,11 @@ + (void)configure:(Configuration *)configuration {
860861
}];
861862
}];
862863

863-
__block NSUInteger nextCount = 0;
864-
__block BOOL gotCompleted = NO;
864+
__block atomic_uint nextCount = 0;
865+
__block atomic_bool gotCompleted = NO;
865866
[[signal repeat] subscribeNext:^(id x) {
866867
nextCount++;
867868
} error:^(NSError *error) {
868-
869869
} completed:^{
870870
gotCompleted = YES;
871871
}];
@@ -2304,7 +2304,7 @@ + (void)configure:(Configuration *)configuration {
23042304

23052305
qck_beforeEach(^{
23062306
testTimer = [^(RACSignal *timer, NSNumber *minInterval, NSNumber *leeway) {
2307-
__block NSUInteger nextsReceived = 0;
2307+
__block atomic_uint nextsReceived = 0;
23082308

23092309
NSTimeInterval startTime = NSDate.timeIntervalSinceReferenceDate;
23102310
[[timer take:3] subscribeNext:^(NSDate *date) {

ReactiveObjCTests/RACSubjectSpec.m

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111

1212
#import "RACSubscriberExamples.h"
1313

14-
#import <libkern/OSAtomic.h>
1514
#import <ReactiveObjC/EXTScope.h>
15+
#import <stdatomic.h>
16+
1617
#import "RACBehaviorSubject.h"
1718
#import "RACCompoundDisposable.h"
1819
#import "RACDisposable.h"
@@ -240,10 +241,10 @@ - (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable {
240241

241242
// Just leak it, ain't no thang.
242243
__unsafe_unretained volatile id *values = (__unsafe_unretained id *)calloc(count, sizeof(*values));
243-
__block volatile int32_t nextIndex = 0;
244+
__block atomic_int nextIndex = 0;
244245

245246
[subject subscribeNext:^(NSNumber *value) {
246-
int32_t indexPlusOne = OSAtomicIncrement32(&nextIndex);
247+
int32_t indexPlusOne = ++nextIndex;
247248
values[indexPlusOne - 1] = value;
248249
}];
249250

@@ -261,7 +262,7 @@ - (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable {
261262
[subject sendCompleted];
262263
});
263264

264-
OSMemoryBarrier();
265+
atomic_thread_fence(memory_order_seq_cst);
265266

266267
NSArray *liveValues = [NSArray arrayWithObjects:(id *)values count:(NSUInteger)nextIndex];
267268
expect(liveValues).to(haveCount(@(count)));
@@ -280,21 +281,21 @@ - (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable {
280281
qck_it(@"should have a current scheduler when replaying", ^{
281282
[subject sendNext:RACUnit.defaultUnit];
282283

283-
__block RACScheduler *currentScheduler;
284+
__block atomic_bool hasCurrentScheduler = NO;
284285
[subject subscribeNext:^(id x) {
285-
currentScheduler = RACScheduler.currentScheduler;
286+
hasCurrentScheduler = RACScheduler.currentScheduler != nil;
286287
}];
287288

288-
expect(currentScheduler).notTo(beNil());
289+
expect(hasCurrentScheduler).notTo(beNil());
289290

290-
currentScheduler = nil;
291+
hasCurrentScheduler = NO;
291292
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
292293
[subject subscribeNext:^(id x) {
293-
currentScheduler = RACScheduler.currentScheduler;
294+
hasCurrentScheduler = RACScheduler.currentScheduler != nil;
294295
}];
295296
});
296297

297-
expect(currentScheduler).toEventuallyNot(beNil());
298+
expect(hasCurrentScheduler).toEventually(beTruthy());
298299
});
299300

300301
qck_it(@"should stop replaying when the subscription is disposed", ^{

0 commit comments

Comments
 (0)