concept actor in category functional programming

This is an excerpt from Manning's book Functional Programming with Kotlin MEAP V07.
To implement
map2
, we’ll use a non-blocking concurrency primitive called actors. AnActor
is essentially a concurrent process that doesn’t constantly occupy a thread. Instead, it only occupies a thread when it receives a message. Importantly, although multiple threads may be concurrently sending messages to an actor, the actor processes only one message at a time, queueing other messages for subsequent processing. This makes them useful as a concurrency primitive when writing tricky code that must be accessed by multiple threads, and which would otherwise be prone to race conditions or deadlocks.It’s best to illustrate this with an example. Many implementations of actors would suit our purposes just fine, but in the interest of simplicity we’ll use our own minimal actor implementation included with the chapter code in the file
actor.kt
. We’ll interact with it through the use of some client code to get a feel of how it works. We begin by getting the actor up and running.Listing 7.21. Setting up an actor to handle client requests
val es: ExecutorService = Executors.newFixedThreadPool(4) #1 val s = Strategy.from(es) #2 val echoer = Actor<String>(s) { #3 println("got message: $it") }Now that we have the instance of the actor referenced by
echoer
, we can send some messages.echoer.send("hello") #1 //got message: hello #2 echoer.send("goodbye") #3 //got message: goodbye echoer.send("You're just repeating everything I say, aren't you?") //got message: You're just repeating everything I say, aren't you?It’s not essential to understand the
Actor
implementation. A correct and efficient implementation is rather subtle, but if you’re curious, see theactor.kt
file in the chapter code. The implementation is under 100 lines of ordinary Kotlin code. The hardest part in understanding an actor implementation is the fact that multiple threads may be messaging the actor simultaneously. The implementation needs to ensure that messages are processed one at a time, and also that all messages sent to the actor will eventually be processed, rather than being queued indefinitely. Even so, the code ends up being concise.

This is an excerpt from Manning's book Functional Programming in C++.
This is the idea behind actors. In the actor model, actors are completely isolated entities that share nothing but can send messages to one another. The minimum that an actor class should have is a way to receive and send messages (see figure 12.2).
Figure 12.2 An actor is an isolated component that can receive and send messages. It processes the messages serially; for each message, it can change its state or behavior, or it can send a new message to another actor in the system.
![]()
Traditionally, actors can send and receive different types of messages, and each actor can choose which actor to send the message to. Also, communication should be asynchronous.
Actor frameworks for C++
You can find a complete implementation of the traditional actor model for C++ at http://actor-framework.org and use it in your projects. The C++ Actor Framework has an impressive set of features. The actors are lightweight concurrent processes (much lighter-weight than threads), and it’s network-transparent, meaning you can distribute actors over multiple separate machines and your program will work without the need to change your code. Although traditional actors aren’t easily composed, they can easily be made to fit into the design covered in this chapter.
An alternative to the C++ Actor Framework is the SObjectizer library (https://sourceforge.net/projects/sobjectizer). It often provides better performance, but it has no built-in support for distributing actors across separate processes.
In this chapter, we’ll define a more rudimentary actor compared to actors as specified by the actor model and actors in the C++ Actor Framework, because we want to focus more on the software design than on implementing a true actor model (see figure 12.3). Although the design of actors presented in this chapter differs from the design of actors in the traditional actor model, the concepts presented are applicable with traditional actors.
You’ll design actors as follows:
Actors can receive only messages of a single type and send messages of a single (not necessarily the same) type. If you need to support multiple different types for input or output messages, you can use std::variant
orstd::any
, as shown in chapter 9.Instead of allowing each actor to choose to whom to send a message, you’ll leave this choice to an external controller so you can compose the actors in a functional way. The external controller will schedule which sources an actor should listen to.
The following listing shows the actor interface.
Listing 12.1 Minimal interface for an actor
template <typename SourceMessageType, #1 typename MessageType> #1 class actor { public: using value_type = MessageType; #4 void process_message(SourceMessageType&& message); #2 template <typename EmitFunction> void set_message_handler(EmitFunction emit); #3 private: std::function<void(MessageType&&)> m_emit; #3 }; #1 An actor can receive messages of one type and send messages of another. #4 Defines the type of the message the actor is sending, so you can check it later when you need to connect actors #2 Handles a new message arriving #3 Sets the m_emit handler the actor calls when it wants to send a messageThis interface clearly states that an actor only knows how to receive a message and how to send a message onward. It can have as much private data as it needs to perform its work, but none of it should ever be available to the outside world. Because the data can’t be shared, you have no need for any synchronization on it.

This is an excerpt from Manning's book Functional Programming in C#: How to write better C# code.
For these reasons, I’ll concentrate on message-passing concurrency in the rest of this chapter, and especially agent-based concurrency. You’ll later see how agents and actors differ in more detail. Let’s begin by looking at message-passing concurrency as a programming model.
Agents and actors are closely related. In both cases, a single thread processes messages sequentially and communicates with other actors/agents by sending them messages. There are also important differences:
Agents run within a single process, whereas actors are designed for distributed systems. In the examples we’ve looked at so far, a reference to an agent refers to a specific instance in the current process. References to actors, on the other hand, are location-transparent; that is, when you have a reference to an actor, that actor may be running in the same process or on another process, possibly on a remote machine. So a reference to an agent is a pointer, whereas a reference to an actor is an ID that the actor model implementation will use to route messages across processes as appropriate.

This is an excerpt from Manning's book Functional Programming in Java: How functional techniques improve your Java programs.
As part of message processing, actors can send messages to other actors. Messages are sent asynchronously, which means there’s no answer to wait for. As soon as a message is sent, the sender can continue its job, which mostly consists of processing, one at a time, a queue of messages it receives. Of course, handling the message queue means that there are some concurrent accesses to the queue to manage. But this management is abstracted in the actor framework, so you, the programmer, don’t need to worry about this.
Of course, answers to messages might be needed. Suppose an actor is responsible for a long computation. The client can take advantage of asynchronicity by continuing its own job while the computation is handled for it. But once the computation is done, there must be a way for the client to receive the result. This is simply done by having the actor responsible for the computation call back its client and send it the result, once again in an asynchronous way. Note that the client may be the original sender, though that need not always be the case.

This is an excerpt from Manning's book Functional Programming in Scala.
To implement map2, we’ll use a non-blocking concurrency primitive called actors. An Actor is essentially a concurrent process that doesn’t constantly occupy a thread. Instead, it only occupies a thread when it receives a message. Importantly, although multiple threads may be concurrently sending messages to an actor, the actor processes only one message at a time, queueing other messages for subsequent processing. This makes them useful as a concurrency primitive when writing tricky code that must be accessed by multiple threads, and which would otherwise be prone to race conditions or deadlocks.