Skip to content

Instantly share code, notes, and snippets.

@joelreymont
Created April 21, 2010 10:30
Show Gist options
  • Save joelreymont/373678 to your computer and use it in GitHub Desktop.
Save joelreymont/373678 to your computer and use it in GitHub Desktop.
#include <tr1/memory>
#include <iostream>
#include <vector>
#include <Block.h>
#include <dispatch/dispatch.h>
class Data
{
public:
Data() {}
};
typedef std::tr1::shared_ptr<Data> DataRef;
typedef std::vector<DataRef> BitsOfData;
// Custom block
typedef int (^OurBlock)(void);
// Generic callback
typedef void (^OurCallback)(int status);
// Data bits callback
typedef void (^DataBitsCallback)(int status, BitsOfData& bits);
// Run loop for the thread we want to talk to
extern CFRunLoopRef __TheOtherRunLoop; // run loop for the thread we want to talk to
// Run synchronously
int RunSync(OurBlock block)
{
// use an error code to capture the result of the operation
__block int status = 0;
// and a semaphore to wait until the operation has completed
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
// enqueue the block on the target run loop
CFRunLoopPerformBlock(__TheOtherRunLoop, kCFRunLoopDefaultMode, ^{
// run the block we created previously
status = block();
// and signal that we are done
dispatch_semaphore_signal(sema);
});
// wake up the target run loop
CFRunLoopWakeUp(__TheOtherRunLoop);
// hold on until we are done above
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
// dispose of the semaphore
dispatch_release(sema);
// and return the error code
return status;
}
// Run asynchronously
void RunAsync(OurBlock block, OurCallback callback)
{
// callback will run in the caller thread
// and use the caller's run loop
CFRunLoopRef callbackRunLoop = CFRunLoopGetCurrent();
// enqueue a block on the target run loop
CFRunLoopPerformBlock(__TheOtherRunLoop, kCFRunLoopDefaultMode, ^{
// do the work
int status = block();
// enqueue a block on the caller's run loop
CFRunLoopPerformBlock(callbackRunLoop, kCFRunLoopDefaultMode, ^{
// and make the block invoke the callback and pass the status code
callback(status);
});
// wake up the caller's run loop
CFRunLoopWakeUp(callbackRunLoop);
});
// wake up the target run loop
CFRunLoopWakeUp(__TheOtherRunLoop);
}
OurBlock MakeCollectBits(BitsOfData& bits)
{
// allocate block on the heap
return Block_copy(^{
int status = 0;
cout << "We right here!" << endl;
// no exceptions can excape the block!
try
{
DataRef bit1(new Data);
bits.push_back(ref1);
}
catch (...)
{
cout << "Unknown exception" << endl;
status = -1;
}
return status;
});
}
// Synchronous gathering of data bits
int CollectBits(BitsOfData& bits)
{
// create the block and "capture" bits
OurBlock block = MakeCollectBits(bits);
// run the block synchronously
int status = RunSync(block);
// release memory allocated to the block
Block_release(block);
// we are done
return status;
}
// Asynchronous gathering of data bits
void CollectBitsAsync(BitsOfData& bits, DataBitsCallback callback)
{
// create a closure as before
OurBlock block = MakeCollectBits(bits);
// run asynchronously and trigger a callback created on the fly
RunAsync(block, ^(int status) {
// we are inside "OurCallback" here and need to clean up
// the bit collection block first and foremost
Block_release(block);
// invoke the data bits callback,
// giving it what we have collected
callback(status, bits);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment