Answer the question
In order to leave comments, you need to log in
Is [NSMutableArray count] thread-safe?
There is a code. Stranger. (in both senses, yes).
There is a flow in which a cycle is organized by hands.
Literally, while (running) { }. There are no NSRunLoops, of course. You can, of course, insert about proper perversion, but you don’t want to.
There was a need to perform operations in its context, while not killing the performance (the loop counts the game logic, among other things it executes the lua machine and draws an opengl frame. 60 fps and all that)
As a result, the following solution was born:
while (_running) {
if ([tasks count] > 0)
{
NSArray *tasksCopy = nil;
@synchronized(tasks)
{
tasksCopy = [tasks copy];
[tasks removeAllObjects];
}
for (NSInvocation *invocation in tasksCopy)
{
[invocation invoke];
}
[tasksCopy release];
}
<...>
}
Answer the question
In order to leave comments, you need to log in
Judging by the source code, there is simply a return of the structure field, without side effects. If I'm not mistaken, for a variable whose size is equal to a machine word, the second thread will always see a valid state (if the array length were 64-bit in 32-bit runtime, there would be a case when another thread would see 4 bytes of the current value and 4 previous). Source CF( Mutable
)ArrayRef
: www.opensource.apple.com/source/CF/CF-476.10/CFArray.c /Reference/OSAtomic_header_reference/Reference/reference.html (see OSAtomicDequeue and OSAtomicEnqueue methods).
NSMutableArray
, but specifically, the method count
certainly returns the value atomically, which, however, does not mean thread-safety, i.e. for example codeif ([tasks count] > 0){
[tasks removeObjectAtIndex:0];
}
count
but did not completely complete adding the element by the time the call was made removeObjectAtIndex:
). if ([tasks count] > 0)
outside the synchronization block is premature optimization, there are other places in this code that you should pay attention to in the first place.while (running){ }
will, in the absence of tasks, constantly load the processor with “empty” cycles, when, as normal event loop
, it does not.NSRunLoop
You may not need a full- fledged one, but for NSAutoreleasePool
sure. Moreover, since NSAutoreleasePool
clears itself at the end of each event loop that you don't have, you need to periodically create and clear NSAutoreleasePool
it inside the while(running)
.NSInvocation
for assignments is somewhat surprising. Firstly, it is inconvenient, it is much more convenient to use blocks, and secondly, it is relatively slow (which, in principle, is probably not critical, it must be profiled). Calling one block takes about the same time as sending one message, and the call NSInvocation
is ~20 times slower. True, if you use weak variables in the block , it will be something like NSInvocation
, but this is not your case, because not used by ARC .Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question