Pure Swift concurrency
Asked Answered
P

4

4

All the libraries I have come across that provide Swift concurrency functionality either depend on an Objective-C library or are wrappers around the C based GCD. (iOS and OS X)

I'm just wondering if anyone knows of a pure Swift concurrency library? No dependencies. Or if not how might we go about making one?

Paperboy answered 3/3, 2016 at 11:42 Comment(0)
I
4

The Swift language doesn't have constructs to support concurrency yet. Rumor has it that those are going to be added to a future version of the language, but in the meantime, I don't think you can do this without OS support.

GCD makes for fairly clean concurrent solutions in Swift, since GCD blocks are Swift closures. It's not platform-indpendent, however. (At least not outside the Apple ecosystem.)

Edit:

I guess you could write a concurrency library that would run on all POSIX-compliant OS's by using POSIX, but Windows isn't really POSIX-compliant, so that might not be a perfect solution either.

Edit #2:

In Swift 3 the GCD interface has been cleaned up and made much more "Swifty". Now there is a Dispatch class, that has class methods to do the things that used to use global functions.

Iatric answered 3/3, 2016 at 11:52 Comment(0)
K
0

You can create a simple abstraction of queue-based dispatching like this:

protocol OperationQueue {
    var suspended: Bool { get set }
    var operationCount: Int { get }
    func addOperationWithBlock(block: () -> Void)
    func cancelAllOperations()
    func waitUntilAllOperationsAreFinished()
}

Then, on OS X (or any other Apple platform), you could use GCD directly:

extension NSOperationQueue: OperationQueue { }

And on all other systems, you could create your own implementations:

class POSIXOperationQueue: OperationQueue { /* implementation with pthread */ }
class Win32OperationQueue: OperationQueue { /* implementation with Win32 API */ }
Kemberlykemble answered 28/3, 2016 at 10:30 Comment(0)
F
0

As of Swift 5.5, Swift now supports concurrency with built-in language features such as async/await, Tasks, TaskGroups, Actors and Structured Concurrency.

Fredette answered 12/9, 2022 at 21:0 Comment(0)
H
0

Swift Concurrency

[Concurrency vs Parallelism]
[Sync vs Async]

Official doc

Swift has built-in support for writing asynchronous and parallel code in a structured way.

It is a kind of from Swift v5.5 iOS v15 and v13 backward compatibility

solves:

  • callback hell
  • error handling(using native try/catch mechanism)
  • natural, straight-line code which is simple to read, write and support

High level structure:

  • await/async markers for recognising async block and run it. You are able to use withCheckedThrowingContinuation and withCheckedContinuation inside callback to support await/async
    • await async func
    • await async let
    • await Actor)
  • Task - create a concurrent environment in which await/async is allowed, it is stared immediately after creation, can be prioritized duting creation and can be canceled, has it's own lifetime as a result - current state. Task.init(priority:operation:) creates unstructured concurrency(doesn't have a parent task)
    • Task Group - allow to run parallel(more dynamic then await async let) tasks and all off them done - task group is finished. When you use TaskGroup.addTask or await async let creates Structured concurrency because it has explicit parent-child relationship between task and taskGroup
  • [Actor] - share mutable referance_type data between tasks in a concurrent environment which prevents Data race

Example:

func runImageTask() {
    let imageSaver = ImageSaver()
    Task.init {
        do {
            let url = URL(string: "https://www.google.com/images/branding/googlelogo/2x/googlelogo_dark_color_272x92dp.png")!
            guard let image = try await self.downloadImage(from: url) else { return }
            try await imageSaver.storeImage(image)
            guard let transformedImage = try await self.transformImage(image) else { return }
            try await imageSaver.storeImage(transformedImage)
            
            self.showImage(transformedImage)
        } catch {
            print("error:\(error)")
        }
    }
}

func downloadImage(from url: URL) async throws -> UIImage? {
    let (data, response) = try await URLSession.shared.data(from: url)
    return UIImage(data: data)
}

func transformImage(_ image: UIImage) async throws -> UIImage? {
    return try await withCheckedThrowingContinuation { continuation in
        DispatchQueue.global().async {
            UIGraphicsBeginImageContext(image.size)
            image.draw(at: CGPoint.zero)

            guard let context = UIGraphicsGetCurrentContext() else {
                continuation.resume(with: .failure(NSError(domain: "context is nil", code: 1)))
                return
            }

            context.setStrokeColor(UIColor.green.cgColor)
            context.setLineWidth(5)
            context.addEllipse(in: CGRect(x: 50, y: 50, width: 50, height: 50))
            context.drawPath(using: .stroke)

            let transformedImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
             
            continuation.resume(with: .success(transformedImage))
        }
    }
    
}

func showImage(_ image: UIImage) {
    self.imageView.image = image
}

class ImageSaver: NSObject {
    var continuation: CheckedContinuation<Void, Error>? = nil
    
    func storeImage(_ image: UIImage) async throws {
        return try await withCheckedThrowingContinuation { continuation in
            self.continuation = continuation
            UIImageWriteToSavedPhotosAlbum(image, self, #selector(saveCompleted), nil)
        }
    }

    @objc func saveCompleted(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        let result: Result<(), Error>
        if let error = error {
            result = .failure(error)
        } else {
            result = .success(())
        }
        self.continuation?.resume(with: result)
    }
}

[Kotlin Coroutine]

Hummocky answered 28/1, 2023 at 14:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.