在Swift中使用libevent和GCD(libdispatch)
我正在
Swift 3中创建一个服务器端应用程序.我选择了libevent来实现网络代码,因为它是跨平台的并且不会遇到C10k问题. Libevent实现了它自己的事件循环,但我想保持CFRunLoop和GCD(DispatchQueue.main.after等)的功能,所以我需要以某种方式粘贴它们.
这就是我想出的: var terminated = false DispatchQueue.main.after(when: DispatchTime.now() + 3) { print("Dispatch works!") terminated = true } while !terminated { switch event_base_loop(eventBase,EVLOOP_NONBLOCK) { // libevent case 1: break // No events were processed case 0: print("DEBUG: Libevent processed one or more events") default: // -1 print("Unhandled error in network backend") exit(1) } RunLoop.current().run(mode: RunLoopMode.defaultRunLoopMode,before: Date(timeIntervalSinceNow: 0.01)) } 这有效,但引入了0.01秒的延迟.当RunLoop正在休眠时,libevent将无法处理事件.当应用程序空闲时,降低此超时会显着增加CPU使用率. 我也在考虑只使用libevent,但是项目中的第三方库可以在内部使用dispatch_async,因此这可能会有问题. 在另一个线程中运行libevent的循环会使同步变得更加复杂,这是解决此延迟问题的唯一方法吗? LINUX更新.上面的代码在Linux上不起作用(2016-07-25-a Swift snapshot),RunLoop.current().run存在但有错误.下面是一个有效的Linux版本,用timer和dispatch_main重新实现.它遇到了相同的延迟问题: let queue = dispatch_get_main_queue() let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,queue) let interval = 0.01 let block: () -> () = { guard !terminated else { print("Quitting") exit(0) } switch server.loop() { case 1: break // Just idling case 0: break //print("Libevent: processed event(s)") default: // -1 print("Unhandled error in network backend") exit(1) } } block() let fireTime = dispatch_time(DISPATCH_TIME_NOW,Int64(interval * Double(NSEC_PER_SEC))) dispatch_source_set_timer(timer,fireTime,UInt64(interval * Double(NSEC_PER_SEC)),UInt64(NSEC_PER_SEC) / 10) dispatch_source_set_event_handler(timer,block) dispatch_resume(timer) dispatch_main() 解决方法
在GitHub上快速搜索Open Source Swift Foundation库可以发现CFRunLoop中的支持(可能显然)在不同平台上的实现方式不同.从本质上讲,这意味着RunLoop和libevent就跨平台而言,只是实现同样事物的不同方式.我可以看到libevent可能更适合服务器实现的思想背后的想法,因为CFRunLoop并没有随着特定的目标而成长,但就跨平台而言,它们都在同一棵树上咆哮.
也就是说,RunLoop和libevent使用的底层同步原语本质上是私有的实现细节,更重要的是,平台之间可能不同.从源代码来看,看起来RunLoop在Linux上使用epoll,libevent也是如此,但在macOS / iOS /等上,RunLoop将使用Mach端口作为其基本原语,但libevent看起来似乎会使用kqueue.您可以通过足够的努力,创建一个与给定平台的自由源相关联的混合RunLoopSource,但这可能非常脆弱,而且通常是不明智的,原因如下:首先,它将是基于RunLoop的私有实现细节,这些细节不属于公共API,因此可能随时更改,恕不另行通知.其次,假设你没有通过并为swift和libevent支持的每个平台执行此操作,那么你就会破坏它的跨平台性,这是你在第一时间与libevent一起讨论的原因之一. 您可能没有考虑过的另一个选项是在没有RunLoops的情况下单独使用GCD.查看 如果你被绑定并决定在同一个应用程序中同时使用RunLoop和libevent,那么,正如你所猜测的那样,最好将libevent放在自己独立的线程中,但我认为它并不像你想象的那么复杂.您应该可以自由地从libevent回调中调度dispas_async,并且类似地编组来自GCD托管线程的回复,以便相当容易地使用libevent的多线程机制(即通过锁定运行,或者通过将调用编组为libevent作为事件本身).同样,即使您选择使用libevent的循环结构,使用GCD的第三方库也不应成为问题. GCD管理自己的线程池,无法踩到libevent的主循环等. 您可能还会考虑构建应用程序,使得您使用的并发和连接处理库无关紧要.然后你可以换掉libevent,GCD,CFStreams等(或混合搭配),具体取决于对给定情况或部署最有效的方法.选择并发方法很重要,但理想情况下,如果情况需要,您就不会将自己与自己紧密联系起来. 当你拥有这样的架构时,我通常会喜欢使用最高级别抽象来完成工作的方法,并且只有在特定情况需要时才会降低到较低级别的抽象.在这种情况下,这可能意味着使用CFStreams和RunLoops启动,并切换到“裸”GCD或稍后解放,如果你碰壁并且还确定(通过经验测量)它是传输层而不是应用程序层是限制因素.很少有非平凡的应用程序实际上解决了传输层中的C10K问题;事情往往必须首先在应用层“扩展”,至少对于比基本消息传递更复杂的应用程序. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |