Abstraction of the actors concepts

Introduced classes

abstract class Actor

actors :: Actor

Abstraction of an actor
class Future[E: nullable Object]

actors :: Future

The promise of a value which will be set asynchronously
class Mailbox[E: nullable Object]

actors :: Mailbox

A Blocking queue implemented from a ConcurrentList
abstract class Message

actors :: Message

A Message received by a Mailbox
class Proxy

actors :: Proxy

Abstraction of proxies for threaded actors
class ShutDownMessage

actors :: ShutDownMessage

A Message to Rule them all... properly shutdown an Actor
class SynchronizedCounter

actors :: SynchronizedCounter

A counter on which threads can wait until its value is 0

Redefined classes

redef class Sys

actors :: actors $ Sys

The main class of the program.

All class definitions

abstract class Actor

actors $ Actor

Abstraction of an actor
class Future[E: nullable Object]

actors $ Future

The promise of a value which will be set asynchronously
class Mailbox[E: nullable Object]

actors $ Mailbox

A Blocking queue implemented from a ConcurrentList
abstract class Message

actors $ Message

A Message received by a Mailbox
class Proxy

actors $ Proxy

Abstraction of proxies for threaded actors
class ShutDownMessage

actors $ ShutDownMessage

A Message to Rule them all... properly shutdown an Actor
class SynchronizedCounter

actors $ SynchronizedCounter

A counter on which threads can wait until its value is 0
redef class Sys

actors :: actors $ Sys

The main class of the program.
package_diagram actors::actors actors pthreads::concurrent_collections concurrent_collections actors::actors->pthreads::concurrent_collections pthreads::extra extra actors::actors->pthreads::extra pthreads pthreads pthreads::concurrent_collections->pthreads pthreads::extra->pthreads ...pthreads ... ...pthreads->pthreads actors::agent_simulation agent_simulation actors::agent_simulation->actors::actors actors::chameneosredux chameneosredux actors::chameneosredux->actors::actors actors::fannkuchredux fannkuchredux actors::fannkuchredux->actors::actors actors::mandelbrot mandelbrot actors::mandelbrot->actors::actors actors::simple simple actors::simple->actors::actors actors::thread_ring thread_ring actors::thread_ring->actors::actors actors::simple_simulation simple_simulation actors::simple_simulation->actors::agent_simulation actors::simple_simulation... ... actors::simple_simulation...->actors::simple_simulation a_star-m a_star-m a_star-m->actors::chameneosredux a_star-m->actors::fannkuchredux a_star-m->actors::mandelbrot a_star-m->actors::simple a_star-m->actors::thread_ring a_star-m... ... a_star-m...->a_star-m

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module array

core :: array

This module introduces the standard array structure.
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.
module environ

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module exec

core :: exec

Invocation and management of operating system sub-processes.
module file

core :: file

File manipulations (create, read, write, etc.)
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module kernel

core :: kernel

Most basic classes and methods.
module list

core :: list

This module handle double linked lists
module math

core :: math

Mathematical operations
module native

core :: native

Native structures for text and bytes
module numeric

core :: numeric

Advanced services for Numeric types
module protocol

core :: protocol

module pthreads

pthreads :: pthreads

Main POSIX threads support and intro the classes Thread, Mutex and Barrier
module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module re

core :: re

Regular expression support for all services based on Pattern
module ropes

core :: ropes

Tree-based representation of a String.
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module stream

core :: stream

Input and output streams of characters
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O

Parents

module concurrent_collections

pthreads :: concurrent_collections

Introduces thread-safe concurrent collections
module extra

pthreads :: extra

Offers some POSIX threads services that are not available on all platforms

Children

module agent_simulation

actors :: agent_simulation

a "Framework" to make Multi-Agent Simulations in Nit
module chameneosredux

actors :: chameneosredux

Example implemented from "The computer Language Benchmarks Game" - Chameneos-Redux
module fannkuchredux

actors :: fannkuchredux

Example implemented from "The computer Language Benchmarks Game" - Fannkuch-Redux
module mandelbrot

actors :: mandelbrot

Example implemented from "The computer Language Benchmarks Game" - Mandelbrot
module simple

actors :: simple

A very simple example of the actor model
module thread_ring

actors :: thread_ring

Example implemented from "The computer Language Benchmarks Game" - Thread-Ring

Descendants

module a_star-m

a_star-m

module simple_simulation

actors :: simple_simulation

Using agent_simulation by refining the Agent class to make
# Abstraction of the actors concepts
module actors is
	new_annotation actor
end

intrude import pthreads::concurrent_collections
intrude import pthreads
intrude import pthreads::extra

