6

Because NSOperationQueue always run tasks on a new thread, I'm confused about the role of isConcurrent when NSOperation runs from NSOperationQueue.

If i have two subclasses of NSOperation, both running an async processes, both are launched from NSOperationQueue and in both I override isCancelled, isExecuting, isFinished and isReady. What will be the difference if at one I override isConcurrent to always return YES and the other always to return NO.

Who actually calls isConcurrent? How the logic change if it is NO or YES.

Mat
  • 202,337
  • 40
  • 393
  • 406
amit
  • 2,171
  • 4
  • 31
  • 50

3 Answers3

5

It's a legacy method, used before OS X v10.6 and before iOS 4, i.e. before the introduction of GCD for NSOperationQueue dispatch.

From the doc

Operation queues usually provide the threads used to run their operations. In OS X v10.6 and later, operation queues use the libdispatch library (also known as Grand Central Dispatch) to initiate the execution of their operations. As a result, operations are always executed on a separate thread, regardless of whether they are designated as concurrent or non-concurrent operations. In OS X v10.5, however, operations are executed on separate threads only if their isConcurrent method returns NO. If that method returns YES, the operation object is expected to create its own thread (or start some asynchronous operation); the queue does not provide a thread for it.

If you're running OS X >= 10.6 or iOS >= 4, you can safely ignore it.

As a confirmation of this fact, from the doc of isConcurrent

In OS X v10.6 and later, operation queues ignore the value returned by this method and always start operations on a separate thread.

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
  • I down voted this this answer because I don't think that it's main conclusion that `isConcurrent` can safely be ignored after 10.6 or iOS4 is correct, given that the method has not been deprecated. – Rory O'Bryan Aug 22 '13 at 10:38
  • Is not deprecated because you don't invoke the method, your override it. This method is called by Apple internal implementation of `NSOperationQueue` and they explicitly say that they are going to ignore its return value. – Gabriele Petronella Aug 22 '13 at 11:17
  • I don't see the link between invoking vs overriding and deprecating. The quotes from the documentation show one change in how the method is used now vs in the past. I don't think that means it couldn't change again in the future, or isn't used anywhere else, and so you should just ignore it. I think until it is deprecated you should return the correct answer, even if you suspect it's not currently used. – Rory O'Bryan Aug 22 '13 at 12:02
2

I have added a more concise answer now, left this for the time being as it was part of a discussion...


Ok, I was quite happy with my use of the isConcurrent method until today !

I read the sentence:

In OS X v10.6 and later, operation queues ignore the value returned by this method and always start operations on a separate thread.

As a warning relating to QA1712, pointing out that for concurrent operations the start method can now be called on a different thread to the one that queued the operation, which is a change in 10.6 and iOS 4.

I didn't read this as indicating that the isConcurrent method is ignored completely by the queue and has no purpose at all, just that it no longer effects the thread on which start is called. I may have misunderstood this.

I also misunderstood the original question as a more general one about concurrent operations and the isConcurrent flag, and the accepted answer as effectively saying

The isConcurrent flag can be ignored since 10.6 and iOS 4

I'm not sure this is correct.

If I understand the original question now, to paraphrase:

Given a correctly built concurrent NSOperation does the isConcurrent flag itself actually alter the execution of the operation at all?

I guess it's hard to say for all possible setups, but we can say that:

  1. It's not deprecated. It's normal for Apple to deprecate methods that are no longer useful.

  2. The documentation consistently refers to the method being a required override.

Perhaps isConcurrent is effectively deprecated but as it's only a single BOOL flag perhaps it's not worth the effort to deprecate it in the docs. Or perhaps it does nothing now but Apple have kept it for possible future use and expect you to override it as described.

I created a quick test project with an NSOperation that overrode isConcurrent and main only, isConcurrent was not called at any stage. It was a very simple test though. I assume you may have tested it also? I assumed perhaps if the NSOperationQueue didn't call it NSOperation's default implementation of start might.

So where does that leave us? Obviously it's no trouble to implement it and return YES to satisfy the documented requirements. However from my perspective I think it's too much of a leap to go from the caveat regarding 10.6 and iOS 4.0 to say that it can be safely ignored now.


My Original Answer...

isConcurrent is not a legacy method and is not ignored by NSOperationQueue. The documentation as quoted in the other answers is a little unclear and easily misunderstood.

isConcurrent = YES means the operation provides its own means of concurrency. Or to put it another way, the operation "isAlreadyConcurrent" and doesn't need the NSOperationQueue to provide and manage the concurrency. As NSOperationQueue is no longer providing the concurrency you need to tell it when the operation isFinished or if it isCancelled (etc) hence the need to override these methods.

A common example is an NSOperation that manages an NSURLConnection. NSURLConnection has it's own mechanism for running in the background, so doesn't need to be made concurrent by NSOperationQueue.

An obvious question is then: "Why put an already concurrent operation into an NSOperationQueue?" It's so the operation can benefit from the other features of the NSOperationQueue like dependencies etc.

The misleading part of the documentation is referring only to what thread the start method of an NSOperation is called on. The change caused a problem discussed in QA1712.

Rory O'Bryan
  • 1,894
  • 14
  • 22
  • I got that from the documentation, but this does not answer my question. Under the assumption that i override all NSOperation methods and i run it under NSOperationQueue, how does setting isConcurrent to YES or NO make a difference? – amit Aug 22 '13 at 07:06
  • You say "and is not ignored by NSOperationQueue" so why does the documentation say "operation queues ignore the value returned by this method"? – David Rönnqvist Aug 22 '13 at 07:39
  • Hi David, added some explanation of how I interpreted that quote in the docs. I think the docs are confusing, but I may just be confusing myself :-). I'm still not sure given the lack of formal deprecation and it's use in the rest of the documentation that is is safe to just ignore `isConcurrent` after 10.6 and iOS4... – Rory O'Bryan Aug 22 '13 at 10:09
0

Paraphrasing the original question to:

Given a correctly built concurrent NSOperation does the value returned by isConcurrent actually alter the execution of the operation at all?

Whilst we could try to understand how the isConcurrent flag is used by NSOperation, NSOperationQueue, or other parts of the operating system, it would be a mistake to rely on any information we discovered.

The purpose of the flag is described only as:

Return YES if the operation runs asynchronously with respect to the current thread or NO if the operation runs synchronously on whatever thread started it.

As long as you correctly respond, it should not be important who calls the method or how it effects any logic inside the Apple frameworks.


Additional Notes:

The documentation does make reference to a change in the way that NSOperationQueue used this value before and after OSX 10.6 and iOS 4.0.

In OS X v10.6, operation queues ignore the value returned by isConcurrent and always call the start method of your operation from a separate thread. In OS X v10.5, however, operation queues create a thread only if isConcurrent returns NO. ...

This change caused an issue described in QA1712.

This commentary is commonly interpreted to imply that the isConcurrent flag is no longer used after 10.6 and iOS 4, and can be ignored. I do not agree with this interpretation as the method has not been formally deprecated and is still documented as a required override for concurrent operations.

Also the fact that it's use has changed in the past is a reminder that it could change again in the future, so we should respond correctly even if we suspect it does not currently have any effect.

Rory O'Bryan
  • 1,894
  • 14
  • 22