I'm just playing with some GCD functions for writing and reading data to files. Two of these functions are dispatch_write()
and dispatch_read()
, which allow one to write and read data to a file descriptor without having to setup a new dispatch_io_t
channel.
So, I have the following code:
#import <dispatch/dispatch.h>
#import <stdio.h>
#import <unistd.h>
int main() {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
int intbuffer[] = { 1, 2, 3, 4 };
dispatch_data_t data = dispatch_data_create(intbuffer, 4 * sizeof(int), queue, NULL);
// Write
dispatch_fd_t fd = open("data.dat", O_RDWR);
printf("FD: %d\n", fd);
dispatch_write(fd, data, queue,^(dispatch_data_t d, int e) {
printf("Written %zu bytes!\n", dispatch_data_get_size(d));
printf("\tError: %d\n", e);
});
close(fd);
// Read
fd = open("data.dat", O_RDWR);
dispatch_read(fd, 4 * sizeof(int), queue, ^(dispatch_data_t d, int e) {
printf("Read %zu bytes!\n", dispatch_data_get_size(d));
printf("\tError: %d\n", e);
});
close(fd);
// Exit confirmation
getchar();
return 0;
}
with which I'm attempting to write a 4-integer array to a file and, after that, to read it back. I previously created data.dat
with the touch
command and anyone has full access to it (sudo chmod 777 data.dat
).
When I execute this code, it seems data.dat
gets open successfully, since the program prints out FD: 3
, which is a valid file descriptor, but dispatch_write
doesn't write anything to it, since I get:
Written 0 bytes!
Error: 9
Read 0 bytes!
Error: 9
Error 9 is the code for a EBADF
error, but, again, 3 is a valid file descriptor.
So, what am I doing wrong?
dispatch_read
and dispatch_write
are not synchronous calls -- that's their whole point. In other words, the way you have it set up here, you close
the file descriptor right after calling dispatch_write
. By the time GCD goes to perform the write on a background thread, the file descriptor is already closed. Same for the read operation. You have to wait until the write operation is finished before you close the file.
I reworked your code a little bit to use a dispatch_semaphore
to wait for the writes and reads to complete before closing the file:
int main() {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
int intbuffer[] = { 1, 2, 3, 4 };
dispatch_data_t data = dispatch_data_create(intbuffer, 4 * sizeof(int), queue, NULL);
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
// Write
dispatch_fd_t fd = open("/tmp/data.dat", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
printf("FD: %d\n", fd);
dispatch_write(fd, data, queue,^(dispatch_data_t d, int e) {
printf("Written %zu bytes!\n", dispatch_data_get_size(data) - (d ? dispatch_data_get_size(d) : 0));
printf("\tError: %d\n", e);
dispatch_semaphore_signal(sem);
});
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
close(fd);
// Read
fd = open("/tmp/data.dat", O_RDWR);
dispatch_read(fd, 4 * sizeof(int), queue, ^(dispatch_data_t d, int e) {
printf("Read %zu bytes!\n", dispatch_data_get_size(d));
printf("\tError: %d\n", e);
dispatch_semaphore_signal(sem);
});
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
close(fd);
// Exit confirmation
getchar();
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With