Re: Implementing a "Synchronous Channel" with dispatch
Re: Implementing a "Synchronous Channel" with dispatch
- Subject: Re: Implementing a "Synchronous Channel" with dispatch
- From: Andreas Grosam <email@hidden>
- Date: Wed, 14 Sep 2011 23:18:47 +0200
On Sep 14, 2011, at 9:39 PM, Dave Zarzycki wrote:
>
> That's fine. Your block can still get at your object's instance variables:
>
> - (void)doSomething
> {
> x = create_something();
> dispatch_sync(consumer_q, ^{
> _prev_state_ivar = do_something_with(_prev_state_ivar, x);
> });
> // do_something_with() is done
> }
OK, I see how I can "hand off" an object from one thread to another, and wait in the producer thread until the consumer finished with processing this data. I suspect, in do_something_with(), the consumer receives a method like consumeData:.
Still, I don't see how this can work in my scenario. I'm not sure if I was clear enough how my consumer works and if you took care for this special issu. So I will try to explain it in more detail:
Unless I miss something, the above consumer has the capability to keep its complete state after returning from precessing a chunk of at data. It is also capable to execute its method consumeData: on the same thread where it is invoked. And as such is capable to return from method "consumeData:" , while keeping its state, and is also capable to process subsequent chunks of content through re-entering consumeData:.
So, it can basically do this:
accept data in tread A, process partial data in tread A, and return while saving its state. Repeat with next partial data.
This, however is not the case with my consumer. This consumer is a "recursive descent" parser, which keeps its state on the call-stack. It cannot parse partial content, through a method like parserPartialData: , then return with result "NEED_MORE_DATA" and later get the next chunk of data.
Usually, a recursive decent parser has a method parse:(NSString*)string, where a *complete* text shall be passed as the parameter. It must not be partial text. Then the parser starts parsing on the same thread and returns the result. Its "parsing state" will be kept on the call stack while it is executing parse: - not in some member variable or ivar. So it cannot return from parsing a partial content without saying: "error: unexpected end of data".
So, basically the parser can do this:
result r = parse(someString);
no repeat. no partial content. Once it did parse, parse is finished.
Due to lack of a better solution, I made this work with this kind of parser as follows:
It is possible to make this kind of parser work with feeding it *partial content*. This requires:
1) the parser must run in its own thread (see method start and run)
2) the parser accesses and "dereferences" a special "iterator" (see method next), which points to the content. If a partial buffer is finished, it waits until a new buffer is offered by a producer. This may block.
3) from another thread, there must be a possibility to feed the parser with partial content (see method consumeTheThing:)
4) there need to be one actor which helps in handing off the buffers from a producer thread to the parser's thread. (see synchronous queue).
In one of my previous post, I outlined these basic methods of the parser:
- (void) start; // invoked from a client to run parser asynchronously on its thread
- (void) run;
- (char) next; // called from the parser internally, will block if no new buffer has been offered.
- (void) consumeTheThing:(NSData*)partialData // invoked from the producer on another thread than run is executing.
And internally, the parser uses the "synchronous queue" where objects where handed off from the producer to the parser.
So, if I possibly missed something here, I would be glad to get enlightened. ;)
Andreas
>
>> The consumer's state (it's a parser) is the function stack. So, I need an intermediate actor - which is capable to hand off one data object. This is some kind of queue.
>
> A dispatch queue should work just fine.
>
> davez
>
>
>>
>>>
>>> A note about dispatch semaphores: While they are powerful, they are not meant to replace queues. They exist for two very specific problems: 1) Refactoring synchronous APIs on top of asynchronous APIs and
>>
>>> 2) managing finite resource pools.
>> This (2) is actually what I'm trying to accomplish (well, a bit more - performance for example). Otherwise, I would just safe the 100Mbyte data download on my iPhone in memory ;)
>>
>> A synchronous queue, would have capacity zero -- which would block producers till a consumer takes the data. This is what I want. Otherwise, if I would asynchronously queue the NSData objects, somehow, NSURLConnection would flood a iPhone with almost 1Mbyte per sec, that is a few seconds before crash.
>>
>> So, unless the parser is capable to truly parse partial content, and can return and restart while it's state is kept somewhere else, I can't see how to make it "easy" in conjunction with a NSURLConnection :)
>>
>>
>> So, the questions remains: would the use of a "Synchronous Queue" be effective enough? What are the consequences?
>>
>> Andreas
>>
>>
>> _______________________________________________
>>
>> Cocoa-dev mailing list (email@hidden)
>>
>> 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:
>>
>> This email sent to email@hidden
>
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden