Concurrentlua-Concurrent-oriented Lua Programming

Source: Internet
Author: User
Concurrentlua -- Concurrent-oriented Lua Programming

Original article address
Linker translates this article only to provide more information.


Introduction

Concurrentlua is an implementation of a non-shared asynchronous message passing model. This model comes from the Erlang language.
She adapted the concurrency elements of Erlang and integrated them into Lua.

A core element of concurrentlua is process. A process is a lightweight virtual machine.
Thread, playing the same role as the operating system process; they do not share the memory, but use the communication between a specific process.
Mechanism. These processes can be created and destroyed as needed, and are implemented through a simple round robin (rotation training) algorithm.
Schedule them.

Each process is associated with a mailbox (a queue for storing messages temporarily) and sent by other processes through the mailbox.
The process can check whether any new message arrives in its mailbox at any time. If yes, the process can
Read data in order of arrival.

Each process has a unique number as the process identifier, called process identifier.
Give the process a name and use the name to indicate the process. The process name and process correspondence are saved to
Central Storage room -- Registry (Registry). The process can edit the registry and add or delete table items.

The error capture mechanism is also implemented as monitors and links. The monitors process can monitor other
Process, and get a notification when the monitored process ends abnormally. Bind the process together through the linker process,
When a process terminates abnormally, other processes are also notified and terminated.

The system also supports distributed programming and all related components.
Communication.

Distribution is based on node components. A node represents a runtime environment that runs many processes.
Nodes can connect and communicate with each other, so a virtual network is established. Distributed processes use this network.
Ordered information exchange.

Each node has a name. Other nodes can use this name to connect to the. One port er wizard process.
A service process, similar to the name service provided by Erlang, provides the name resolution service. Port er.
Know the information of all nodes in the virtual network.

Just as a process can be created locally, a process can already be created on a remote node. A remote process can be viewed
For a local process.

If the nodes in the virtual network are fully interconnected (each node connects to other nodes in two directions), you can use
Global process name. nodes communicate with each other and maintain the Virtual Global Registry and keep their local registry always
Update.

Monitors and links support distributed processes and local processes in the same semantics. nodes can be transparently processed.
Distribution process error. In addition, the process can be like monitoring the entire node.

Nodes can be authenticated before communication. Only Authenticated nodes can be part of the virtual network.
The policy is guaranteed by a simple security mechanism.


Implementation

Concurrentlua is implemented based on the Lua component system, which organizes and manages Lua
The main module provides the concurrency function and the distributed programming function.
It can be loaded separately, and each module can selectively load the sub-module to be used. The Independent Port er
The genie process is also part of the implementation.

The process in the system is implemented through the Lua coroutine mechanism. A process is actually a Lua coroutine,
Use yield to suspend a process and use resume to continue executing a process.

The scheduling mechanism of the process is still based on the collaborative multi-threaded model used by Lua. The process voluntarily suspends itself,
This allows other processes to run. However, pending and resuming processes are partially hidden in the high-level mechanism.
When a process waits for the message to arrive, it is suspended and ready to be restored after the message arrives in the process mailbox.
A simple round robin scheduler is used to restore process execution.

All types of Lua data, except memory reference, can be sent through messages. messages can be boolean values,
Numbers, strings, tables, or functions, or their mixture. The data is automatically serialized upon sending and accepted
Time deserialization, so data is passed by value.

The Distributed inter-process communication mechanism between nodes is based on asynchronous socket. ing to the network layer is non-blocking.
Socket and scheduled training. This is the method used by most Lua modules today. Non-blocking semantics should also be used.
For example, file and pipeline I/O operations.



Usage

Some examples provide usage of components not required by the system, such as creating a process, passing messages to distributed processes, and capturing errors.


Create Process

The spawn () function can create a process. The spawn () function accepts at least one parameter, which indicates the entry function of the process.
Other additional parameters are directly transferred to the entry function.

The following example shows how to create a process. The process outputs messages of a specified number of times:

Require 'concurrent'

Function hello_world (times)
For I = 1, times do print ('Hello World') End
Print ('done ')
End

Concurrent. spawn (hello_world, 3)

Concurrent. Loop ()


The output should be:

Hello World
Hello World
Hello World
Done


First load the system:
Require 'concurrent'
Process entry function:
Function hello_world (times)
For I = 1, times do print ('Hello World') End
Print ('done ')
End
Create a new process:
Concurrent. spawn (hello_world, 3)
Finally, the call system has an infinite loop:
Concurrent. Loop ()


