This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <sys/select.h> | |
void MonitorFiles( int fileDescriptor1, int fileDescriptor2 ) | |
{ | |
fd_set allFileDescriptorSet; | |
FD_ZERO( &allFileDescriptorSet ); | |
FD_SET( fileDescriptor1, &allFileDescriptorSet ); | |
FD_SET( fileDescriptor2, &allFileDescriptorSet ); | |
int maxFileDescriptor = MAX( fileDescriptor1, fileDescriptor2 ); | |
for( ;; ) | |
{ | |
fd_set readFileDescriptorSet = allFileDescriptorSet; | |
int readyCount = select( maxFileDescriptor + 1, &readFileDescriptorSet, NULL, NULL, NULL ); | |
if( readyCount < 0 ) | |
{ | |
// Error | |
break; | |
} | |
if( FD_ISSET( fileDescriptor1, &readFileDescriptorSet ) ) | |
{ | |
// Read data from fileDescriptor1 | |
} | |
if( FD_ISSET( fileDescriptor2, &readFileDescriptorSet ) ) | |
{ | |
// Read data from fileDescriptor2 | |
} | |
} | |
} |
The kqueue API is similar to select, and has the same limitations with respect to blocking threads.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void MonitorFiles( int fileDescriptor1, int fileDescriptor2 ) | |
{ | |
int kq = kqueue(); | |
if( kq < 0 ) | |
{ | |
// Error | |
return; | |
} | |
struct kevent monitorList[2]; | |
EV_SET( &monitorList[0], fileDescriptor1, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0 ); | |
EV_SET( &monitorList[1], fileDescriptor2, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0 ); | |
struct kevent eventList[2]; | |
for( ;; ) | |
{ | |
int eventCount = kevent( kq, monitorList, 2, eventList, 2, NULL ); | |
if( eventCount < 0 ) | |
{ | |
// Error | |
break; | |
} | |
for( int i = 0; i < eventCount; i++ ) | |
{ | |
// Check eventList[i].flags for errors | |
// eventList[i].ident is the file descriptor that triggered | |
// the read event | |
readDataFromFileDescriptor( eventList[i].ident ); | |
} | |
} | |
close( kq ); | |
} |
Using libdispatch is a better option for GUI applications. The file descriptors can be monitored on a background thread and processed on the main thread.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void MonitorFileDescriptors( int fileDescriptor1, int fileDescriptor2 ) | |
{ | |
dispatch_source_t fd1Source = dispatch_source_create( DISPATCH_SOURCE_TYPE_READ, fileDescriptor1, 0UL, dispatch_get_main_queue() ); | |
dispatch_source_set_event_handler( fd1Source, ^{ readDataFromFileDescriptor( fileDescriptor1 ); } ); | |
dispatch_source_set_cancel_handler( fd1Source, ^{ | |
dispatch_release( fd1Source ); | |
close( fileDescriptor1 ); | |
} ); | |
dispatch_resume( fd1Source ); | |
dispatch_source_t fd2Source = dispatch_source_create( DISPATCH_SOURCE_TYPE_READ, fileDescriptor2, 0UL, dispatch_get_main_queue() ); | |
dispatch_source_set_event_handler( fd2Source, ^{ readDataFromFileDescriptor( fileDescriptor2 ); } ); | |
dispatch_source_set_cancel_handler( fd2Source, ^{ | |
dispatch_release( fd2Source ); | |
close( fileDescriptor2 ); | |
} ); | |
dispatch_resume( fd2Source ); | |
// Must call either dispatch_main(), [[NSRunLoop currentRunLoop] run], or CFRunLoopRun() | |
} |
Using NSFileHandle is an even simpler option for GUI applications. The only caveat is that the readability handler is called on a random thread. If you need to update your UI in response to something read from the file descriptor, you will need to move over to the main thread.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void MonitorFiles( int fileDescriptor1, int fileDescriptor2 ) | |
{ | |
NSFileHandle * fh1 = [[NSFileHandle alloc] initWithFileDescriptor:fileDescriptor1 closeOnDealloc:NO]; | |
fh1.readabilityHandler = ^( NSFileHandle *fh ) { | |
// readabilityHandler is called on a random thread. Move it back to the main thread | |
dispatch_sync( dispatch_get_main_thread(), ^{ readDataFromFileDescriptor( fh.fileDescriptor ) } ); | |
}] | |
NSFileHandle * fh2 = [[NSFileHandle alloc] initWithFileDescriptor:fileDescriptor2 closeOnDealloc:NO]; | |
fh2.readabilityHandler = ^( NSFileHandle *fh ) { | |
// readabilityHandler is called on a random thread. Move it back to the main thread | |
dispatch_sync( dispatch_get_main_thread(), ^{ readDataFromFileDescriptor( fh.fileDescriptor ) } ); | |
}] | |
// Must call either [[NSRunLoop currentRunLoop] run] or CFRunLoopRun() | |
} |
No comments:
Post a Comment