CocoaPods trunk is moving to be read-only. Read more on the blog, there are 14 months to go.
| TestsTested | ✓ |
| LangLanguage | SwiftSwift |
| License | Custom |
| ReleasedLast Release | Jan 2016 |
| SPMSupports SPM | ✓ |
Maintained by Josh Baker.
Atomic<T> class for numbers and strings.dispatch keyword for firing off background routines.Chan<T> for conncurent communication.Mutex, Cond, Once, WaitGroup Int, Int8, Int16, Int32, Int64, UInt, UInt8, UInt16, UInt32, UInt64, Float, Double, Bool, String
==, !=, &&, ||, <=, >=, >, <, !
+, -, *, /, %, <<, >>, ^, &, &+, &-, &*, ++, --, +=, -=, *=, /=, %=, +=, <<=, >>=, ^=, &=
var anum = IntA(100) // IntA is an alias for Atomic<Int>.
anum += 15 // Adds a value atomically.
let res = anum % 4 // Modulo operation atomically.
print("\(anum) \(res)") // prints '115 3'.Safe adds an uncomplicated method for dispatching routines.
dispatch {
print("Background")
}
print("Foreground")A new Chan<T> class provides a clean and simple model for concurrently sharing objects. Chan<T> is modeled after Go channels.
Sharing Memory by Communicating
let jobs = Chan<Int>(5) // buffered channel
let done = Chan<Bool>() // unbuffered channel
dispatch {
for ;; {
if let j = <-jobs {
print("received job \(j)")
} else {
print("received all jobs")
done <- true
return
}
}
}
for var j = 1; j <= 3; j++ {
jobs <- j
print("sent job \(j)")
}
jobs.close()
print("sent all jobs")
<-doneA channel can also be iterated through.
while let j = <-jobs {
print("received job \(j)")
}
print("received all jobs")The _select keyword is a multiway communications multiplexer that works on multiple channels. _select, _case, and _default start with underscores so that they do not conflict with the select, case, and default syscall and keywords. When a _select encounters multiple channels with data, the chosen _case is selected at random
let jobs1 = Chan<Int>()
let jobs2 = Chan<Int>()
dispatch {
for ;; {
_select {
_case(jobs1){ j in
print("received 1: \(j)")
}
_case(jobs2){ j in
print("received 2: \(j)")
}
}
}
}
for var j = 1; ; j++ {
jobs1 <- (j * 1000)
jobs2 <- (j * 2000)
NSThread.sleepForTimeInterval(1)
}A _select can contain a single _default for non-blocking operations.
_select {
_case(jobs1){ j in
print("received 1: \(j)")
}
_case(jobs2){ j in
print("received 2: \(j)")
}
_default {
print("channels not ready")
}
}Incredibly useful sync APIs.
let m = Mutex()
m.lock()
m.unlock()
m.lock {
// this block is locked
}let c = Cond(Mutex())
c.wait() // wait for signal.
c.wait(0.25) // wait for signal or 250ms to pass.
c.signal() // signal to one wait.
c.broadcast() // signal to all waits.func f(){
print("hey there")
}
let o = Once()
o.doit(f) // runs once
o.doit(f) // noop: cannot run twicelet dosomething : (NSTimeInterval, WaitGroup)->() = { (delay, wg) in
NSThread.sleepForTimeInterval(delay)
print("Function in background, duration: \(delay)")
wg.done()
}
let wg = WaitGroup()
wg.add(1)
dispatch { dosomething(0.40, wg) }
wg.add(1)
dispatch { dosomething(0.30, wg) }
wg.add(1)
dispatch { dosomething(0.15, wg) }
wg.add(1)
dispatch { dosomething(0.60, wg) }
wg.wait()
print("done")Copy the Source/*.swift file into your project.
There is no need for import Safe when manually installing.
Josh Baker @tidwall
The Safe source code is available under the MIT License.