自定义输入源
根据苹果官方文档说明,基于端口的源(Source1
)由内核自动发出信号,定制源(Source0
)必须从另一个线程手动发出信号
定制源Source0
创建custom input source
需要定义以下内容:
- 您希望输入源处理的信息。
- 一个调度函数(
scheduler
),让感兴趣的客户端知道如何联系输入源。 - 执行任何客户机发送的请求的处理函数(
handler
)。 - 用于使输入源无效的取消函数(
cancellation
)。
在本例中,应用程序的Main Thread
维护对Input Source
的引用、该Input Source
的自定义命令缓冲区以及安装输入源的运行循环。当Main Thread
有一个任务要传递给Worker Thread
时,它会向Command Buffer
发送一个命令以及Worker Thread
启动任务所需的任何信息。(因为Worker Thread
的Input Source
和Main Thread
都可以访问Command Buffer
,所以必须同步访问。)一旦发出命令,Main Thread
就向Input Source
发出信号,并唤醒Worker Thread
的Runloop
。在接收到wake up
命令后,Runloop
调用Input Source
的处理程序,该处理程序处理在Command Buffer
中找到的命令。
可以在主线程直接通过激活子线程的souce0,在子线程做一些事情。
附上demo https://pan.baidu.com/s/10Ao5VJgnHwC2oJSAP_5WbQ 密码:xgta
下面讲解如何实现:
自定义输入源
需要使用Core Foundation
来配置Runloop源
并将其附加到Runloop
。尽管基本的处理程序是基于C的函数,但这并不妨碍您为这些函数编写包装器,并使用Objective-C或c++实现代码主体。
@interface RunLoopSource : NSObject
{
CFRunLoopSourceRef runLoopSource;
NSMutableArray* commands;
}
- (id)init;
- (void)addToCurrentRunLoop;
- (void)invalidate;
// Handler method
- (void)sourceFired;
// Client interface for registering commands to process
- (void)addCommand:(NSInteger)command withData:(id)data;
- (void)fireAllCommandsOnRunLoop:(CFRunLoopRef)runloop;
@end
// These are the CFRunLoopSourceRef callback functions.
void RunLoopSourceScheduleRoutine (void *info, CFRunLoopRef rl, CFStringRef mode);
void RunLoopSourcePerformRoutine (void *info);
void RunLoopSourceCancelRoutine (void *info, CFRunLoopRef rl, CFStringRef mode);
// RunLoopContext is a container object used during registration of the input source.
@interface RunLoopContext : NSObject
{
CFRunLoopRef runLoop;
RunLoopSource* source;
}
@property (readonly) CFRunLoopRef runLoop;
@property (readonly) RunLoopSource* source;
- (id)initWithSource:(RunLoopSource*)src andLoop:(CFRunLoopRef)loop;
@end
回调函数
source0加入回调
RunLoopSourceScheduleRoutine
回调会在你把自定义Source0
加入到Runloop时,就进行回调。
我们会将source0
封装到一个Context
中后注册到中央代理(HCRunLoopDelegate)
中。当某一方需要通过该source0
触发操作时,他可以通过中央代理
通信,使用Context
对象中的source0
来进行通信。
void RunLoopSourceScheduleRoutine (void *info, CFRunLoopRef rl, CFStringRef mode)
{
NSLog(@"RunLoopSourceScheduleRoutine 对象地址 %p",info);
RunLoopSource* obj = (__bridge RunLoopSource*)(info);
HCRunLoopDelegate* del