timpone
timpone

Reputation: 19929

Actor pattern - what it exactly constitutes

I am doing some objective-C / iOS development and have heard several references to the Actor pattern. In Big Nerd Ranch book, it says:

An actor object is used when you have a long running task and some code that needs to be executed after it completes. This kind of object is given the information it needs to perform the task and callbacks to execute when that task is done. The actor runs on its own thread without any further input and is destroyed when it is finished.

The actor here is used in conjunction with a network call. Is this how the Actor is primarily used? Is it mutually exclusive or complimentary to delegation? The Actor definition seems VERY broad and I am trying to get a better handle on what it means. Also, is it possible to have an Actor in a non-OO environment?

Upvotes: 53

Views: 21449

Answers (2)

yoAlex5
yoAlex5

Reputation: 34175

Swift Actor model

[iOS Thread safe]

actor is a type to share reference type[About] mutable data(var + reference_type they are not thread safe despite of let + reference_type or value_type in general) between tasks in a concurrent environment. Swift Actor is available (from Swift v5.5 iOS v15 and v13 backward compatibility) and solves one of thread-safe[About] problem as Data race[About](without Race condition) in concurrent computation and it is a variation of Actor model.

Official doc

You can use tasks to break up your program into isolated, concurrent pieces. Tasks are isolated from each other, which is what makes it safe for them to run at the same time, but sometimes you need to share some information between tasks. Actors let you safely share information between concurrent code.

  • actor are like a class - reference types but do not support inheritance
  • actor automatically serializes all access to it - only one caller has an access(serial access) to the actor at given time
  • async is created under the hood for isolated(by default) context, that is why you use await while calling actor

Example:

actor MyActor {
    let constant = "MyConstant" //let is thread safe
    var name = "SomeName 1" //read
    
    //write
    func changeName(_ name: String) {
        self.name = name
    }
    
    //nonisolated context to work with thread safe code
    nonisolated func printConstant() {
        print(self.constant)
    }
}

let myActor = MyActor()
Task {
    print(await myActor.name)
    await myActor.changeName("SomeName 2")
    myActor.printConstant()
}

Actor doesn't solve Race condition because any await inside the actor unblocks this actor

Upvotes: 1

Daniel Yankowsky
Daniel Yankowsky

Reputation: 7006

That definition of an Actor actually seems a little restrictive. It certainly doesn't handle Erlang-style actors (or I believe Scala-style actors). In my experience, an actor is something that:

  • Sends and receives messages (each actor has a mailbox)
  • Shares no mutable memory with other actors
  • Is scheduled based on the whims of the runtime. An actor could be given its own thread, but it is more likely that several actors participate in co-operative multithreading in a single thread, or maybe even participate in pre-emptive multithreading.

But fundamentally, an actor is a free-running chunk of code that can receive messages from its environment and can send messages back out to its environment.

Actors are used any time that you need lots (and lots) of stateful little processes. Networking is a common use case, because you don't want to allocate a whole thread to each connection. You want something lighter-weight, so you allocate an actor to each connection, and then schedule the actors on a smaller pool of threads. But networking is certainly not the only use of an actors.

In Erlang, an actor is a function. The function probably tail-calls itself (so it's basically an infinite loop), and it probably has a clean way to self-terminate (the infinite loop has a "break" condition). The loop typically waits for a message from the system, processes it, and then sends out messages to the rest of the system. The Erlang OTP library has some abstractions that eliminate the need to even write the loop, so an OTP actor is implemented as a set of callbacks. In that way, an OTP actor looks a lot like an object.

Upvotes: 66

Related Questions