iOS runloop 内部构造

runloop

 runloop 死循环,运行循环, 事件循环。

我们打开手机,app一直运行不会退出,当我们操作app时,app会立即给我们相应的响应,依赖的就是runloop;

runloop 作用:

  •  运行循环,保证线程不退出,一直运行
  • 当任务来时,会唤醒线程执行任务
  • 没有任务时,线程进入休眠状态,节省系统资源

在OSX/iOS 系统中,runloop相关对象:NSRunLoop 和 CFRunLoopRef。 

 

CFRunloopRef源码 

首先了解几个结构体

__CFRunLoop 

  • __CFRunLoop
  • __CFRunLoopMode
  • __CFRunLoopSource
  • __CFRunLoopObserver
  • __CFRunLoopTimer
struct __CFRunLoop {
    CFRuntimeBase _base;
    pthread_mutex_t _lock;			/* locked for accessing mode list */
    __CFPort _wakeUpPort;			// used for CFRunLoopWakeUp 
    Boolean _unused;
    volatile _per_run_data *_perRunData;              // reset for runs of the run loop
    pthread_t _pthread; //runloop所在的线程 每一个runloop对应一个线程
    uint32_t _winthread;
    CFMutableSetRef _commonModes; // 存储commonMode中的mode 默认commonMode 中含有两个mode
    CFMutableSetRef _commonModeItems; //存储commonModelItem中的(source, observer, timer)
    CFRunLoopModeRef _currentMode; //runloop当前所在的mode
    CFMutableSetRef _modes; //__CFRunLoopMode 一个线程中存在多个mode
    struct _block_item *_blocks_head;
    struct _block_item *_blocks_tail;
    CFTypeRef _counterpart;
};

使用 timer需要加入到commonModel下 默认commonModel中包含kCFRunLoopDefaultMode 和 UITrackingRunLoopMode;

kCFRunLoopDefaultMode 正常状态, UITrackingRunLoopMode scrollView 滚动状态

__CFRunLoopMode 

  • 一个runloop 对应一个线程
  • 一个runloop 中对应多个mode
  • 切换mode需要退出当前mode,mode中的item时独立存在,在当前mode下只能处理当前mode对应的 commonModelItem,同一时间runloop只存在一种mode状态
  • commonMode对应多个mode,添加进commonMode的item,循环添加进commonModel中所有mode中 
struct __CFRunLoopMode {
    CFRuntimeBase _base;
    pthread_mutex_t _lock;	/* must have the run loop locked before locking this */
    CFStringRef _name;
    Boolean _stopped;
    char _padding[3];
    CFMutableSetRef _sources0; //当前mode下source0
    CFMutableSetRef _sources1; //当前mode下source1
    CFMutableArrayRef _observers; //当前mode下observer 
    CFMutableArrayRef _timers;    //当前mode下timer 
    CFMutableDictionaryRef _portToV1SourceMap;
    __CFPortSet _portSet; //基于mach_port的source1
    CFIndex _observerMask;
#if USE_DISPATCH_SOURCE_FOR_TIMERS
    dispatch_source_t _timerSource;
    dispatch_queue_t _queue;
    Boolean _timerFired; // set to true by the source when a timer has fired
    Boolean _dispatchTimerArmed;
#endif
#if USE_MK_TIMER_TOO
    mach_port_t _timerPort;
    Boolean _mkTimerArmed;
#endif
#if DEPLOYMENT_TARGET_WINDOWS
    DWORD _msgQMask;
    void (*_msgPump)(void);
#endif
    uint64_t _timerSoftDeadline; /* TSR */
    uint64_t _timerHardDeadline; /* TSR */
};

CF_INLINE void __CFRunLoopModeLock(CFRunLoopModeRef rlm) {
    pthread_mutex_lock(&(rlm->_lock));
    //CFLog(6, CFSTR("__CFRunLoopModeLock locked %p"), rlm);
}
  • 可以多个 source0/source1,observer,timer,timer 
  • 当mode为__CFRunLoop的currentMode (source0/source1,observer,timer,timer )才会执行

 __CFRunLoopSource

struct __CFRunLoopSource {
    CFRuntimeBase _base;
    uint32_t _bits;
    pthread_mutex_t _lock;
    CFIndex _order;			/* immutable */
    CFMutableBagRef _runLoops;
    union {
	CFRunLoopSourceContext version0;	/* immutable, except invalidation */
        CFRunLoopSourceContext1 version1;	/* immutable, except invalidation */
    } _context;
};

