Reputation: 25
I have a Cocoa app which launches a new NSThread (Thread A) from within applicationDidFinishLaunching
.
Thread A successfully creates an RFCOMM connection then spawns another NSThread (Thread B), passing the established IOBluetoothRFCOMMChannel to Thread B. Thread B creates a IOBluetoothRFCOMMChannelDelegate and calls setDelegate on IOBluetoothRFCOMMChannel with it and then runs its current NSRunLoop. Thread A then waits for Thread B to signal a sync object.
The intent is that, when data arrives, Thread B's NSRunLoop will execute the delegate which copies the received data and signals Thread A to read it.
However, the delegate never gets called because Thread B's NSRunLoop has no input sources. I imagined that setDelegate would create an input source on it. The only way I can get the delegate called is if I have Thread A wait on its own NSRunLoop instead of wait on the sync object. In that case, the delegate gets executed.
But that arrangement will not work for me. Eventually, my code will just be a library that exposes a C API that is a standard and is only suitable as a procedurally flowing set of functions. Thread A will be someone else's Thread (maybe main maybe not) and will call into my library in a procedural way.
1) I thought that the thread/runloop which registered for a delegate callback (Thread B) was the one that would get the input source and execute the callback in its runloop. But Thread A's NSRunLoop gets the input source instead, Why? What's the expected relationship between these things?
2) How can I get Thread B to get the input source and be the thread that executes the delegates?
Thanks for any and all help.
My Thread B is below:
@implementation CBaiHardwareBluetoothEventThread
- (void) runEventThread: (IOBluetoothObjectID)deviceID
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop];
CallbackDelegate* cd = [[CallbackDelegate alloc] init];
IOBluetoothRFCOMMChannel* myOBJCChannel = [IOBluetoothRFCOMMChannel withObjectID:deviceID];
[myOBJCChannel setDelegate:cd];
do{
[myRunLoop runUntilDate:[NSDate distantFuture]];
cout << __FUNCTION__ << " this should not be returning but it is ???" << endl;
usleep(1000000);//avoid the unintentional hard loop that happens
}while(1); //forever for now
[pool release];
}
@end
Upvotes: 2
Views: 604
Reputation: 11594
IOBluetooth and threading is messy. You'll have to work this stuff out by trial and error. If it seems that the callbacks happen on the thread that opened the connection, then you'll have to open the connection on the thread where you need the callbacks. Also, this behavior often changes between OS releases...
Upvotes: 3