RTSync Tutorial 4 - Actors

Up until now, the only examples have been those with only one actor. Most practical programs written in RTSync will not only use one actor, but several working together simulaneously. Here is an example of a program using multiple actors:

  #include <iostream>
  using namespace std;
  
  void print(string &s)
  {
      cout << s << endl;
  }
  
  actor A
  {
      init
      {
          /* do nothing */
      }
  
      a()
      {
          /* call a method of B */
          B.b(50);
          /* print finished message */
          print("Method A.a() finished.");
      }
  }
  
  actor B
  {
      int i;
  
      init
      {
          i = 2;
      }
  
      b(int n)
      {
          /* do some random calculation */
          while(i < n)
          {
              i = i + 1;
          }
          /* print finished message */
          print("Method B.b() finished.");
      }
  }
  
  int main()
  {
      rt_start("A", "a");
  }

Here we have a second actor B introduced. This program looks quite similar to that in the last tutorial. This is done to illustrate a simple point. From C++ knowledge, one would expect that when the program finished, the console output would look something like this:

  Method B.b() finished.
  Method A.a() finished.

However this is not necessarily the case. It is possible that this may be what happens, however unlike C++, Java or several other languages, RTSync does not halt in a() when b() is called. Instead of waiting for b() to finish, a() will then execute the next line, with b() running on a new thread. In order to understand real-time programming, one must understand multithreaded programs. In a program it is possible to have multiple threads running at once. For example, an instant messenger program can have multiple conversations in separate windows at once. Each one of these may have it's own thread to handle interactions with it. Another thread may then be communicating with the server to retrieve messages in one conversation while the user is typing into a different conversation. RTSync handles this in a similar fashion, where each actor is running simulaneously and communicates with one another by messages. Instead of thinking of the line

  B.b(50);

as a method call with a parameter 50, it can be thought of as a message to B saying to run its method b() with the parameter 50.

There is a way for one method to wait for another method to finish, and that is by using the sync keyword. Here is an example:

  actor A
  {
      /* anything else in here */
      a()
      {
          sync B.b();
          print("Method A.a() finished.");
      }
  }

In this case, A.a() would wait until B.b() finished, guaranteed.

One other thing to note with this example is that the actor B is declared after the actor A. Normally in C++ if something makes a reference to something that has not been defined yet, the compiler gives an error. In RTSync, actors do not need to be declared before they can have messages passed to them by other actors. There is a reason for this, which will be discussed in much more detail in a later tutorial.