事件源,只有source0和source1

  •  Source0 只包含了一个回调(函数指针),它并不能主动触发事件。使用时,你需要先调用 CFRunLoopSourceSignal(source),将这个 Source 标记为待处理,然后手动调用 CFRunLoopWakeUp(runloop) 来唤醒 RunLoop,让其处理这个事件。
  • source1包含一个mach_port和回调指针,source1用于内核和其他线程直接的消息,source1能唤醒线程。

 __CFRunLoopObserver

struct __CFRunLoopObserver {
    CFRuntimeBase _base;
    pthread_mutex_t _lock;
    CFRunLoopRef _runLoop; //runloop 观察的runloop
    CFIndex _rlCount;
    CFOptionFlags _activities;		/* immutable */ //runloop状态
    CFIndex _order;			/* immutable */
    CFRunLoopObserverCallBack _callout;	/* immutable */ 回调指针
    CFRunLoopObserverContext _context;	/* immutable, except invalidation */
};

__CFRunLoopObserver 包含观察的runloop 和回调指针,当runloop状态变化时,回调用回调函数 回调时间点

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry         = (1UL << 0), // 即将进入Loop
    kCFRunLoopBeforeTimers  = (1UL << 1), // 即将处理 Timer
    kCFRunLoopBeforeSources = (1UL << 2), // 即将处理 Source
    kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
    kCFRunLoopAfterWaiting  = (1UL << 6), // 刚从休眠中唤醒
    kCFRunLoopExit          = (1UL << 7), // 即将退出Loop
};

 __CFRunLoopTimer

struct __CFRunLoopTimer {
    CFRuntimeBase _base;
    uint16_t _bits;
    pthread_mutex_t _lock;
    CFRunLoopRef _runLoop; //runloop 
    CFMutableSetRef _rlModes; //加入的mode
    CFAbsoluteTime _nextFireDate;
    CFTimeInterval _interval;//间隔		/* immutable */
    CFTimeInterval _tolerance;//误差          /* mutable */
    uint64_t _fireTSR;			/* TSR units */
    CFIndex _order;			/* immutable */
    CFRunLoopTimerCallBack _callout;	/* immutable */ //回调
    CFRunLoopTimerContext _context;	/* immutable, except invalidation */
};

 CFRunLoopTimerRef 是基于时间的触发器,它和 NSTimer 是toll-free bridged 的,可以混用。其包含一个时间长度和一个回调(函数指针)。当其加入到 RunLoop 时,RunLoop会注册对应的时间点,当时间点到时,RunLoop会被唤醒以执行那个回调。

他们的关系是:

参考资料:

深入理解runloop

runloop 官方文档

分数阶傅里叶变换(Fractional Fourier Transform, FRFT)是对传统傅里叶变换的拓展,它通过非整数阶的变换方式,能够更有效地处理非线性信号以及涉及时频局部化的问题。在信号处理领域,FRFT尤其适用于分析非平稳信号,例如在雷达、声纳和通信系统中,对线性调频(Linear Frequency Modulation, LFM)信号的分析具有显著优势。LFM信号是一种频率随时间线性变化的信号,因其具有宽频带和良好的时频分辨率,被广泛应用于雷达和通信系统。FRFT能够更精准地捕捉LFM信号的时间和频率信息,相比普通傅里叶变换,其性能更为出色。 MATLAB是一种强大的数值计算和科学计算工具,拥有丰富的函数库和用户友好的界面。在MATLAB中实现FRFT,通常需要编写自定义函数或利用信号处理工具箱中的相关函数。例如,一个名为“frft”的文件可能是用于执行分数阶傅里叶变换的MATLAB脚本或函数,并展示其在信号处理中的应用。FRFT的正确性验证通常通过对比变换前后信号的特性来完成,比如评估信号的重构质量、信噪比等。具体而言,可以通过计算原始信号与经过FRFT处理后的信号之间的相似度,或者对比LFM信号的关键参数(如初始频率、扫频率和持续时间)是否在变换后得到准确恢复。 在MATLAB代码实现中,通常包含以下步骤:首先,生成LFM信号模型,设定其初始频率、扫频率、持续时间和采样率等参数;其次,利用自定义的frft函数对LFM信号进行分数阶傅里叶变换;接着,使用MATLAB的可视化工具(如plot或imagesc)展示原始信号的时域和频域表示,以及FRFT后的结果,以便直观对比;最后,通过计算均方误差、峰值信噪比等指标来评估FRFT的性能。深入理解FRFT的数学原理并结合MATLAB编程技巧,可以实现对LFM信号的有效分析和处理。这个代码示例不仅展示了理论知识在
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值