fix mac disconnection crash due to asynchronous operations
This commit is contained in:
@@ -51,7 +51,7 @@
|
||||
|
||||
IOBluetoothUserNotification* disconnectNotification;
|
||||
|
||||
NSMutableArray* receivedData; // a queue os NSData*
|
||||
NSMutableArray* receivedData; // a queue of NSObject<WiiuseReceivedMessage>*
|
||||
NSLock* receivedDataLock;
|
||||
}
|
||||
|
||||
@@ -66,4 +66,20 @@
|
||||
@end
|
||||
|
||||
|
||||
@protocol WiiuseReceivedMessage <NSObject>
|
||||
- (int) applyToStruct: (wiimote*) wm; // <0: not copied, 0: copied empty, >0: copied
|
||||
@end
|
||||
|
||||
@interface WiiuseReceivedData : NSObject<WiiuseReceivedMessage> {
|
||||
NSData* data;
|
||||
}
|
||||
- (id) initWithBytes: (void*) bytes length: (NSUInteger) length;
|
||||
- (id) initWithData: (NSData*) data;
|
||||
@end
|
||||
|
||||
@interface WiiuseDisconnectionMessage : NSObject<WiiuseReceivedMessage> {
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
@@ -142,32 +142,33 @@
|
||||
|
||||
- (void) disconnected:(IOBluetoothUserNotification*) notification fromDevice:(IOBluetoothDevice*) device {
|
||||
|
||||
wiiuse_disconnected(wm);
|
||||
WiiuseDisconnectionMessage* message = [[WiiuseDisconnectionMessage alloc] init];
|
||||
[receivedDataLock lock];
|
||||
[receivedData addObject:message];
|
||||
[receivedDataLock unlock];
|
||||
[message release];
|
||||
}
|
||||
|
||||
#pragma mark read, write
|
||||
|
||||
// <0: nothing received, else: length of data received (can be 0 in case of disconnection message)
|
||||
- (int) checkForAvailableData {
|
||||
unsigned int length = 0;
|
||||
int result = -1;
|
||||
|
||||
[receivedDataLock lock];
|
||||
if([receivedData count]) {
|
||||
// pop first item from queue
|
||||
NSData* firstData = [receivedData objectAtIndex:0];
|
||||
[receivedData removeObjectAtIndex:0];
|
||||
|
||||
byte* data = (byte*) [firstData bytes];
|
||||
length = [firstData length];
|
||||
|
||||
// forward event data to C struct
|
||||
memcpy(wm->event_buf, data, sizeof(wm->event_buf));
|
||||
// look at first item in queue
|
||||
NSObject<WiiuseReceivedMessage>* firstMessage = [receivedData objectAtIndex:0];
|
||||
result = [firstMessage applyToStruct:wm];
|
||||
if(result >= 0)
|
||||
[receivedData removeObjectAtIndex:0];
|
||||
}
|
||||
[receivedDataLock unlock];
|
||||
|
||||
return length;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void) waitForInclomingData: (NSTimeInterval) duration {
|
||||
- (void) waitForIncomingData: (NSTimeInterval) duration {
|
||||
NSDate* timeoutDate = [NSDate dateWithTimeIntervalSinceNow: duration];
|
||||
NSRunLoop *theRL = [NSRunLoop currentRunLoop];
|
||||
while (true) {
|
||||
@@ -193,18 +194,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
// result = length of data copied to event buffer
|
||||
- (int) read {
|
||||
// is there already some data to read?
|
||||
int result = [self checkForAvailableData];
|
||||
if(!result) {
|
||||
// wait a short amount of time, until data becomes available
|
||||
[self waitForInclomingData:1];
|
||||
if(result < 0) {
|
||||
// wait a short amount of time, until data becomes available or a timeoutis reached
|
||||
[self waitForIncomingData:1];
|
||||
|
||||
// check again
|
||||
result = [self checkForAvailableData];
|
||||
}
|
||||
|
||||
return result;
|
||||
return result >= 0 ? result : 0;
|
||||
}
|
||||
|
||||
- (int) writeBuffer: (byte*) buffer length: (NSUInteger) length {
|
||||
@@ -266,7 +268,7 @@
|
||||
}
|
||||
|
||||
// copy the data into the buffer
|
||||
NSData* newData = [[NSData alloc] initWithBytes:data length:length];
|
||||
WiiuseReceivedData* newData = [[WiiuseReceivedData alloc] initWithBytes: data length: length];
|
||||
[receivedDataLock lock];
|
||||
[receivedData addObject: newData];
|
||||
[receivedDataLock unlock];
|
||||
@@ -275,4 +277,52 @@
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark WiiuseReceivedMessage
|
||||
|
||||
@implementation WiiuseReceivedData
|
||||
|
||||
- (id) initWithData:(NSData *)data_ {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
data = [data_ retain];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (id) initWithBytes: (void*) bytes length: (NSUInteger) length {
|
||||
NSData* data_ = [[NSData alloc] initWithBytes:bytes length:length];
|
||||
id result = [self initWithData: data_];
|
||||
[data_ release];
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
[data release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (int) applyToStruct:(wiimote *)wm {
|
||||
byte* bytes = (byte*) [data bytes];
|
||||
NSUInteger length = [data length];
|
||||
if(length > sizeof(wm->event_buf)) {
|
||||
WIIUSE_WARNING("Received data was longer than event buffer. Dropping excess bytes.");
|
||||
length = sizeof(wm->event_buf);
|
||||
}
|
||||
memcpy(wm->event_buf, bytes, length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation WiiuseDisconnectionMessage
|
||||
|
||||
- (int) applyToStruct:(wiimote *)wm {
|
||||
wiiuse_disconnected(wm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
@@ -149,13 +149,14 @@ int wiiuse_os_poll(struct wiimote_t** wm, int wiimotes) {
|
||||
if (wiiuse_os_read(wm[i])) {
|
||||
/* propagate the event, messages should be read as in linux, starting from the second element */
|
||||
propagate_event(wm[i], wm[i]->event_buf[1], wm[i]->event_buf+2);
|
||||
evnt += (wm[i]->event != WIIUSE_NONE);
|
||||
|
||||
/* clear out the event buffer */
|
||||
memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf));
|
||||
} else {
|
||||
idle_cycle(wm[i]);
|
||||
}
|
||||
|
||||
evnt += (wm[i]->event != WIIUSE_NONE);
|
||||
}
|
||||
|
||||
return evnt;
|
||||
|
||||
@@ -85,6 +85,7 @@ void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes) {
|
||||
|
||||
for (; i < wiimotes; ++i) {
|
||||
wiiuse_disconnect(wm[i]);
|
||||
wiiuse_cleanup_platform_fields(wm[i]);
|
||||
free(wm[i]);
|
||||
}
|
||||
|
||||
@@ -177,8 +178,6 @@ void wiiuse_disconnected(struct wiimote_t* wm) {
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
|
||||
|
||||
/* reset a bunch of stuff */
|
||||
wiiuse_cleanup_platform_fields(wm);
|
||||
|
||||
wm->leds = 0;
|
||||
wm->state = WIIMOTE_INIT_STATES;
|
||||
wm->read_req = NULL;
|
||||
|
||||
Reference in New Issue
Block a user