Misty Programming Language:

Actors

Misty has direct support for actors. Actors run independently and concurrently. Actors communicate by sending messages. Every actor has its own memory space. Actors do not share memory. A program is generally a lead actor that may be supported by a team of supporting actors running in the same machine or in different machines. An actor may make use of modules.

misty "misty" space misty_type space name '{' indent use statements outdent '}'

misty_type "actor" "module"

Every actor has an actor object called @at sign that contains a reference to the actor itself and other powerful capabilities. An actor can pass actor objects (including an attenuated version of @) as parameters to functions or in messages to other actors. If an actor can acquire the actor object of another actor, then it can send messages to it. Messages may contain numbers, texts, records, arrays, logicals, null, blobs, and actor objects.

An attenutated @ object is produced when @ is on the right side of a set statement, or when @ is passed an argument to a function, or wehn @ is included in an array literal or record literal..

Misty programs are organized into source files. There are two types of Misty source files:

A module is a chunk of independent program. These can be used to build reusable libraries. The last statement in a module is a return statement, which usually returns a function or a record containing functions. That return value is bound to the name in a use statement.

An actor file includes the word actor before the name.

In this example, the example actor imports the app_master_2000 module, and designates its handler function as the receiver of messages for the actor.

misty actor example {
    use app: "app_master_2000"
    call @.receiver(app.handler)
}

Actors are started with the @.new method. An actor that starts another actor is call a master. An actor started by a master is called a padawan. An actor can be a padawan to one actor and a master to many others.

Communication between actors happens exclusively with messages. Messages are one way with eventual consequences.

Messages are usually transmitted over some sort of connection.

use statement

use "" "use" space name locator linebreak use

locator "" ": " text

The use statement makes a module available to an actor or other module. The return value of the module is bound to the name. An optional locator can be provided for finding the module file. Standard modules do not require a locator.

Actor object

An actor object contains the information needed to communicate with an actor. An actor object can be transmitted to other actors, even on other machines.

An actor object is an immutable black box. It can be used in a send statement to send a message to the actor associated with the actor object. Actor objects can be sent to other actors, giving them the capability to also send messages to the actor associated with the actor object.

None of the contents of the actor object are visible or accessible.

Example:

actor?(@)                     # true
actor?(my_actor)              # true
record?(my_actor)             # false
stone?(my_actor)              # true
my_actor = my_actor           # true
my_actor = your_actor         # false (probably)

The actor? function

actor?(value)

The actor? function gives true if the value is an actor object.

Messages

Actors communicate using messages. Actors do not share variables or functions.

Incoming messages are queued by the Misty system and delivered in arrival order. The exceptions are system level messages like the die message, which, if valid, will cause an actor to immediately fail, even if there are undelivered messages waiting for it in the queue.

Some messages can be used to reply to the original sender of the message.

receiver function

The receiver method is given a callback function that will receive the actor's messages. The callback function will receive a single argument, the message object.

System Messages

The Misty System uses its own messaging system to transmit system messages. A system message type has as its first character. Reserved messages can not be sent by the send statement.

℠begin

The begin message is the first message sent to an actor when it is created. It will contain the actor object of the master.

℠end

The end message is sent when an actor is no longer needed. The actor receiving this message should finish its work and die.

℠die

The die message is not queued or delivered to the actor. Instead, the actor is immediately terminated. It will also terminate the novices and pact actors. The die message can only be sent by the die method or as a consequence of a pact.

℠done

The done message is sent to the master of an actor if an actor stops for any reason.

℠hello

The hello message is sent as a response to the contact method. It will include the actor object of the remote actor.

℠pact

The pact message is a request to be sent a die message when the receiver dies.

@ Methods

The @ object is only available in the misty actor files. The @ object is not available in misty module files, although the attenuated actor object and some of the @ methods can be passed in. The @ object may contain these methods: new, connection, contact, receiver, portal, kill, pact, delay, clock, random.

new method

@.new(callback, text, configuration)

The new function creates a new actor. It takes a text that identifies the actor program file that the new actor runs. It sends the ℠begin message to the new actor.

The configuration record contains fields having the names of the @ methods. If the field's value is true, then the new actor will have that method in its own @ object. So, if the configuration contains a contact field that is true, then the new actor is allowed to contact portals to obtain actor objects.

The callback is passed the new actor object.

Example:

call @.actor.new(
    callback,
    "example.mst",
    {
        contact: true,
        new: true,
        pact: true,
        receiver: true
    }
)

connection method

@.connection(callback, actor, configuration)

The connection method takes a callback function, an actor object, and a configuration record for getting information about the status of a connection to an actor. The configuration record is used to request the sort of information that needs to be communicated. This can include partitions, speed, congestion, cost, activity. The callback will be given a record containing the requested information.

contact method

@.contact(callback, record)

The contact method sends a message to a portal on another machine to obtain an actor object.

The record can contain:

The current actor is the parent of the new actor, and it will be notified when the new actor terminates.

The callback function will be passed the padawan actor object.

receiver method

@.receiver(function)

This method registers a function that will receive all messages sent to the actor except for portal contact messages, and replies.

portal method

@.portal(function, port)

A portal is a special actor that that performs introduction services. It listens on a specified port for contacts by external actors that need to acquire an actor object. The function will receive the record containing the request. The record can have a reply sent through it. A portal can respond by beginning a new actor, or finding an existing actor, or by forwarding the contact message to another actor. This is how distributed Misty networks are bootstrapped.

kill method

@.kill(actor)

This method sends the die message. The actor object must be one of your own novices or @. An actor may kill itself.

pact method

@.pact(actor object, another actor object)

The pact function links two actors together in a suicide pact. If the other actor object fails, then actor object will fail. The actor object must be either @ or one of its padawans.

If a master fails, then all of its padawans fail automatically.

delay method

@.delay(function, seconds)

The delay function is used to schedule the invocation of a function at a later time. Any value returned from the delayed invocation will be ignored. There is no guarentee that the function will ever be invoked. The delayed invocation will not interrupt normal processing. The invocation will be delayed until the system is quiescent.

The delay function immediately returns a cancel function. Calling the cancel function will cancel the delayed execution of the function, if it is not too late..

The seconds parameter determines when the invocation will occur, no sooner than seconds seconds after now. The seconds parameter must be a non-negative number or null which behaves as 0.

clock method

@.clock(function)

The clock method takes a function argument that will eventually be called with the current time in number form. See time.

random function

@.random()

The random function returns a number between 0 and 1.

Worker Data Structures

Worker Object

An actor object is used with the send statement. It contains the address of an actor. A message may contain actor objects, which will give the recipient actor the capability to send to those actors.

There are three ways that an actor can obtain an actor object of another actor:

Message object

A message object is obtained from the callback function that is registered with @.receiver. It acts like an ordinary record.

When a message is sent using the callback form, the message may be used as an actor object for transmitting the reply.

Turns

Computation takes place in an actor in a fragment of time called a turn. A turn starts with the delivery of a message or delay. A function (such as the function registered with @.receive, @.portal, @.clock, or a @.delay callback function) will run to completion or failure. Any outgoing messages will be held until the turn completes successfully, at which time they go into the outgoing queue and are sent.

An actor will not receive another message until the turn ends. Each turn will process exactly one message.

If a machine has multiple computation units, then it is possible for multiple turns of multiple actors to be going on simultaneously. Turns can be timesliced. There are no concurrency issues because actors do not share memory. They communicate with other actors and the world only by message passing.