10

I know it's possible to solve reader-writer issues in GCD using barriers. Since I (generally) try to use NSOperationQueue instead of GCD when performance isn't a key issue, I'd like an NSOperation-compatible solution to this issue.

I've tried to write my own, but my solution has become unwieldy...surely someone has tackled this problem already?

Does anyone know of an NSOperation-compatible solution to the reader-writer problem?

Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
Greg Maletic
  • 6,225
  • 8
  • 54
  • 73

1 Answers1

1

As with most NSOperationQueue hackery, you can exploit its support for dependencies between operations:

  • Create an NSBlockOperation subclass, ReaderWriterBlockOperation. Add to it property BOOL writer.
  • Create an operation queue per protected resource.
  • Stop exposing your operation queue to clients. Instead expose the API -readWithBlock: and -writeWithBlock:. Both enqueue an ReaderWriterBlockOperation, the one with writer == NO, the other == YES. Their operation manages dependencies as follows:
    • -readWithBlock: does, in an @synchronized(self) block, a scan of the operations from last to first looking for a writer block. If none is found, it adds operation and returns. If one is found, it makes the new reader block dependent on the writer, enqueues it, and returns.
    • -writeWithBlock: does the same thing. Except if no writer is found in the queued operations, it makes the block dependent on all readers found. If one is found in the queued operations, it makes itself dependent on that operation and all following (reader) operations.

This should have the result of blocking all readers till the writer before them has completed, and blocking all writers till the readers before them have completed.

One possible issue: I'm unclear (because the docs are unclear, and I haven't implemented this as such yet) if NSBlockOperation actually waits for its block to finish running before declaring itself complete. If it doesn't, you'll need to manage that yourself in your operation subclass.

All that said, if the system provides a working solution, such as barrier blocks, you should use that. This whole system is a hack to get an operation queue to do something that dispatch queues have been tuned to handle very well. If performance is not in fact a concern, then why not just use a serial queue (NSOperationQueue with max concurrent operation count == 1)?

Jeremy W. Sherman
  • 35,901
  • 5
  • 77
  • 111