Message Interaction

The process exchanges messages through the send () and receive () functions. Similarly, the self () function is also used to obtain the process ID.
The following program implements two processes to exchange messages and then terminate:

Require 'concurrent'

Function Pong ()
While true do
Local MSG = concurrent. Receive ()
If msg. Body = 'finished' then
Break
Elseif msg. Body = 'ping' then
Print ('pong encrypted ed ping ')
Concurrent. Send (msg. From, {body = 'pong '})
End
End
Print ('pong finished ')
End

Function Ping (n, pid)
For I = 1, n do
Concurrent. Send (PID ,{
From = concurrent. Self (),
Body = 'ping'
})
Local MSG = concurrent. Receive ()
If msg. Body = 'pong' then
Print ('Ping your Ed Pong ')
End
End
Concurrent. Send (PID ,{
From = concurrent. Self (),
Body = 'finished'
})
Print ('Ping finished ')
End

PID = concurrent. spawn (PONG)
Concurrent. spawn (Ping, 3, pid)

Concurrent. Loop ()


The output should be:

Pong encrypted ed Ping
Ping your Ed Pong
Pong encrypted ed Ping
Ping your Ed Pong
Pong encrypted ed Ping
Ping your Ed Pong
Pong finished
Ping finished


After the pong process is created, the ping process obtains the PID of the pong process:
PID = concurrent. spawn (PONG)
Concurrent. spawn (Ping, 3, pid)

The Ping process sends a message:
Concurrent. Send (PID ,{
From = concurrent. Self (),
Body = 'ping'
})

The Pong process waits for the message to arrive, and then saves the received message to a variable:
Local MSG = concurrent. Receive ()

Pong process reply:
Concurrent. Send (msg. From, {body = 'pong '})

The Pong process ends after receiving a prompt from the ping process.


Register process name

You can replace the PID with the process name to specify the message receiver. Register () function can be used in the Registry
The table corresponding to the system name, rather than the Windows registry .)
Create a process name:

Require 'concurrent'

Function Pong ()
While true do
Local MSG = concurrent. Receive ()
If msg. Body = 'finished' then
Break
Elseif msg. Body = 'ping' then
Print ('pong encrypted ed ping ')
Concurrent. Send (msg. From, {body = 'pong '})
End
End
Print ('pong finished ')
End

Function Ping (N)
For I = 1, n do
Concurrent. Send ('pong ',{
From = concurrent. Self (),
Body = 'ping'
})
Local MSG = concurrent. Receive ()
If msg. Body = 'pong' then
Print ('Ping your Ed Pong ')
End
End
Concurrent. Send ('pong ',{
From = concurrent. Self (),
Body = 'finished'
})
Print ('Ping finished ')
End

PID = concurrent. spawn (PONG)
Concurrent. Register ('pong ', pid)
Concurrent. spawn (Ping, 3)

Concurrent. Loop ()


The change from the previous version is where the ping process sends messages:
Concurrent. Send ('pong ',{
From = concurrent. Self (),
Body = 'ping'
})
And:
Concurrent. Send ('pong ',{
From = concurrent. Self (),
Body = 'finished'
})

And now the pong process has registered its name:
Concurrent. Register ('pong ', pid)

Therefore, the ping process does not need to know the PID of the pong process.


Distributed message transmission

Processes on different nodes can still use the same message transmission mechanism.
The node name can be specified. The previous example can be transformed into two programs, one independent process.

The Pong Process Code is as follows:

Require 'concurrent'

Function Pong ()
While true do
Local MSG = concurrent. Receive ()
If msg. Body = 'finished' then
Break
Elseif msg. Body = 'ping' then
Print ('pong encrypted ed ping ')
Concurrent. Send (msg. From, {body = 'pong '})
End
End
Print ('pong finished ')
End

Concurrent. INIT ('pong @ gaa ')

PID = concurrent. spawn (PONG)

Concurrent. Register ('pong ', pid)
Concurrent. Loop ()
Concurrent. Shutdown ()


The Ping Process Code is as follows:

Require 'concurrent'

