On Sep 14, 2011, at 7:18 PM, Kyle Sluder wrote:

> On Wed, Sep 14, 2011 at 9:38 AM, Andreas Grosam <agro...@onlinehome.de> wrote:
>> A "Synchronous Channel" (or Synchronous Queue) is a well known pattern used 
>> in multithreading. Basically, it is used to "hand off" objects from one 
>> thread to another, with the requirement that the "producer" waits until a 
>> "consumer" took the object.
> 
> If you want to block the producer until its object is consumed, why
> not use dispatch_sync?
> 
> void producer() {
>  while (1) {
>    dispatch_sync(consumer_queue, ^{
>      dispatch_async(consumer_queue, ^{
>        // consume the thing
>      }
>    }
>  }
> }
> 
> --Kyle Sluder


Hm, if we dispatch "consume the thing" asynchronously, wouldn't it return 
pretty fast?
It would also not wait until consumer has processed the data in "consume the 
thing"? So, possibly many data objects can be created by the producer, then 
waiting in a dispatch queue without having a means to throttle this?

Also, I could possibly schedule several "consume the thing" work items - but 
what if "consume the thing" is only *one* operation, and cannot be performed by 
several sequential operations? In fact, my consumer cannot partially consume 
content provided by one NSData object, then return with result "STILL_HUNGRY", 
and then restart with the next partial data. Instead, the running consumer can 
be fed with NSData objects from a producer thread at any point in time. This, 
however should block if consumer is still chewing on the previous mouthful.



Here is the problem as brief as I can present it:


"consumer" will do roughly the following:

// Start a worker thread on the global concurrent queue.
// start will be invoked by some Controller object, which also listens to 
notifications (async blocks), sent
// from consumer while it processes the data:
- (void) start {
   dispatch_async(dispatch_get_global_queue(),^{[self run]});
}

// run is the actual task of the consumer - only after when it is finished 
// with one or more NSData objects, it returns.
// runs in its own thread!
- (void) run 
{
    char ch;
    while (!done && (ch = [self next]) != 0) {
        // invokes nested methods, each can invoke next
    }
}

// retrieve the next char from the buffer. If we are finished with the buffer,
// get a new buffer. This may block.
- (char) next {
   if (p_ == buffer_end_) {
       buffer_ = [synchronousQueue_ getData];  // blocks until data is offered
       p_ = [buffer_ bytes];
       buffer_end_ = p_ + [buffer length];
   }
   char ch = *p_++;
   return ch;
}


// Here we feed the consumer with the next data buffer:
- (void) consumeTheThing:(NSData*)thing {
  [synchronousQueue_ putData:thing];
}


So for example, a NSURLConnection is the producer:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
   // we are not on the main thread!
   [consumer_ consumeTheThing:data];  // blocks until data has been taken (this 
will throttle download)
}



Andreas

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to