-
Notifications
You must be signed in to change notification settings - Fork 40
/
Copy pathContext.swift
298 lines (249 loc) · 9.13 KB
/
Context.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
//
// Copyright (c) 2016-2017 Ahmad M. Zawawi (azawawi)
//
// This package is distributed under the terms of the MIT license.
// Please see the accompanying LICENSE file for the full text of the license.
//
extension SwiftyZeroMQ {
/**
This represents a ZeroMQ context
*/
public class Context: Hashable {
/**
This is the low-level context pointer handle. Please be extra
careful while using this one otherwise crashes and memory leaks may
occur.
*/
public var handle : UnsafeMutableRawPointer?
/**
This is used internally to manage context handle cleanup in
deinitialization
*/
private var cleanupNeeded : Bool
/**
Create a new ZeroMQ context
- throws: ZeroMQError
*/
public init() throws {
let contextHandle = zmq_ctx_new()
if contextHandle == nil {
throw ZeroMQError.last
}
handle = contextHandle
cleanupNeeded = true
}
/**
Called automatically by garbage collector to terminate context
*/
deinit {
guard cleanupNeeded else {
// No need to cleanup, user has already done that
return
}
do {
try terminate()
} catch {
print(error)
}
}
/**
Shutdown the current context without terminating the current context
*/
public func shutdown() throws {
guard handle != nil else {
return
}
let result = zmq_ctx_shutdown(handle)
if result == -1 {
throw ZeroMQError.last
} else {
handle = nil
cleanupNeeded = false
}
}
/**
Terminate the current context and block until all open sockets
are closed or their linger period has expired
*/
public func terminate() throws {
guard handle != nil else {
// No need to terminate
return
}
let result = zmq_ctx_term(handle)
if result == -1 {
throw ZeroMQError.last
} else {
handle = nil
}
}
/**
An alias for `terminate`
*/
public func close() throws {
try terminate()
}
/**
Returns a ZMQ socket with the type provided
- parameters:
- type: socket type of type SocketType
- returns: a ZeroMQ socket with the type provided
*/
public func socket(_ type : SwiftyZeroMQ.SocketType) throws -> Socket {
return try Socket(context: self, type: type)
}
/**
Returns the current context option value (private)
- parameters:
- name: option name
- returns: the option value
*/
private func getOption(_ name : Int32) throws -> Int32 {
let result = zmq_ctx_get(handle, name)
if result == -1 {
throw ZeroMQError.last
}
return result
}
/**
Sets the current context option value (private)
- parameters:
- name: the option name
- value: the option value to be set
*/
private func setOption(_ name: Int32, _ value: Int32) throws {
let result = zmq_ctx_set(handle, name, value)
if result == -1 {
throw ZeroMQError.last
}
}
/**
Returns whether the `terminate` method call will block forever or
not. Default option value is true.
By default the context will block, forever, on a `.terminate` call.
The assumption behind this behavior is that abrupt termination will
cause message loss. Most real applications use some form of
handshaking to ensure applications receive termination messages, and
then terminate the context with `socket.setLinger(0)` on all
sockets. This setting is an easier way to get the same result. When
it is set to false, all new sockets are given a linger timeout of
zero. **You must still close all sockets before calling terminate.**
*/
public func isBlocky() throws -> Bool {
return try getOption(ZMQ_BLOCKY) == 1
}
/**
Sets whether the `terminate` method call will block forever or not.
Default option value is true.
By default the context will block, forever, on a `.terminate` call.
The assumption behind this behavior is that abrupt termination will
cause message loss. Most real applications use some form of
handshaking to ensure applications receive termination messages, and
then terminate the context with `socket.setLinger(0)` on all
sockets. This setting is an easier way to get the same result. When
it is set to false, all new sockets are given a linger timeout of
zero. **You must still close all sockets before calling terminate.**
*/
public func setBlocky(_ enabled : Bool = true) throws {
try setOption(ZMQ_BLOCKY, enabled ? 1 : 0)
}
/**
Returns the number of I/O threads for the current context
Default value is 1 (read and write)
returns: The number of I/O threads for the current context
*/
public func getIOThreads() throws -> Int {
return try Int(getOption(ZMQ_IO_THREADS))
}
/**
Sets the number of I/O threads for the current context
Default value is 1 (read and write)
*/
public func setIOThreads(_ value : Int = 1) throws {
try setOption(ZMQ_IO_THREADS, Int32(value))
}
/**
Sets the scheduling policy for I/O threads for the current context
Default value is -1 (write only)
*/
public func setThreadSchedulingPolicy(_ value : Int = -1) throws {
try setOption(ZMQ_THREAD_SCHED_POLICY, Int32(value))
}
/**
Sets the scheduling priority for I/O threads for the current context
Default value is -1 (write only)
*/
public func setThreadPriority(_ value : Int = -1) throws {
try setOption(ZMQ_THREAD_PRIORITY, Int32(value))
}
/**
Returns the maximum allowed size of a message sent in the current
context. Default value is Int32.max (i.e. 2147483647).
Default value is Int32.max (i.e. 2147483647)
*/
public func getMaxMessageSize() throws -> Int {
return try Int(getOption(ZMQ_MAX_MSGSZ))
}
/**
Sets the maximum allowed size of a message sent in the current
context. Default value is Int32.max (i.e. 2147483647).
*/
public func setMaxMessageSize(_ size : Int = Int(Int32.max)) throws {
try setOption(ZMQ_MAX_MSGSZ, Int32(size))
}
/**
Returns the maximum number of sockets associated with the current
context
Default value is 1024 (read/write)
*/
public func getMaxSockets() throws -> Int {
return try Int(getOption(ZMQ_MAX_SOCKETS))
}
/**
Sets the maximum number of sockets associated with the current
context
Default value is 1024 (read/write)
*/
public func setMaxSockets(_ value : Int = 1024) throws {
try setOption(ZMQ_MAX_SOCKETS, Int32(value))
}
/**
Returns whether the IPV6 is enabled or not for the current context
Default value is false (read/write)
*/
public func isIPV6Enabled() throws -> Bool {
return try getOption(ZMQ_IPV6) == 1
}
/**
Sets whether the IPV6 is enabled or not for the current context
Default value is false (read/write)
*/
public func setIPV6Enabled(_ enabled : Bool = false) throws {
try setOption(ZMQ_IPV6, enabled ? 1 : 0)
}
/**
The maximum socket limit associated with the current context
Default value: (read only)
*/
public func getSocketLimit() throws -> Int {
return try Int(getOption(ZMQ_SOCKET_LIMIT))
}
/**
Hashable implementation
*/
public var hashValue: Int {
if let hashValue = handle?.hashValue {
return hashValue
}
else {
return 0 // todo: not clear what this corresponds to...
}
}
/**
Equatable implementation (inherited from Hashable)
*/
public static func ==(lhs: Context, rhs: Context) -> Bool {
return lhs.handle == rhs.handle
}
}
}