github.com/github.com/noppoMan/Prorsum

A Go like concurrent system + networking/http library for Swift that works on Linux and Mac


Keywords
channel, event-driven, go, goroutine, http, server-side-swift, socket, swift3, tcp, udp, websocket
License
MIT

Documentation

Prorsum

A Go like current system for Swift

⚠️ Prorsum is in early development and pretty experimental.

Features

  • OperationQueue based Concurrent System
  • WaitGroup
  • Once
  • Channels
  • Channel Iteration
  • Select
  • Timers

Installation

Currenty Prorsum supports only SPM.

SPM

import PackageDescription

let package = Package(
    name: "MyApp",
    dependencies: [
        .Package(url: "https://github.com/noppoMan/Prorsum.git", majorVersion: 0, minor: 1),
    ]
)

Cocoapods

Not supported yet

Carthage

Not supported yet

Usage

go

go is an alias of OperationQueue.addOperation { }

func asyncTask(){
  print(Thread.current)
}

go(asyncTask())

go {
  print(Thread.current)
}

WaitGroup

A WaitGroup waits for a collection of BlockOperations to finish. The main BlockOperation calls Add to set the number of BlockOperations to wait for. Then each of the BlockOperations runs and calls Done when finished. At the same time, Wait can be used to block until all BlockOperations have finished.

let wg = WaitGrpup()

wg.add(1)
go {
    sleep(1)
    print("wg: 1")
    wg.done()
}

wg.add(1)
go {
    sleep(1)
    print("wg: 2")
    wg.done()
}

wg.wait() // block unitle twice wg.done() is called.

print("wg done")

Channel<Element>

Channels are the pipes that connect concurrent operation. You can send values into channels from one BlockOperation and receive those values into another BlockOperation.

let ch = Channel<String>.make(capacity: 1)

func asyncSend(){
  try! ch.send("Expecto patronum!")
}

go(asyncSend()) // => Expecto patronum!

go {
  try! ch.send("Accio!")
}

try! ch.receive() // => Accio!

ch.close()

select

The select statement lets a BlockOperation wait on multiple communication operations.

let magicCh = Channel<String>.make(capacity: 1)

go {
  try! magicCh.send("Obliviate")
}

select {
  when(magicCh) {
    print($0)
  }

  otherwise {
    print("otherwise")
  }
}

forSelect

Generally You need to wrap the select inside a while loop. To make it easier to work with this pattern You can use forSelect. forSelect will loop until done() is called.

let magicCh = Channel<String>.make(capacity: 1)
let doneCh = Channel<String>.make(capacity: 1)

go {
  try! magicCh.send("Crucio")
  try! magicCh.send("Imperio")
}

go {
  try! doneCh.send("Avada Kedavra!")
}

select { done in
  when(magicCh) {
    print($0)
  }

  when(doneCh) {
    done() // break current loop
  }

  otherwise {
    print("otherwise")
  }
}

License

Prorsum is released under the MIT license. See LICENSE for details.