美文网首页
CocoaLumberjack GCD 使用(1)

CocoaLumberjack GCD 使用(1)

作者: 老猫_2017 | 来源:发表于2020-01-21 10:41 被阅读0次
// create concurrent queue
dispatch_queue_t _queue;
_queue = dispatch_queue_create("cocoa.lumberjack.multiformatter", DISPATCH_QUEUE_CONCURRENT);

// sync concurrent queue 多读,并发执行
- (NSString *)formatLogMessage:(DDLogMessage *)logMessage {
    __block NSString *line = logMessage->_message;

    dispatch_sync(_queue, ^{
        for (id<DDLogFormatter> formatter in self->_formatters) {
            DDLogMessage *message = [self logMessageForLine:line originalMessage:logMessage];
            line = [formatter formatLogMessage:message];

            if (!line) {
                break;
            }
        }
    });

    return line;
}
// 多读,并发执行
- (NSArray *)formatters {
    __block NSArray *formatters;

    dispatch_sync(_queue, ^{
        formatters = [self->_formatters copy];
    });

    return formatters;
}

- (BOOL)isFormattingWithFormatter:(id<DDLogFormatter>)formatter {
    __block BOOL hasFormatter;

    dispatch_sync(_queue, ^{
        hasFormatter = [self->_formatters containsObject:formatter];
    });

    return hasFormatter;
}
// 异步 独写
- (void)addFormatter:(id<DDLogFormatter>)formatter {
    dispatch_barrier_async(_queue, ^{
        [self->_formatters addObject:formatter];
    });
}

- (void)removeFormatter:(id<DDLogFormatter>)formatter {
    dispatch_barrier_async(_queue, ^{
        [self->_formatters removeObject:formatter];
    });
}

- (void)removeAllFormatters {
    dispatch_barrier_async(_queue, ^{
        [self->_formatters removeAllObjects];
    });
}

并发读,单写 dispatch_barrier_async, dispatch_sync 并发读

// create timer
_saveTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.loggerQueue);

// set event handler
dispatch_source_set_event_handler(_saveTimer, ^{ @autoreleasepool {
                                                            [self performSaveAndSuspendSaveTimer];
                                                        } });


// start source
dispatch_resume(_deleteTimer);

// source cancel 
dispatch_source_cancel(_deleteTimer);

source timer, gcd的定时器实现,可以cancel, 可以 resume, 可以 set event hander 等.

// 监听系统的通知
notify_register_dispatch(kNotifyASLDBUpdate, &notifyToken, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(int token)
        {
            // At least one message has been posted; build a search query.
            @autoreleasepool
            {
                aslmsg query = asl_new(ASL_TYPE_QUERY);
                char stringValue[64];

                if (lastSeenID > 0) {
                    snprintf(stringValue, sizeof stringValue, "%llu", lastSeenID);
                    asl_set_query(query, ASL_KEY_MSG_ID, stringValue, ASL_QUERY_OP_GREATER | ASL_QUERY_OP_NUMERIC);
                } else {
                    snprintf(stringValue, sizeof stringValue, "%llu", startTime);
                    asl_set_query(query, ASL_KEY_TIME, stringValue, ASL_QUERY_OP_GREATER_EQUAL | ASL_QUERY_OP_NUMERIC);
                }

                [self configureAslQuery:query];

                // Iterate over new messages.
                aslmsg msg;
                aslresponse response = asl_search(NULL, query);
                
                while ((msg = asl_next(response)))
                {
                    [self aslMessageReceived:msg];

                    // Keep track of which messages we've seen.
                    lastSeenID = (unsigned long long)atoll(asl_get(msg, ASL_KEY_MSG_ID));
                }
                asl_release(response);
                asl_free(query);

                if (_cancel) {
                    notify_cancel(token);
                    return;
                }

            }
        });

int notifyToken = 0; 
// Can be used to unregister with notify_cancel().

notify_register_dispatch_ 接收系统的通知信息. 可以做进程,线程的处理.

notify_cancel 可以关闭通知

// async 异步操作,并发删除文件,没过block ,都独立触发
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                // Since we just created a new log file, we may need to delete some old log files
                [self deleteOldLogFiles];
            });


// create vnode source 监控文件的变化 flags 来确定变化的部分
dispatch_source_vnode_flags_t flags = DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE;
    _currentLogFileVnode = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,
                                                        (uintptr_t)[_currentLogFileHandle fileDescriptor],
                                                        flags,
                                                        _loggerQueue);

