Флаг отправки Центрального диспетчерского пункта (GCD)

Недавно я переключился с kqueue на Источники отправки GCD для мониторинга изменений файлов. Это хорошо сработало и привело к значительно более простому API. Я зарегистрировал свой переключатель здесь. Единственная проблема, с которой я сталкиваюсь, заключается в том, что теперь я не могу получить доступ к флагам события, которое я смог в kqueue. Например, с помощью kqueue я смог проверить, был ли файл удален, переименован или его атрибуты были изменены следующим образом:

struct kevent event;

...

if(event.flag & EV_DELETE)
{
    printf("File was deleted\n");
}

Этот API недоступен с GCD или мне нужно настроить источники отправки для каждого флага, который я хотел бы прослушать. Или лучше использовать kqueue, поскольку он обеспечивает большую видимость события, которое произошло.

Ответы

Ответ 1

Я нашел ответ в Concurrency Руководство по программированию. Сначала я посмотрел в GCD Reference, но без везения. Соответствующая строка из руководства была

Для источника отправки дескриптора, который отслеживает активность файловой системы, эта функция возвращает константу, указывающую тип произошедшего события. Список констант см. В перечисляемом типе dispatch_source_vnode_flags_t.

Вот пример того, как вы можете его использовать.

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
int fildes = open("path/to/some/file", O_EVTONLY);
__block dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,fildes, 
                                                  DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_LINK | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE,
                                                  queue);
dispatch_source_set_event_handler(source, ^
{
    unsigned long flags = dispatch_source_get_mask(source);
    if(flags & DISPATCH_VNODE_DELETE)
        printf("DISPATCH_VNODE_DELETE\n");
    if(flags & DISPATCH_VNODE_WRITE)
        printf("DISPATCH_VNODE_WRITE\n");
    if(flags & DISPATCH_VNODE_EXTEND)
        printf("DISPATCH_VNODE_EXTEND\n");
    if(flags & DISPATCH_VNODE_ATTRIB)
        printf("DISPATCH_VNODE_ATTRIB\n");
    if(flags & DISPATCH_VNODE_LINK)
        printf("DISPATCH_VNODE_LINK\n");
    if(flags & DISPATCH_VNODE_RENAME)
        printf("DISPATCH_VNODE_RENAME\n");
    if(flags & DISPATCH_VNODE_REVOKE)
        printf("DISPATCH_VNODE_REVOKE\n");
});
dispatch_source_set_cancel_handler(source, ^(void) 
{
    close(fildes);
});
dispatch_resume(source);

Ответ 2

Вы можете изменить * dispatch_source_get_mask (source) * на * dispatch_source_get_data (source) *, так как dispatch_source_get_mask (source) возвращает все флаги, которые вы передали при создании обработчика вместо генерируемого события.