Is BOOL read/write atomic in Objective C?
I would have to diverge from the accepted answer. Sorry. While objective c does not guarantee that BOOL properties declared as nonatomic are in fact atomic I'd have to guess that the hardware you most care about (all iOS and macos devices) have instructions to perform byte reads and stores atomically. So, unless Apple comes out with Road Light OS running on an IBM microcontroller that has 5 bit wide bus to send 10 bit bytes over you could just as well use nonatomic BOOLs in a situation that calls for atomic BOOLs. The code would not be portable to Road Light OS but if you can sacrifice the futureproofing of your code nonatomic is fine for this use case. I'm sure there are hardened individuals on s.o. that would raise to the challenge of disassembling synthesized BOOL getter and setter for atomic/nonatomic cases to see what's the difference. At least on ARM.
Your takeaway from this is likely this
- you can declare BOOL properties as atomic and it won't cost you a dime on all HW iOS and macOS intrinsically supports.
- memory barriers are orthogonal to atomicity
- you most definitely should not use 4 byte properties to store booleans into unless you are into [very] fuzzy logic. It's idiotic and wasteful, you don't want to be a clone of a Java programmer, who can't tell a float from a double, or do you?
- BOOL variables (which do not obviously support atomic/nonatomic decorators would not be atomic on some narrow bus architectures objective C would not be used on anyway (microcontrollers with or without some [very] micro OS are C & assembly territory I suppose. they don't typically need the luggage objc runtime would bring)
Here is code for solution suggested by Jacko.
Use volatile
uint32_t
with OSAtomicOr32Barrier
and OSAtomicAnd32Barrier
#import <libkern/OSAtomic.h>
volatile uint32_t _IsRunning;
- (BOOL)isRunning {
return _IsRunning != 0;
}
- (void)setIsRunning:(BOOL)allowed {
if (allowed) {
OSAtomicOr32Barrier(1, & _IsRunning); //Atomic bitwise OR of two 32-bit values with barrier
} else {
OSAtomicAnd32Barrier(0, & _IsRunning); //Atomic bitwise AND of two 32-bit values with barrier.
}
}
No. Without a locking construct, reading/writing any type variable is NOT atomic in Objective C.
If two threads write YES at the same time to a BOOL, the result is YES regardless of which one gets in first.
Please see: Synchronizing Thread Execution