using grand central dispatch with c++ for inter-thread communication

260 views
Skip to first unread message

Joel Reymont

unread,
Apr 21, 2010, 7:49:48 AM4/21/10
to Darwin Dev
Here's my write-up on using GCD with C++ for inter-thread communication:

http://twitter.com/wagerlabs/status/12571649529

Please let me know what you think!

Thanks, Joel

---
http://es.linkedin.com/in/joelreymont

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (Darwi...@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/darwin-dev/darwin-dev-garchive-73044%40googlegroups.com

This email sent to darwin-dev-g...@googlegroups.com

--
You received this message because you are subscribed to the Google Groups "darwin-dev" group.
To post to this group, send email to darwi...@googlegroups.com.
To unsubscribe from this group, send email to darwin-dev+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/darwin-dev?hl=en.

Brian Bechtel

unread,
Apr 21, 2010, 11:14:06 AM4/21/10
to Joel Reymont, Darwin Dev
On Wed, Apr 21, 2010 at 4:49 AM, Joel Reymont <joe...@gmail.com> wrote:
> Here's my write-up on using GCD with C++ for inter-thread communication:
>
> http://twitter.com/wagerlabs/status/12571649529
>
> Please let me know what you think!


Wouldn't pointing directly to the article be more efficient?

<http://wagerlabs.com/grand-central-dispatch-c-and-inter-thread-com>


Thanks for the article!

Joel Reymont

unread,
Apr 21, 2010, 11:45:10 AM4/21/10
to Brian Bechtel, Darwin Dev

On Apr 21, 2010, at 4:14 PM, Brian Bechtel wrote:

> Wouldn't pointing directly to the article be more efficient?
>
> <http://wagerlabs.com/grand-central-dispatch-c-and-inter-thread-com>

A bit of context is probably due...

I wrote a user land USB driver and packaged it in a framework. The framework starts the driver in a new thread upon initialization. I needed the separate thread and needed a way to talk to it.

I explored Mach ports but these turned out to be too painful. Grand Central Dispatch, on the other hand, turned out to be the answer to my prayers. I can shuffle code and data back with no problems whatsoever.

As a bonus, my API calls are queued and serialized for me so I don't need to lock portions of the driver for concurrent access.

---
http://es.linkedin.com/in/joelreymont
http://twitter.com/wagerlabs

David Leimbach

unread,
Apr 21, 2010, 12:49:01 PM4/21/10
to Joel Reymont, Darwin Dev
On Wed, Apr 21, 2010 at 8:45 AM, Joel Reymont <joe...@gmail.com> wrote:

On Apr 21, 2010, at 4:14 PM, Brian Bechtel wrote:

> Wouldn't pointing directly to the article be more efficient?
>
> <http://wagerlabs.com/grand-central-dispatch-c-and-inter-thread-com>

A bit of context is probably due...

I wrote a user land USB driver and packaged it in a framework. The framework starts the driver in a new thread upon initialization. I needed the separate thread and needed a way to talk to it.

I explored Mach ports but these turned out to be too painful. Grand Central Dispatch, on the other hand, turned out to be the answer to my prayers. I can shuffle code and data back with no problems whatsoever.

As a bonus, my API calls are queued and serialized for me so I don't need to lock portions of the driver for concurrent access.


This is a good nutshell argument for why libdispatch and GCD kicks serious ass to program with in general.  I wish every platform (especially linux, as I could really use it today in my day job for some small systems concurrency) had this at this point.  Usually I don't like features for concurrency cobbled into a language that did not originally consider concurrency and threading as a primary concern (like any of the C family), but libdispatch is comfortable enough to get by when I can't have my Erlang or Haskell, or even Go.

I'm very happy to hear it's coming to iPhone OS 4 as well.   

Dave


 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list      (Darwi...@lists.apple.com)
Help/Unsubscribe/Update your Subscription:

Kevin Van Vechten

unread,
Apr 21, 2010, 2:26:43 PM4/21/10
to Joel Reymont, Darwin Dev
Hi Joel,

Good article. You describe a perfectly good technique for what you're trying to accomplish — inter-thread communication between existing (well known) threads running CFRunLoop — and there are plenty of instances where this is exactly the right thing to do, especially when bridging existing technologies together.

However, this isn't exactly the "GCD" way of doing things. The true GCD way is to let the dispatch queue *be* the run loop, enqueue work asynchronously via dispatch_async, and have the system implicitly manage the threads for you. That's where the power and performance of GCD really shine.

But don't get me wrong. I'm certainly happy to see you chose to write up an article describing the syntactic convenience of blocks, CFRunLoopPerformBlock and dispatch semaphores. Thanks!

Kevin

On Apr 21, 2010, at 8:45 AM, Joel Reymont wrote:

> On Apr 21, 2010, at 4:14 PM, Brian Bechtel wrote:
>
>> Wouldn't pointing directly to the article be more efficient?
>>
>> <http://wagerlabs.com/grand-central-dispatch-c-and-inter-thread-com>
>
> A bit of context is probably due...
>
> I wrote a user land USB driver and packaged it in a framework. The framework starts the driver in a new thread upon initialization. I needed the separate thread and needed a way to talk to it.
>
> I explored Mach ports but these turned out to be too painful. Grand Central Dispatch, on the other hand, turned out to be the answer to my prayers. I can shuffle code and data back with no problems whatsoever.
>
> As a bonus, my API calls are queued and serialized for me so I don't need to lock portions of the driver for concurrent access.

Joel Reymont

unread,
Apr 21, 2010, 2:32:32 PM4/21/10
to Kevin Van Vechten, Darwin Dev

On Apr 21, 2010, at 7:26 PM, Kevin Van Vechten wrote:

> However, this isn't exactly the "GCD" way of doing things. The true GCD way is to let the dispatch queue *be* the run loop,

I may be wrong but it seemed from reading the source code that run loop _were_ implemented on top of dispatch queues. Is this not so?

Thanks, Joel

Kevin Van Vechten

unread,
Apr 21, 2010, 2:37:29 PM4/21/10
to Joel Reymont, Darwin Dev

On Apr 21, 2010, at 11:32 AM, Joel Reymont wrote:

> On Apr 21, 2010, at 7:26 PM, Kevin Van Vechten wrote:
>
>> However, this isn't exactly the "GCD" way of doing things. The true GCD way is to let the dispatch queue *be* the run loop,
>
> I may be wrong but it seemed from reading the source code that run loop _were_ implemented on top of dispatch queues. Is this not so?

Not exactly. But ignoring the implementation details…

The API for CFRunLoop requires that you manage the threads yourself. The goal of GCD is for you to work with queues that may or may not be backed by threads at any given time.

Kevin _______________________________________________

Joel Reymont

unread,
Apr 21, 2010, 3:05:21 PM4/21/10
to Kevin Van Vechten, Darwin Dev

On Apr 21, 2010, at 7:37 PM, Kevin Van Vechten wrote:

> The API for CFRunLoop requires that you manage the threads yourself. The goal of GCD is for you to work with queues that may or may not be backed by threads at any given time.

I looked at using dispatch queues at first but got stuck. This may be just the opportunity to get me over the stumbling block! This is the crucial bit of code that I can't figure out how to translate to dispatch queues:

static IONotificationPortRef __NotifyPort;

// add notification port and run loop source for async notifications

__NotifyPort = IONotificationPortCreate(masterPort);
runLoopSource = IONotificationPortGetRunLoopSource(__NotifyPort);

// set up run loop for our driver thread

__MeasatRunLoop = CFRunLoopGetCurrent(),
CFRunLoopAddSource(__MeasatRunLoop, runLoopSource, kCFRunLoopDefaultMode);

and then

// set up notification to detect plugging of Measat without firmware

kr = IOServiceAddMatchingNotification( __NotifyPort,
kIOFirstMatchNotification,
matchingDict,
RawDeviceAdded,
NULL,
&__RawAddedIter );

I see dispatch_source_create as a candidate to replace CFRunLoopAddSource but what dispatch source type should I use? There's one for Mach receive and one for Mach send. Which one should I use with the Mach port behind the IO Notification Port? I'm assuming here that I need to get hold of the underlying Mach port.

Daniel A. Steffen

unread,
Apr 21, 2010, 3:57:23 PM4/21/10
to Joel Reymont, Darwin Dev
Hi Joel,

On Apr 21, 2010, at 12:05 PM, Joel Reymont wrote:

> I looked at using dispatch queues at first but got stuck. This may be just the opportunity to get me over the stumbling block! This is the crucial bit of code that I can't figure out how to translate to dispatch queues:
>
> static IONotificationPortRef __NotifyPort;
>
> // add notification port and run loop source for async notifications
>
> __NotifyPort = IONotificationPortCreate(masterPort);


> runLoopSource = IONotificationPortGetRunLoopSource(__NotifyPort);
> __MeasatRunLoop = CFRunLoopGetCurrent(),
> CFRunLoopAddSource(__MeasatRunLoop, runLoopSource, kCFRunLoopDefaultMode);


instead of these three lines instead, all that should be needed is

IONotificationPortSetDispatchQueue(__NotifyPort, some_queue)

with some_queue the dispatch queue on which you want IOKit to invoke your callbacks

> // set up notification to detect plugging of Measat without firmware
>
> kr = IOServiceAddMatchingNotification( __NotifyPort,
> kIOFirstMatchNotification,
> matchingDict,
> RawDeviceAdded,
> NULL,
> &__RawAddedIter );
>
> I see dispatch_source_create as a candidate to replace CFRunLoopAddSource but what dispatch source type should I use? There's one for Mach receive and one for Mach send. Which one should I use with the Mach port behind the IO Notification Port? I'm assuming here that I need to get hold of the underlying Mach port.

IONotificationPortSetDispatchQueue() will set up a MACH_RECV dispatch source and handles mach message reception & decoding for you.

You would have to do this yourself if you were to setup your own DISPATCH_SOURCE_TYPE_MACH_RECV source on the port returned by IONotificationPortGetMachPort() (which is probably not even possible with the messages sent by IOKit), a MACH_RECV dispatch source only notifies you when messages are available on the port, it does not receive or decode them.

Cheers,

Daniel _______________________________________________

Kevin Van Vechten

unread,
Apr 21, 2010, 4:07:52 PM4/21/10
to Daniel Steffen, Darwin Dev
And in general, if there's a framework that is providing an API that returns a CFRunLoopSourceRef or schedules an object with a run loop but does not have a dispatch source equivalent, please file an enhancement request at http://bugreporter.apple.com/

Kevin _______________________________________________

James Peach

unread,
Apr 21, 2010, 7:13:26 PM4/21/10
to Daniel A. Steffen, Darwin Dev
On 21 April 2010 12:57, Daniel A. Steffen <dste...@apple.com> wrote:
> Hi Joel,
>
> On Apr 21, 2010, at 12:05 PM, Joel Reymont wrote:
>
>> I looked at using dispatch queues at first but got stuck. This may be just the opportunity to get me over the stumbling block! This is the crucial bit of code that I can't figure out how to translate to dispatch queues:
>>
>> static IONotificationPortRef __NotifyPort;
>>
>>  // add notification port and run loop source for async notifications
>>
>>  __NotifyPort = IONotificationPortCreate(masterPort);
>
>
>>  runLoopSource = IONotificationPortGetRunLoopSource(__NotifyPort);
>>  __MeasatRunLoop = CFRunLoopGetCurrent(),
>>  CFRunLoopAddSource(__MeasatRunLoop, runLoopSource, kCFRunLoopDefaultMode);
>
>
> instead of these three lines instead, all that should be needed is
>
>        IONotificationPortSetDispatchQueue(__NotifyPort, some_queue)

That's not a public API, see

<http://www.opensource.apple.com/source/IOKitUser/IOKitUser-514.8.1/IOKitLibPrivate.h>

--
James Peach | jor...@gmail.com

Daniel Markarian

unread,
Apr 21, 2010, 10:13:18 PM4/21/10
to James Peach, Darwin Dev
Hey James,

We expect to make IONotificationPortSetDispatchQueue() public in the next major release. You can use it safely.

Dan
Reply all
Reply to author
Forward
0 new messages