# Abstraction of an actor
# It has a mailbox, can receive and process messages asynchronously
abstract class Actor
	super Thread

	# Type of the proxied class (or working class)
	type V: Object

	# The instance used to do the real work
	# i.e. the real working object
	var instance: V

	# Mailbox used to receive and process messages
	var mailbox = new Mailbox[Message].with_actor(self)

	# Is `self` working ?
	# i.e. does it have messages to process or is it processing one now ?
	var working = true

	redef fun main do
		loop
			var m = mailbox.shift
			if m isa ShutDownMessage then
				sys.active_actors.decrement
				return null
			end
			m.invoke(instance)
		end
	end

	# Ends `self`, cancel ongoing work abrutly
	# Pretty dangerous to use
	fun kill do
		var n = self.native
		if n != null then n.cancel
	end
end

# A Blocking queue implemented from a `ConcurrentList`
# `shift` is blocking if there isn't any element in `self`
# `push` or `unshift` releases every blocking threads
# Corresponds to the mailbox of an actor
class Mailbox[E]
	super BlockingQueue[E]

	# The associated actor
	var actor: Actor is noautoinit

	# init self with an associated actor
	init with_actor(actor: Actor) do
		self.actor = actor
		sys.active_actors.increment
	end

	# Adding the signal to release eventual waiting thread(s)
	redef fun push(e) do
		mutex.lock
		if real_collection.is_empty and not actor.working then
			actor.working = true
			sys.active_actors.increment
			real_collection.push(e)
			self.cond.signal
		else
			real_collection.push(e)
		end
		mutex.unlock
	end

	redef fun unshift(e) do
		mutex.lock
		real_collection.unshift(e)
		self.cond.signal
		mutex.unlock
	end

	# If empty, blocks until an item is inserted with `push` or `unshift`
	redef fun shift do
		mutex.lock
		if real_collection.is_empty then
			actor.working = false
			sys.active_actors.decrement
			while real_collection.is_empty do self.cond.wait(mutex)
		end
		var r = real_collection.shift
		mutex.unlock
		return r
	end

	redef fun is_empty do
		mutex.lock
		var r = real_collection.is_empty
		mutex.unlock
		return r
	end
end

# A Message received by a Mailbox
# In fact, this is the reification of a call
# Each Message class represent a call to make on `instance` via `invoke`
abstract class Message

	# Type of the class on which `self` make the call
	type E: Object

	# Redef this method so it calls the right one on `instance` (double dispatch)
	fun invoke(instance: E) is abstract
end

# Abstraction of proxies for threaded actors
class Proxy

	# Type of the actor `self` is proxiing
	type E: Actor

	# The proxied actor
	var actor: E is noinit

	# Kill `actor` without mercy
	fun kill do actor.kill

	# Tell `actor` to terminate properly
	# Queueing a ShutDownMessage to the end of its mailbox
	fun terminate do
		var msg = new ShutDownMessage
		actor.mailbox.push(msg)
	end

	# Tell `actor` to terminate now
	# Queueing a ShutDownMessage before every other ones
	fun terminate_now do
		var msg = new ShutDownMessage
		actor.mailbox.unshift(msg)
	end

	# Wait for `actor` to terminate
	fun wait_termination do actor.join
end

# A Message to Rule them all... properly shutdown an Actor
# It's behaviour is implemented in the actor itself
class ShutDownMessage
	super Message
end

# The promise of a value which will be set asynchronously
class Future[E]
	# Value promised by `self`
	var value: nullable E = null

	# Mutex for synchronisation
	protected var mutex = new Mutex

	# Condition variable for synchronisation
	protected var cond: nullable PthreadCond = null

	# Can be used to check if the value is available without waiting
	protected var is_done = false

	# Set the value and signal so that, someone waiting for `value` can retrieve it
	fun set_value(value: E) do
		mutex.lock
		is_done = true
		self.value = value
		var cond = self.cond
		if cond != null then cond.signal
		mutex.unlock
	end

	# Return immediatly if `value` is set, or block waiting for `value` to be set
	fun join: E do
		mutex.lock
		if not is_done then
			var cond = self.cond
			if cond == null then
				cond = new PthreadCond
				self.cond = cond
			end
			cond.wait(mutex)
		end
		mutex.unlock
		return value
	end
end

# A counter on which threads can wait until its value is 0
class SynchronizedCounter

	# The starting value, always starts with 0
	private var c = 0

	private var cond = new PthreadCond
	private var mutex = new Mutex

	# Increment the counter atomically
	fun increment do
		mutex.lock
		c += 1
		mutex.unlock
	end

	# Decrement the counter atomically,
	# signals to waiting thread(s) if `c == 0`
	fun decrement do
		mutex.lock
		c -= 1
		if c == 0 then
			cond.signal
		end
		mutex.unlock
	end

	# Block until `c == 0`
	fun wait do
		mutex.lock
		while c != 0 do cond.wait(mutex)
		mutex.unlock
	end
end

redef class Sys

	# Number of active actors
	var active_actors = new SynchronizedCounter

	redef fun run do
		super
		# The program won't end until every actor is done
		active_actors.wait
	end
end
lib/actors/actors.nit:15,1--253,3