Function Ping (N)
For I = 1, n do
Concurrent. Send ({'pong ', 'pong @ Gaia '},{
From = {concurrent. Self (), concurrent. node ()},
Body = 'ping'
})
Local MSG = concurrent. Receive ()
If msg. Body = 'pong' then
Print ('Ping your Ed Pong ')
End
End
Concurrent. Send ({'pong ', 'pong @ Gaia '},{
From = {concurrent. Self (), concurrent. node ()},
Body = 'finished'
})
Print ('Ping finished ')
End

Concurrent. spawn (Ping, 3)

Concurrent. INIT ('Ping @ Selene ')
Concurrent. Loop ()
Concurrent. Shutdown ()


If you want to run this example by yourself, you need to modify the machine name in the second half of the node name to match your network environment .)

Pong process output should be:
Pong encrypted ed Ping
Pong encrypted ed Ping
Pong encrypted ed Ping
Pong finished

The Ping process output should be:
Ping your Ed Pong
Ping your Ed Pong
Ping your Ed Pong
Ping finished

In this example, the runtime system runs in distributed mode. To see the result, the port er must first run:
$ Clpmd
Code for initializing the node where the pong process is located:
Concurrent. INIT ('pong @ gaa ')
Code for initializing the node where the ping process is located:
Concurrent. INIT ('Ping @ Selene ')

The above two codes are used to register the node to the port er:
Concurrent. Shutdown ()

The only change in this example is that the message sending destination. node () function will return the name of the called process sitting on the node:
Concurrent. Send ({'pong ', 'pong @ Gaia '},{
From = {concurrent. Self (), concurrent. node ()},
Body = 'ping'
})

Next:
Concurrent. Send ({'pong ', 'pong @ Gaia '},{
From = {concurrent. Self (), concurrent. node ()},
Body = 'finished'
})


Error Handling

One way to capture errors between processes is to connect to the process. The two processes are bound together, after an exception is terminated
The other will terminate the. Link () function to bind the process:

Require 'concurrent'

Function Ping (n, pid)
Concurrent. Link (PID)
For I = 1, n do
Concurrent. Send (PID ,{
From = concurrent. Self (),
Body = 'ping'
})
Local MSG = concurrent. Receive ()
If msg. Body = 'pong' then
Print ('Ping your Ed Pong ')
End
End
Print ('Ping finished ')
Concurrent. Exit ('finished ')
End

Function Pong ()
While true do
Local MSG = concurrent. Receive ()
If msg. Body = 'ping' then
Print ('pong encrypted ed ping ')
Concurrent. Send (msg. From, {body = 'pong '})
End
End
Print ('pong finished ')
End

PID = concurrent. spawn (PONG)
Concurrent. spawn (Ping, 3, pid)

Concurrent. Loop ()


The output should be:
Pong encrypted ed Ping
Ping your Ed Pong
Pong encrypted ed Ping
Ping your Ed Pong
Pong encrypted ed Ping
Ping your Ed Pong
Pong finished -- Note: here should be: Ping fininshed

The Pong process will never run to the last line, because it will terminate when receiving the ping process exit signal.

The connection process code is as follows:
Concurrent. Link (PID)

You can also capture the exit signal caused by Process Termination. The captured exit signal is converted into a special message:

Require 'concurrent'

Concurrent. setoption ('trapeg', true)

Function Pong ()
While true do
Local MSG = concurrent. Receive ()
If MSG. Signal = 'Port' then
Break
Elseif msg. Body = 'ping' then
Print ('pong encrypted ed ping ')
Concurrent. Send (msg. From, {body = 'pong '})
End
End
Print ('pong finished ')
End

Function Ping (n, pid)
Concurrent. Link (PID)
For I = 1, n do
Concurrent. Send (PID ,{
From = concurrent. Self (),
Body = 'ping'
})
Local MSG = concurrent. Receive ()
If msg. Body = 'pong' then
Print ('Ping your Ed Pong ')
End
End
Print ('Ping finished ')
Concurrent. Exit ('finished ')
End

PID = concurrent. spawn (PONG)
Concurrent. spawn (Ping, 3, pid)

Concurrent. Loop ()


The output should be:
Pong encrypted ed Ping
Ping your Ed Pong
Pong encrypted ed Ping
Ping your Ed Pong
Pong encrypted ed Ping
Ping your Ed Pong
Pong finished
Ping finished

You can use the setoption () function to set the process link options. Here is the trapexit option:
Concurrent. setoption ('trapeg', true)

The Pong process receives an Exit message:
If MSG. Signal = 'Port' then
Break

The Monitor Based on the prompt message can also be used to handle errors.
































































Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.