// set vnode event handler
__weak __auto_type weakSelf = self;
    dispatch_source_set_event_handler(_currentLogFileVnode, ^{ @autoreleasepool {
        NSLogInfo(@"DDFileLogger: Current logfile was moved. Rolling it and creating a new one");
        [weakSelf lt_rollLogFileNow];
    } });

// cancel vnode
dispatch_source_t vnode = _currentLogFileVnode;
    dispatch_source_set_cancel_handler(_currentLogFileVnode, ^{
        dispatch_release(vnode);
    });

// start source
    dispatch_resume(_currentLogFileVnode);


// cancel source 
if (_currentLogFileVnode) {
        dispatch_source_cancel(_currentLogFileVnode);
        _currentLogFileVnode = NULL;
    }

// create timer    
_rollingTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _loggerQueue);

// cacel source timer
if (_rollingTimer) {
        dispatch_source_cancel(_rollingTimer);
        _rollingTimer = NULL;
    }

// timer hander
__weak __auto_type weakSelf = self;
    dispatch_source_set_event_handler(_rollingTimer, ^{ @autoreleasepool {
        [weakSelf lt_maybeRollLogFileDueToAge];
    } });

// timer cancel
dispatch_source_t theRollingTimer = _rollingTimer;
    dispatch_source_set_cancel_handler(_rollingTimer, ^{
        dispatch_release(theRollingTimer);
    });

// set timer
static NSTimeInterval const kDDMaxTimerDelay = LLONG_MAX / NSEC_PER_SEC;
    int64_t delay = (int64_t)(MIN([logFileRollingDate timeIntervalSinceNow], kDDMaxTimerDelay) * (NSTimeInterval) NSEC_PER_SEC);
    dispatch_time_t fireTime = dispatch_time(DISPATCH_TIME_NOW, delay);

    dispatch_source_set_timer(_rollingTimer, fireTime, DISPATCH_TIME_FOREVER, (uint64_t)kDDRollingLeeway * NSEC_PER_SEC);
// start timer
    dispatch_resume(_rollingTimer);

// 串行队列执行任务,保证资源释放安全
- (void)dealloc {
    if (self.isOnInternalLoggerQueue) {
        [self lt_cleanup];
    } else {
        dispatch_sync(self.loggerQueue, ^{
            [self lt_cleanup];
        });
    }
}

Source timer 不用说了

source vnode 监控文件, 文件变更时,能收到事件通知.

block 内部执行频繁操作,可以 @autoreleasepool 来辅助优化控制内存

相关文章

  • CocoaLumberjack GCD 使用(1)

    并发读,单写 dispatch_barrier_async, dispatch_sync 并发读 source t...

  • CocoaLumberjack GCD 使用(2)

    group 保证多任务,完成通知semaphore 保证限制处理的资源数量,进行的数量控制Dispatch_get...

  • iOS调试篇(一)——日志重定向篇

    1 CocoaLumberjack 使用开源第三方库CocoaLumberjack。 2 hook 使用fishh...

  • 全量日志

    1 CocoaLumberjack 使用开源第三方库CocoaLumberjack。 2 hook 使用fishh...

  • iOS - Log

    一、CocoaLumberjack 项目中的日志系统可以通过 CocoaLumberjack 实现,目前使用过 D...

  • CocoaLumberjack使用

    一 利用cocopods 安装CocoaLumberjack(2.2.0) 1.必须要定义 打印级别 DDLog ...

  • xcode Log 插件

    1. 安装XcodeColors插件 2、下载CocoaLumberjack开源框架 3、使用 #ifdef DE...

  • 多线程之GCD

    GCD介绍 1、GCD简介 2、GCD任务和队列 3、GCD 的基本使用 4、GCD 线程间的通信 5、GCD 的...

  • GCD多线程详解

    1. GCD 简介 2. GCD 任务和队列 3. GCD 的使用步骤 4. GCD 的基本使用(6种不同组合区别...

  • iOS面试--GCD常见用法

    项目中常见的GCD用法有已下几种: 1.GCD栅栏函数2.GCD快速迭代(遍历)3.GCD队列组的使用 1.GCD...

网友评论

      本文标题:CocoaLumberjack GCD 使用(1)

      本文链接:https://www.haomeiwen.com/subject/npfezctx.html