@@ -45,12 +45,14 @@ public extension AsyncSocketPool where Self == SocketPool<ePoll> {
45
45
public struct ePoll : EventQueue {
46
46
47
47
private( set) var file : Socket . FileDescriptor
48
+ private( set) var canary : Socket . FileDescriptor
48
49
private( set) var existing : [ Socket . FileDescriptor : Socket . Events ]
49
50
private let eventsLimit : Int
50
51
private let logger : any Logging
51
52
52
53
public init ( maxEvents limit: Int , logger: some Logging = . disabled) {
53
54
self . file = . invalid
55
+ self . canary = . invalid
54
56
self . existing = [ : ]
55
57
self . eventsLimit = limit
56
58
self . logger = logger
@@ -59,19 +61,33 @@ public struct ePoll: EventQueue {
59
61
public mutating func open( ) throws {
60
62
existing = [ : ]
61
63
self . file = try Self . makeQueue ( )
64
+ self . canary = try Self . makeEventTrigger ( )
65
+
66
+ var event = CSystemLinux . epoll_event ( )
67
+ let options : EPOLLEvents = [ EPOLLEvents . edgeTriggered, EPOLLEvents . read]
68
+ event. events = options. rawValue
69
+ event. data. fd = canary. rawValue
70
+ guard epoll_ctl ( file. rawValue, EPOLL_CTL_ADD, canary. rawValue, & event) != - 1 else {
71
+ throw SocketError . makeFailed ( " epoll_ctl EPOLL_CTL_ADD " )
72
+ }
62
73
}
63
74
64
75
public mutating func stop( ) throws {
65
76
existing = [ : ]
66
- guard file != . invalid else {
77
+ guard canary != . invalid else {
67
78
throw SocketError . disconnected
68
79
}
69
- defer { file = . invalid }
70
- try Self . closeQueue ( file: file)
80
+ eventfd_write ( canary. rawValue, 1 ) ;
81
+ canary = . invalid
82
+
71
83
}
72
84
73
85
public mutating func close( ) throws {
74
- // should really close file here
86
+ guard file != . invalid else {
87
+ throw SocketError . disconnected
88
+ }
89
+ defer { file = . invalid }
90
+ try Self . closeQueue ( file: file)
75
91
}
76
92
77
93
public mutating func addEvents( _ events: Socket . Events , for socket: Socket . FileDescriptor ) throws {
@@ -117,22 +133,29 @@ public struct ePoll: EventQueue {
117
133
}
118
134
119
135
public func getNotifications( ) throws -> [ EventNotification ] {
136
+ guard canary != . invalid else {
137
+ throw SocketError . disconnected
138
+ }
120
139
var events = Array ( repeating: epoll_event ( ) , count: eventsLimit)
121
140
let status = CSystemLinux . epoll_wait ( file. rawValue, & events, Int32 ( eventsLimit) , - 1 )
122
141
guard status > 0 else {
123
142
throw SocketError . makeFailed ( " epoll wait " )
124
143
}
125
144
126
- return events
145
+ return try events
127
146
. prefix ( Int ( status) )
128
147
. map ( makeNotification)
129
148
}
130
149
131
- func makeNotification( from event: epoll_event ) -> EventNotification {
150
+ func makeNotification( from event: epoll_event ) throws -> EventNotification {
132
151
var notification = EventNotification . make ( from: event)
133
152
if notification. events. isEmpty, let existing = existing [ notification. file] {
134
153
notification. events = existing
135
154
}
155
+
156
+ if event. data. fd == self . canary. rawValue {
157
+ throw SocketError . disconnected
158
+ }
136
159
return notification
137
160
}
138
161
@@ -144,6 +167,14 @@ public struct ePoll: EventQueue {
144
167
return file
145
168
}
146
169
170
+ static func makeEventTrigger( file: Int32 = CSystemLinux . eventfd ( 0 , Int32 ( EFD_NONBLOCK) ) ) throws -> Socket . FileDescriptor {
171
+ let file = Socket . FileDescriptor ( rawValue: file)
172
+ guard file != . invalid else {
173
+ throw SocketError . makeFailed ( " eventfd " )
174
+ }
175
+ return file
176
+ }
177
+
147
178
static func closeQueue( file: Socket . FileDescriptor ) throws {
148
179
guard file != . invalid else { return }
149
180
guard Socket . close ( file. rawValue) >= 0 else {
@@ -194,6 +225,7 @@ private struct EPOLLEvents: OptionSet, Hashable {
194
225
static let rdhup = EPOLLEvents ( rawValue: EPOLLRDHUP . rawValue)
195
226
static let err = EPOLLEvents ( rawValue: EPOLLERR . rawValue)
196
227
static let pri = EPOLLEvents ( rawValue: EPOLLPRI . rawValue)
228
+ static let edgeTriggered = EPOLLEvents ( rawValue: EPOLLET . rawValue)
197
229
}
198
230
199
231
private extension Socket . Events {
0 commit comments