Reputation: 3673
I'm just getting into iPhone development after many years doing Java development. I'm looking for the Objective-C equivalent to Java's BlockingQueue. Is there something like that?
In case I'm going about things the wrong way, here's what I'm trying to achieve:
I want to display, one at a time, chunks of data pulled from a network server. To keep the user from noticing network lag, I want to always have a few chunks of data pre-fetched. In Java-land, I'd use a thread-safe queue between my fetching thread and my display thread.
Upvotes: 4
Views: 5040
Reputation: 14247
Here's an implementation of a blocking queue with a queue and dequeue method. The expectation would be that one thread goes into a loop calling dequeueUnitOfWorkWaitingUntilDate: and processes units of work while a second thread is calling queueUnitOfWork:.
@interface MyBlockingQueue : NSObject {
NSMutableArray *queue;
NSConditionLock *queueLock;
}
- (id)dequeueUnitOfWorkWaitingUntilDate:(NSDate *)timeoutData;
- (void)queueUnitOfWork:(id)unitOfWork;
@end
enum {
kNoWorkQueued = 0,
kWorkQueued = 1
}
@implementation MyBlockingQueue
- (id)init {
if ((self = [super init])) {
queueLock = [[NSConditionLock alloc] initWithCondition:kNoWorkQueued];
workItems = [[NSMutableArray alloc] init];
}
return self;
}
- (void)dealloc {
[queueLock release];
[workItems release];
[super dealloc];
}
- (id)dequeueUnitOfWorkWaitingUntilDate:(NSDate *)timeoutDate {
id unitOfWork = nil;
if ([queueLock lockWhenCondition:kWorkQueued beforeDate:timeoutDate]) {
unitOfWork = [[[queue objectAtIndex:0] retain] autorelease];
[queue removeObjectAtIndex:0];
[queueLock unlockWithCondition:([workItems count] ? kWorkQueued : kNoWorkQueued)];
}
return unitOfWork;
}
- (void)queueUnitOfWork:(id)unitOfWork {
[queueLock lock];
[queue addObject:unitOfWork];
[queueLock unlockWithCondition:kWorkQueued];
}
@end
Upvotes: 8
Reputation: 24466
You can simply spin off an NSOperation and post a notification when the data has come back (finished loading). Take a look at Dave Dribin's blog post on concurrency with NSOperation that shows how to encapsulate an NSURLConnection session:
http://www.dribin.org/dave/blog/archives/2009/05/05/concurrent_operations/
If you are not talking about accessing a web service or site where NSURLConnection is appropriate, you can instead use Cocoa Async Socket if it's straight TCP/IP or UDP:
http://code.google.com/p/cocoaasyncsocket/
Best Regards,
Upvotes: 2
Reputation: 60130
I don't think such a thing exists natively - you're probably going to have to write your own class that maintains a queue of network objects. Your header might look something like:
@interface ObjcBlockingQueue : NSObject {
// The objects that you're holding onto
NSArray *objects;
}
@property(nonatomic,retain) NSArray *objects;
- (ServerData *)getNextChunk;
Then you can implement getNextChunk
to pop and return the top object off your objects
array, and if [objects count]
is less than a certain value, launch a thread to fetch some more objects (probably using NSURLConnection with ObjcBlockingQueue being the delegate). You can also have that thread/connection launched inside an overridden init
method to prefill the queue.
You might also want to think about adding a
- (BOOL)isChunkAvailable;
method that will let your display thread know whether it can display something new right away or if it has to display a loading message. Depending on where you're displaying the data and how your app is structured, it may also be worth your while to make ObjcBlockingQueue a singleton class.
Upvotes: 1