A script language of time-sharing scheduling coroutine in single thread
Coroutine in Melang is time-sharing scheduled in a single thread.
If you use the execution file which is generated by the repository on Github, script files in a same melang command will be executed in one process or even one thread.
e.g.
/*the tasks those behind command name are running in a same thread.*/
$ ./melang a.mln b.mln ...
Besides this way, there is a function named Eval
to start a new script task in the current thread to execute a piece of code.
Eval(val, data, in_string, alias);
If in_string
is true, val
will be the script code, otherwise val
is the script file path.
data
will be passed to the new script task. If we want to use data
in new task, we can use the variable named EVAL_DATA
which is a built-in variable added by Eval
.
data
not support all data types, it just supports:
alias
is the name to be indicated to the new coroutine task, and it can be omitted if it doesn’t need a name.
If val
is nil
, function will return an array of names of all named coroutines.
e.g.
sys = Import('sys');
Eval('sys = Import('sys'); while (1) {sys.print(EVAL_DATA);}', 'bbb', true);
while (1) {
sys.print('aaa');
}
The output would be like:
...
aaa
aaa
bbb
bbb
bbb
bbb
bbb
bbb
aaa
...
There is the same problem as shown in preprocess. If val
is a file path, it will follow the same rules as include
’s.
Melang also provide a function to kill running coroutine task.
Kill(alias);
alias
is the name that given by function Eval
.
This function always return nil
.
Here are two comprehensive examples of HTTP server. There are some functions which will be introduced in library used in these two examples.
There are two files: server.mln
and worker.mln
.
Example 1.
Each TCP connection will be handled in an individual coroutine.
/* filename: server.mln */
net = Import('net');
sys = Import('sys');
listenfd = net.tcp_listen('127.0.0.1', '80');
while (1) {
fd = net.tcp_accept(listenfd);
sys.print(fd);
Eval('worker.mln', fd);
}
/* filename: worker.mln */
net = Import('net');
sys = Import('sys');
fd = EVAL_DATA;
ret = net.tcp_recv(fd);
if (ret) {
net.tcp_send(fd, "HTTP/1.1 200 OK\r\nContent-Length: 1\r\n\r\na\r\n\r\n");
}fi
net.tcp_close(fd);
sys.print('quit');
Now, you can use ab (apache bench)
to test.
Example 2.
Create a coroutine pool which has 100 coroutines.
Each TCP will be delivered to a coroutine which is in coroutine pool to be handled.
/* filename: server.mln */
net = Import('net');
mq = Import('mq');
listenfd = net.tcp_listen('127.0.0.1', '80');
for (i = 0; i < 4; ++i) {
Eval('worker.mln', i);
}
while (1) {
fd = net.tcp_accept(listenfd);
mq.send('test', fd);
}
/* filename: worker.mln */
sys = Import('sys');
net = Import('net');
mq = Import('mq');
sys.print(EVAL_DATA);
while (1) {
fd = mq.recv('test');
ret = net.tcp_recv(fd);
if (ret) {
net.tcp_send(fd, "HTTP/1.1 200 OK\r\nContent-Length: 1\r\n\r\na\r\n\r\n");
}fi
net.tcp_close(fd);
}