DEV Community

Cover image for Preemptive scheduling coroutine programming language
Megabit
Megabit

Posted on

Preemptive scheduling coroutine programming language

The concept of coroutine must be familiar to everyone now. After all, not only LUA, Go or Kotlin but also C++, they are all support coroutines.
But different languages have different implementations. Such as LUA, coroutines will be scheduled when someone called yield() or resume().
A new language introduced to you today is a scripting language of coroutine preemptive scheduling based on time slices. That is, each coroutine does not need to explicitly call certain functions to give up control, but according to the weight of execution time to control whether to be suspended or run.

Its name is Melang

We will discuss the following:

  • features
  • usage scenarios

Features

For a language, it must have flow control, array, dict, structure or class, etc. These in Melang are no different from other languages. So we will focus on the following:

Coroutine preemptive scheduling

In Melang, each script task is an independent coroutine, and coroutines' execution environments are isolated. But they can communicate with each other by the message queue functions.
Let's look at two examples:

  • running multi-tasks by melang execution file

There are two script files:

 //a.mln
 while (true) {
   @mln_print('a');
 }
Enter fullscreen mode Exit fullscreen mode
 //b.mln
 while (true) {
   @mln_print('b');
 }
Enter fullscreen mode Exit fullscreen mode

Then I execute the following command:

 $ melang a.mln b.mln
Enter fullscreen mode Exit fullscreen mode

After execution, you will see the screen print a and b alternately, as follows:

 ...
 b
 b
 b
 a
 a
 a
 a
 a
 ...
Enter fullscreen mode Exit fullscreen mode

And using top command will find out that only one process (and also only one thread) is performing these two tasks.
Melang scheduling does not occur in the function mln_print, but will try to switch during the processing of each statement.

  • start up multi-tasks in a Melang task
 //launcher.mln
 @mln_eval('a.mln');
 @mln_eval('b.mln');
Enter fullscreen mode Exit fullscreen mode

We create a new script file named launcher.mln to start up a.mln and b.mln by calling function mln_eval. And then execute:

 $ melang launcher.mln
Enter fullscreen mode Exit fullscreen mode

The output is the same as previous example.

Reflection

Reflection means that the class to be operated is known at runtime, and the complete structure of the class can be obtained at runtime and the corresponding method can be called. -- quoted from a netizen

In Melang, the concept of class is called Set, but it is more similar to the structure in C, but also supports function definitions.
Let's look at a simple example:

Human {
  name;
  age;
  @init (name, age) {
    this.name = name;
    this.age = age;
  }
}
Enter fullscreen mode Exit fullscreen mode

Here we define a Set named Human, which has two member variables: name and age, and a method init.
The general instantiation code is as follows:

me = $Human;
Enter fullscreen mode Exit fullscreen mode

This instantiates a Human object named me.
However, we can also instantiate it like this:

str = 'Human';
me = $str;
Enter fullscreen mode Exit fullscreen mode

The result is the same.

Then we can call the method of the object:

me.init('Tom', 18);
Enter fullscreen mode Exit fullscreen mode

In Melang, not only Set can be obtained by a string, but also functions and object methods can be used in this way.

Examples for function:

@foo ()
{
  @mln_print('foo');
}
a = 'foo';
a();
Enter fullscreen mode Exit fullscreen mode

Here we define a function, and we call it indirectly by a string variable.

Example for object method:

Human {
  name;
  age;
  action;
  @init (name, age) {
    this.name = name;
    this.age = age;
  }
}

me = $Human;
me.action = 'init';
me.action('Tom', 18);
@mln_print(me.name);
Enter fullscreen mode Exit fullscreen mode

As you can see in this example, we call the method of an object by a string member variable.

Injection

For an instantiated object, we can still add (or inject) some members and methods to it, for example:

Human {
}

someone = $Human;
someone.age = 20;
@mln_print(someone.age);
Enter fullscreen mode Exit fullscreen mode

The output is 20. The member variable age was successfully added to the object someone.

Note: The injection is defined for the object, not Set. Therefore, if you instantiate Human again, there is still no age.

The above example is the simplest injection. Melang also provides function set and get similar to other scripts.

Let's look at an example of method injection:

Human {
  age;
}

@printAge()
{
  @mln_print(this.age);
}

someone = $Human;
someone.age = 20;
someone.print = printAge;
someone.print();
Enter fullscreen mode Exit fullscreen mode

This example will still output 20, but this time it is output by mln_print called in the injected method printAge.

Reactive programming

As we can see in web front-end programming, a variable will be monitored by a set of functions. When the value changes, the callback function will be called. (Note that, in Melang, even if the new value is the same as the old one, it also will be called)

Example:

@eventHandler(newdata, userData)
{
  @mln_print(newdata);
  @mln_print(userData);
}
n = 0;
@mln_watch(n, eventHandler, 'this is an useData');
for (; n < 5; ++n)
  ;
Enter fullscreen mode Exit fullscreen mode

Here, variable n will be tracked by calling the function mln_watch. When the value of n changed, the eventHandler function would be called.

We will see the following output:

1
this is an useData
2
this is an useData
3
this is an useData
4
this is an useData
5
this is an useData
Enter fullscreen mode Exit fullscreen mode

Synchronous code, executed asynchronously

In Melang, code is written in a synchronized form. The advantage is logical coherence.

In traditional languages, synchronous writing also means synchronous processing, so the performance is low. But in Melang, the interpreter will execute completely asynchronously.

Example:

//a.mln
while (true) {
  @mln_msgQueueSend('queue', 'a');
  ret = @mln_msgQueueRecv('queue');
  @mln_print(ret);
}
Enter fullscreen mode Exit fullscreen mode
//b.mln
while (true) {
  ret = @mln_msgQueueRecv('queue');
  @mln_print(ret);
  @mln_msgQueueSend('queue', 'b');
}
Enter fullscreen mode Exit fullscreen mode

These two scripts use the message queue functions to send and receive messages from each other and print them out. For each task, its logic is sequential. For example, a.mln must send a message first, then receive the message, and then print. If b.mln does not send a message to a.mln, then a.mln will be suspended while receiving the message.

The above is just a simple example, and it is the same when it comes to network I/O. When data arrives on the socket, the interpreter will receive it, then return to the script layer, and change the script task from the suspended state to the running state.

Usage Scenarios

The current usage scenario of Melang is mainly embedded in other applications, which is basically the same as LUA. The Melang project on Github is a launcher. The launcher will call the script-related functions in the core library for initialization and execution. And of course, the core library is also open source.

Melang's core library provides many interfaces such as algorithms, data structures, event mechanisms, multi-process and multi-threaded frameworks. Based on this library, not only can obtain melang script, but also reduce development costs.

In addition, if an application uses the event processing interface provided by the core library, not only events can be processed, but scripts can also be executed in the same thread.

Melang provides a basic function library. Besides string, file system and network IO operations, it also provides functions for accessing MySQL8 and a series of functions such as encryption, decryption and communication.


Although the core library has been updated and upgraded for several years, the language is still in its infancy. And we still need to make a lot of efforts on it. Looking forward to your attention to this project. Thanks for reading.

Top comments (0)