/* pipe_source.m clang pipe_source.m -o pipe -framework Foundation -D [ USE_SOURCE | USE_IO | USE_FILEHANDLE [ FILEHANDLE_READABILITY | FILEHANDLE_WAIT ] ] */ #import <Foundation/Foundation.h> int main(void) { enum RunLoop { Dispatch, RunLoop, } runLoop = Dispatch; int filedes[2]; int pipeError = pipe(filedes); if (pipeError != 0) { fprintf(stderr, "couldn't create pipe, error: %d\n", errno); return 1; } int readFd = filedes[0], writeFd = filedes[1]; /// // Read Strategy #if defined(USE_SOURCE) dispatch_source_t readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, readFd, 0, dispatch_get_main_queue()); dispatch_source_set_cancel_handler(readSource, ^{ fprintf(stderr, "closing read fd\n"); close(readFd); }); dispatch_source_set_event_handler(readSource, ^{ uint8_t buffer[1024]; int readCount = read(readFd, buffer, sizeof(buffer)); fprintf(stderr, "read %d bytes\n", readCount); bool done = (readCount == 0); if (done) { fprintf(stderr, "EOF encountered\n"); dispatch_source_cancel(readSource); exit(0); } }); dispatch_resume(readSource); #elif defined(USE_IO) dispatch_io_t readChannel = dispatch_io_create(DISPATCH_IO_STREAM, readFd, dispatch_get_main_queue(), ^(int error) { close(readFd); }); dispatch_io_set_interval(readChannel, NSEC_PER_SEC / 2, DISPATCH_IO_STRICT_INTERVAL); __block int readCount = 0; dispatch_io_read(readChannel, 0, SIZE_MAX, dispatch_get_main_queue(), ^(bool done, dispatch_data_t data, int error) { fprintf(stderr, "readCount: %d done: %d dataSize: %ld error: %d\n", ++readCount, done, dispatch_data_get_size(data), error); if (done) { fprintf(stderr, "EOF encountered\n"); dispatch_io_close(readChannel, 0); exit(0); } }); #elif defined(USE_FILEHANDLE) NSFileHandle *readHandle = [[NSFileHandle alloc] initWithFileDescriptor:readFd closeOnDealloc:YES]; #if defined(FILEHANDLE_READABILITY) // EOF is not encountered readHandle.readabilityHandler = ^(NSFileHandle *readHandle) { int readCount = readHandle.availableData.length; fprintf(stderr, "read %d bytes\n", readCount); bool done = (readCount == 0); if (done) { fprintf(stderr, "EOF encountered\n"); exit(0); } }; #elif defined(FILEHANDLE_WAIT) // EOF is encountered id readObserver = [NSNotificationCenter.defaultCenter addObserverForName:NSFileHandleDataAvailableNotification object:readHandle queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification *notification) { int readCount = readHandle.availableData.length; fprintf(stderr, "read %d bytes\n", readCount); bool done = (readCount == 0); if (done) { fprintf(stderr, "EOF encountered\n"); exit(0); } [readHandle waitForDataInBackgroundAndNotify]; }]; [readHandle waitForDataInBackgroundAndNotify]; #else #error no file handle strategy defined #endif runLoop = RunLoop; #else #error no read strategy defined #endif /// // Write char *const output = "Hello, world."; write(writeFd, output, 6); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ write(writeFd, output + 6, 7); close(writeFd); }); /// // Event Loop switch (runLoop) { case Dispatch: dispatch_main(); case RunLoop: [NSRunLoop.currentRunLoop run]; } }