@@ -8,20 +8,6 @@ import CLibdill
88
99/// A channel is a synchronization primitive.
1010///
11- /// # Threads
12- ///
13- /// You can use Venice in multi-threaded programs.
14- /// However, individual threads are strictly separated.
15- /// You may think of each thread as a separate process.
16- ///
17- /// In particular, a coroutine created in a thread will
18- /// be executed in that same thread, and it will never
19- /// migrate to a different one.
20- ///
21- /// In a similar manner, a handle, such as a channel or
22- /// a coroutine handle, created in one thread cannot be
23- /// used in a different thread.
24- ///
2511/// ## Example:
2612///
2713/// ```swift
@@ -32,9 +18,10 @@ import CLibdill
3218/// }
3319///
3420/// let theAnswer = try channel.receive(deadline: 1.second.fromNow())
35- /// try coroutine.close()
3621/// ```
37- public final class Channel < Type> : Handle {
22+ public final class Channel < Type> {
23+ private typealias Handle = Int32
24+
3825 private enum ChannelResult < Type> {
3926 case value( Type )
4027 case error( Error )
@@ -49,6 +36,7 @@ public final class Channel<Type> : Handle {
4936 }
5037 }
5138
39+ private let handle : Handle
5240 private var buffer = List < ChannelResult < Type > > ( )
5341
5442 /// Creates a channel
@@ -58,39 +46,36 @@ public final class Channel<Type> : Handle {
5846 /// It doesn't store any items.
5947 ///
6048 /// - Throws: The following errors might be thrown:
61- /// #### VeniceError.canceled
62- /// Thrown when the operation is performed within a closed coroutine.
49+ /// #### VeniceError.canceledCoroutine
50+ /// Thrown when the operation is performed within a canceled coroutine.
6351 /// #### VeniceError.outOfMemory
64- /// Thrown when the system doesn't have enough memory to perform the operation.
65- /// #### VeniceError.unexpectedError
66- /// Thrown when an unexpected error occurs.
67- /// This should never happen in the regular flow of an application.
52+ /// Thrown when the system doesn't have enough memory to create a new channel.
6853 public init ( ) throws {
6954 let result = chmake ( 0 )
7055
7156 guard result != - 1 else {
7257 switch errno {
7358 case ECANCELED:
74- throw VeniceError . canceled
59+ throw VeniceError . canceledCoroutine
7560 case ENOMEM:
7661 throw VeniceError . outOfMemory
7762 default :
7863 throw VeniceError . unexpectedError
7964 }
8065 }
8166
82- super . init ( handle: result)
67+ handle = result
8368 }
8469
8570 deinit {
86- try ? close ( )
71+ hclose ( handle )
8772 }
8873
8974 /// Reference to the channel which can only send.
90- public lazy var sendOnly : SendOnly = SendOnly ( self )
75+ public lazy var sending : Sending = Sending ( self )
9176
9277 /// Reference to the channel which can only receive.
93- public lazy var receiveOnly : ReceiveOnly = ReceiveOnly ( self )
78+ public lazy var receiving : Receiving = Receiving ( self )
9479
9580 /// Sends a value to the channel.
9681 public func send( _ value: Type , deadline: Deadline ) throws {
@@ -108,12 +93,10 @@ public final class Channel<Type> : Handle {
10893
10994 guard result == 0 else {
11095 switch errno {
111- case EBADF:
112- throw VeniceError . invalidHandle
11396 case ECANCELED:
114- throw VeniceError . canceled
97+ throw VeniceError . canceledCoroutine
11598 case EPIPE:
116- throw VeniceError . handleIsDone
99+ throw VeniceError . doneChannel
117100 case ETIMEDOUT:
118101 buffer. remove ( node)
119102 throw VeniceError . deadlineReached
@@ -129,12 +112,10 @@ public final class Channel<Type> : Handle {
129112
130113 guard result == 0 else {
131114 switch errno {
132- case EBADF:
133- throw VeniceError . invalidHandle
134115 case ECANCELED:
135- throw VeniceError . canceled
116+ throw VeniceError . canceledCoroutine
136117 case EPIPE:
137- throw VeniceError . handleIsDone
118+ throw VeniceError . doneChannel
138119 case ETIMEDOUT:
139120 throw VeniceError . deadlineReached
140121 default :
@@ -145,36 +126,50 @@ public final class Channel<Type> : Handle {
145126 return try buffer. removeFirst ( ) . getValue ( )
146127 }
147128
129+ /// This function is used to inform the channel that no more `send` or `receive` should be
130+ /// performed on the channel.
131+ ///
132+ /// - Warning:
133+ /// After `done` is called on a channel, any attempts to `send` or `receive`
134+ /// will result in a `VeniceError.doneChannel` error.
135+ public func done( ) {
136+ hdone ( handle, 0 )
137+ }
138+
148139 /// Send-only reference to an existing channel.
149140 ///
150141 /// ## Example:
151142 ///
152143 /// ```swift
153144 /// let channel = Channel<Int>()
154145 ///
155- /// func send(to channel: Channel<Int>.SendOnly ) throws {
146+ /// func send(to channel: Channel<Int>.Sending ) throws {
156147 /// try channel.send(42, deadline: 1.second.fromNow())
157148 /// }
158149 ///
159- /// try send(to: channel.sendOnly )
150+ /// try send(to: channel.sending )
160151 /// ```
161- public final class SendOnly : Handle {
152+ public final class Sending {
162153 private let channel : Channel < Type >
163154
164155 fileprivate init ( _ channel: Channel < Type > ) {
165156 self . channel = channel
166- super. init ( handle: channel. handle)
167157 }
168158
169- /// Sends a value to the channel.
159+ /// :nodoc:
170160 public func send( _ value: Type , deadline: Deadline ) throws {
171161 try channel. send ( value, deadline: deadline)
172162 }
173163
174- /// Sends an error to the channel.
164+ /// :nodoc:
175165 public func send( _ error: Error , deadline: Deadline ) throws {
176166 try channel. send ( error, deadline: deadline)
177167 }
168+
169+ /// :nodoc:
170+ public func done( ) {
171+ channel. done ( )
172+ }
178173 }
179174
180175 /// Receive-only reference to an existing channel.
@@ -184,41 +179,100 @@ public final class Channel<Type> : Handle {
184179 /// ```swift
185180 /// let channel = Channel<Int>()
186181 ///
187- /// func receive(from channel: Channel<Int>.ReceiveOnly ) throws {
182+ /// func receive(from channel: Channel<Int>.Receiving ) throws {
188183 /// let value = try channel.receive(deadline: 1.second.fromNow())
189184 /// }
190185 ///
191- /// try receive(from: channel.receiveOnly )
186+ /// try receive(from: channel.receiving )
192187 /// ```
193- public final class ReceiveOnly : Handle {
188+ public final class Receiving {
194189 private let channel : Channel < Type >
195190
196191 fileprivate init ( _ channel: Channel < Type > ) {
197192 self . channel = channel
198- super. init ( handle: channel. handle)
199193 }
200194
201- /// Receives a value from channel.
195+ /// :nodoc:
202196 @discardableResult public func receive( deadline: Deadline ) throws -> Type {
203197 return try channel. receive ( deadline: deadline)
204198 }
199+
200+ /// :nodoc:
201+ public func done( ) {
202+ channel. done ( )
203+ }
205204 }
206205}
207206
208207extension Channel where Type == Void {
209- /// Sends to the channel.
210- ///
211208 /// :nodoc:
212209 public func send( deadline: Deadline ) throws {
213210 try send ( ( ) , deadline: deadline)
214211 }
215212}
216213
217- extension Channel . SendOnly where Type == Void {
218- /// Sends to the channel.
219- ///
214+ extension Channel . Sending where Type == Void {
220215 /// :nodoc:
221216 public func send( deadline: Deadline ) throws {
222217 try send ( ( ) , deadline: deadline)
223218 }
224219}
220+
221+ class Node < T> {
222+ var value : T
223+ var next : Node < T > ?
224+ weak var previous : Node < T > ?
225+
226+ init ( value: T ) {
227+ self . value = value
228+ }
229+ }
230+
231+ fileprivate class List < T> {
232+ private var head : Node < T > ?
233+ private var tail : Node < T > ?
234+
235+ @discardableResult fileprivate func append( _ value: T ) -> Node < T > {
236+ let newNode = Node ( value: value)
237+
238+ if let tailNode = tail {
239+ newNode. previous = tailNode
240+ tailNode. next = newNode
241+ } else {
242+ head = newNode
243+ }
244+
245+ tail = newNode
246+ return newNode
247+ }
248+
249+ @discardableResult fileprivate func remove( _ node: Node < T > ) -> T {
250+ let prev = node. previous
251+ let next = node. next
252+
253+ if let prev = prev {
254+ prev. next = next
255+ } else {
256+ head = next
257+ }
258+
259+ next? . previous = prev
260+
261+ if next == nil {
262+ tail = prev
263+ }
264+
265+ node. previous = nil
266+ node. next = nil
267+
268+ return node. value
269+ }
270+
271+ @discardableResult fileprivate func removeFirst( ) throws -> T {
272+ guard let head = head else {
273+ throw VeniceError . unexpectedError
274+ }
275+
276+ return remove ( head)
277+ }
278+ }
0 commit comments