Skip to content

Commit 8aedb4f

Browse files
authored
Merge pull request #34 from Zewo/fd
Remove handle and add write and read to fd
2 parents e81c3f7 + 9f8a358 commit 8aedb4f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1558
-3088
lines changed

.jazzy.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ xcodebuild_arguments:
99
- Venice
1010

1111
custom_categories:
12-
- name: Handles
13-
children:
14-
- Handle
15-
1612
- name: Coroutines
1713
children:
1814
- Coroutine

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import PackageDescription
3131

3232
let package = Package(
3333
dependencies: [
34-
.Package(url: "https://github.com/Zewo/Venice.git", majorVersion: 0, minor: 17)
34+
.Package(url: "https://github.com/Zewo/Venice.git", majorVersion: 0, minor: 18)
3535
]
3636
)
3737
```
@@ -54,7 +54,7 @@ What you end up with is a tree of coroutines rooted in the `main` function. This
5454

5555
![call-tree](http://libdill.org/index3.jpeg "Call Tree")
5656

57-
Venice implements structured concurrency by allowing you to close a running coroutine.
57+
Venice implements structured concurrency by allowing you to cancel a running coroutine.
5858

5959
```swift
6060
let coroutine = try Coroutine {
@@ -71,12 +71,12 @@ let coroutine = try Coroutine {
7171
}
7272

7373
try Coroutine.wakeUp(1.second.fromNow())
74-
try coroutine.close()
74+
coroutine.cancel()
7575
```
7676

77-
When a coroutine is being closed all blocking calls will start to throw `VeniceError.canceled`. On one hand, this forces the function to finish quickly (there's not much you can do without blocking functions); on the other hand, it provides an opportunity for cleanup.
77+
When a coroutine is being canceled all coroutine-blocking calls will start to throw `VeniceError.canceledCoroutine`. On one hand, this forces the function to finish quickly (there's not much you can do without coroutine-blocking functions); on the other hand, it provides an opportunity for cleanup.
7878

79-
In the example above, when `coroutine.close` is called the call to `Coroutine.wakeUp` inside the coroutine will throw `VeniceError.canceled` and then the `defer` statement will run, thus releasing the memory allocated for `resource`.
79+
In the example above, when `coroutine.cancel` is called the call to `Coroutine.wakeUp` inside the coroutine will throw `VeniceError.canceledCoroutine` and then the `defer` statement will run, thus releasing the memory allocated for `resource`.
8080

8181
# Threads
8282

Sources/Venice/Channel.swift

Lines changed: 105 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -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

208207
extension 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

Comments
 (0)