So what was the solution?
3 threads, running concurrently:
Thread 1: Read data from file in chunks and uncompress it
Thread 2: Process chunk of data and prepare it for import
Thread 3: Core Data imports stuff, several hundred records at a time
So it looks something like this:
File IO -> XML Parsing -> Core Data Import
This requires some sort of thread-safe way to pass the data from one thread to another. And of course, if the file IO is way faster than the XML parsing, we don't want it to run out of control and slap 100 MB into RAM. Looks like your classic producer / consumer problem.
There's a lot of great documentation out there on multithreading in Cocoa. Apple's "Threading Programming Guide" is a good place to start. I'm just going to present one simple, yet elegant, solution here.
NSCondition is a really simple way to achieve what we want. The consumer pseudo code looks something like this:
[condition lock];
while([array count] == 0)
{
// Nothing to consume.
// Call wait, which will unlock our condition, and
// block our thread until we're signaled by the
// producer thread, at which point we'll
// automatically regain the lock and continue.
[condition wait];
}
// Remove data from array for processing
[condition unlock];
This concept can be rolled into a really simple class which we called BlockingQueue. There are only a few simple methods. A "put" method that the producer can call. If the array is already at capacity (configurable on init) the method will block. This prevents the producer from creating data faster than the consumer can handle. And a "get" method that the consumer can call. This method blocks if the consumer is going faster than the producer, allowing it to sleep while the producer catches up.
@interface BlockingQueue : NSObject
{
NSUInteger maxSize;
NSCondition *condition;
NSMutableArray *array;
}
- (id)initWithMaxSize:(NSUInteger)maxSize;
- (NSUInteger)maxSize;
- (void)put:(id)obj;
- (id)get;
- (NSArray *)getUpTo:(NSUInteger)num;
@end
@implementation BlockingQueue
- (id)initWithMaxSize:(NSUInteger)max
{
if((self = [super init]))
{
maxSize = MAX(max, 1);
condition = [[NSCondition alloc] init];
array = [[NSMutableArray alloc] initWithCapacity:maxSize];
}
return self;
}
- (void)dealloc
{
[condition release];
[array release];
[super dealloc];
}
- (NSUInteger)maxSize
{
return maxSize;
}
- (void)put:(id)obj
{
if(obj == nil) return;
[condition lock];
while([array count] == maxSize)
{
[condition wait]; // unlock + wait for signal
}
[array addObject:obj];
if([array count] == 1)
{
// The array was previously empty.
// There may be a get operation waiting on us.
[condition signal]; // unlock + signal
}
[condition unlock];
}
- (id)get
{
[condition lock];
while([array count] == 0)
{
[condition wait]; // unlock + wait for signal
}
id result = [[[array objectAtIndex:0] retain] autorelease];
[array removeObjectAtIndex:0];
if([array count] == (maxSize - 1))
{
// The array was previously full.
// There may be a put operation waiting on us.
[condition signal]; // unlock + signal
}
[condition unlock];
return result;
}
- (NSArray *)getUpTo:(NSUInteger)requestNum
{
[condition lock];
while([array count] == 0)
{
[condition wait]; // unlock + wait for signal
}
NSUInteger available = [array count];
NSUInteger resultNum = MIN(available, requestNum);
NSRange resultRange = NSMakeRange(0, resultNum);
NSArray *result = [array subarrayWithRange:resultRange];
[array removeObjectsInRange:resultRange];
if(available == maxSize)
{
// The array was previously full.
// There may be a put operation waiting on us.
[condition signal]; // unlock + signal
}
[condition unlock];
return result;
}
@end
Like I said, pretty simple, but useful when you need it.
20 comments:
Hey there,
So, was wondering.. are you one of the developers who worked on MOJO? If so, are there any plans to get it compatible with iTunes 9? I love my Mojo and miss it.
Thanks,
-M
What happened to Mojo? I'd be intrested in helping out gettig it back up and running.
Hi - is deusty.com / mojo shutdown for good?
Deusty/Mojo is not dead. We are just restructuring. We plan on being back up in a few weeks.
Whew... I had given up the ghost and thought mojo was over!!! My brief searches revealed no news (at the time) ... looking forward to having my trusty Mojo back so I can listen to my home iTunes while on the road without burdening my laptop with my iTunes library!
Can't wait, thanks for all your hard work-- MUCH appreciated and (currently) MISSED!!!
@MissFitz What seems to be wrong with iTunes and Mojo? I have no problem running it.
my mojo will not work. i had some problems installing so i got the netframe and bonjour seperatly finally downloaded mojo and now i cant connect to my buddies pc.
it goes
connecting to computer
requesting itunes data
cannot connect to computer.
what could be wrong? my buddies can look at my itunes fine
What OS and iTunes version are you two on?
where can I download the latest version for Mac... I switched recently and now I'm looking for the Mac-version...
I have it hosted here http://www.berad.me/files/files.php
I do wish these people would atleast take a minute to say what is up instead of leaving us in the dust.
@Anonymous If you have troubles let me know. I have not had any what so ever. 10.6.2 and iTunes 9. Btw, I can not find Mojo_3.5.0.leopard. That seems to be the latest version.
I can't get mojo to download songs.
I have os x 10.4 (tiger) and itunes 9 and I have no trouble connecting to computers but when I hit download the progress bar fills up completely but never says finished, the songs do not add to my itunes, and if I click on a new song to download it is added to the queue, which indicates to me that the song is never downloading at all.
please help!
i have mojo 3.1 and when i hit update it says :
An error occurred while downloading the update. Please try again later.
does that have to do with the fact that deuesty is down?
@Cherylin Look up a few comments. Get that file. It's 3.4.1. I am not sure if it will run on Tiger but I would assume so.
@ Anonymous
i googled mojo 3.4 for tiger and everyplace that comes up has a link to another place for the tiger compatible version and it always takes me here:
http://www.deusty.com/software/download_mojo.php
to deusty's down site.
i tried 3.4 for leopard and my mac wouldn't even open it once installed.
Like I said, try this link here: http://www.berad.me/files/files.php I have it hosted for people that can not find it. Otherwise, if that don't work I suggest doing a google search for "mojo tiger 3.1". Use those links at your own risk. Most are from rapidshare or mediafire but you can find the file.
Anyone know where I can get the most recent version of mojo for windows? it's getting quite frustrating being redirected to a downed website so often. Any help is greatly appreciated.
Thanks
Robbie Hanson said...
Deusty/Mojo is not dead. We are just restructuring. We plan on being back up in a few weeks.
it's dec 28 and nothing
they should at least keep all the registered users up to date on what is happening. lack of info always gives me a feeling of distrust.
when i registered, they got my email. all they have to do is email everyone and let us know. seems like that's the least they can do after taking our money
@Anonymous Regarding Windows Mojo
Why not try Google? CNet download works fine.
http://bit.ly/8rd5GC
Robbie is it true? The end of mojo as we know it? Where is a link to users who are still using the program?
Post a Comment