Melang

Logo

A script language of preemptive scheduling coroutine in single thread

View the Project on GitHub Water-Melon/Melang

Coroutine

Coroutine in Melang is preemptive 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 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 mln_eval to start a new script task in the current thread to execute a piece of code.

@mln_eval(val, data, in_string);

If in_string is true, val is 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 an internal variable added by mln_eval.

data not support all data types, it just supports:

e.g.

@mln_eval('while (1) {@mln_print(EVAL_DATA);}', 'bbb', true);
while (1) {
  @mln_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.

Examples

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 processor.mln.

Example 1.

Each TCP connection will be handled in an individual coroutine.

/* filename: server.mln */
listenfd = @mln_tcp_listen('127.0.0.1', '80');
while (1) {
    fd = @mln_tcp_accept(listenfd);
    @mln_print(fd);
    @mln_eval('processor.mln', fd);
}
/* filename: processor.mln */
fd = EVAL_DATA;
ret = @mln_tcp_recv(fd);
if (ret) {
    @mln_tcp_send(fd, "HTTP/1.1 200 OK\r\nContent-Length: 1\r\n\r\na\r\n\r\n");
}fi
@mln_tcp_close(fd);
@mln_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 */
listenfd = @mln_tcp_listen('127.0.0.1', '80');
for (i = 0; i < 100; ++i) {
    @mln_eval('processor.mln', i);
}
while (1) {
    fd = @mln_tcp_accept(listenfd);
    @mln_msg_queue_send('test', fd);
}
/* filename: processor.mln */
@mln_print(EVAL_DATA);
while (1) {
    fd = @mln_msg_queue_recv('test');
    ret = @mln_tcp_recv(fd);
    if (ret) {
        @mln_tcp_send(fd, "HTTP/1.1 200 OK\r\nContent-Length: 1\r\n\r\na\r\n\r\n");
    }fi
    @mln_tcp_close(fd);
}