|
Tutorial
A Programmer's Introduction to redFOX
This is a brief introduction to redFOX. It is
intended to give a feel for what it does and how it works with a
minimum investment of the reader's time. (You can be out of here
in 20 minutes.) It contains simplifications and should not be taken
as definitive. The definitive version is in the Programmer's
Manual.
redFOX allows methods on C++ objects to be called
remotely. This is done using an automatically generated class called
a "dref" (short for distributed reference). For a given class T,
redFOX can generate a class dref<T>. A dref<T> knows
the location of the object it references and it has a method for
every method in T that calls the corresponding method on the remote
object. A dref should be thought of as a special kind of object
reference. Like an object reference, it is small and it can be copied.
Unlike an object reference, it remains valid when it is copied to
any other node. "Node" is the term we use for the scope in which
a compiled and linked program runs, including a memory, code, data
and threads. A node may be a Unix process, an embedded program or
something else. Nodes communicate through communication channels
such as sockets, through which redFOX passes the messages that implement
remote method calls.
Drefs form the nervous system of a redFOX distributed
application. They can create, destroy and call objects. They can
be copied as parameters to method calls to build up and maintain
complex relationships between objects on the various nodes running
the application.
Let us build a simple
redFOX application. Of course, it involves an object. The object
belongs to a class, announcer, which has one method, print. The
method takes a string parameter and sends it to std::cout with some
decoration. Here are the source files that define
the class.
announcer.h
#include <string>
class announcer {
public:
void print (const std::string &item);
}
#pragma dref<announcer> interface
announcer.cpp
#include <announcer.h>
#include <iostream>
void announcer::print (const std::string &item) {
std::cout << item << std::endl;
}
#pragma dref<announcer> implementation
This is simple C++
code, except for two non-standard pragmas. These pragmas instruct
redFOX to generate dref<announcer>.
Next we need two nodes.
We will run two programs, node_0 and node_1 on two different nodes.
How the nodes communicate
with each other is outside the scope of this introduction and the
programmer does not usually have to deal with it anyway.
Node_0.cpp does very
little. At (1), it tells the "node_manager" (the part of redFOX
that is visible to the application) to wait until it is shut down,
which in this case is never. This statement serves to stop the main
thread on node 0, so that (a) it will not terminate immediately
and (b) it does not waste processor time that is needed by the redFOX
runtime to process messages and execute method calls.
node_0.cpp
#include <redplain/node_manager.h>
int main () {
node_manager::instance().wait_for_shutdown(); // (1)
return 0;
}
Node_1.cpp does the
clever stuff. At (2), it remotely creates an announcer object on
node 0 and constructs a dref to it. This is possible because drefs
have special constructors that create objects on a remote heap.
These special constructors are how an application establishes meaningful
communications between nodes. At (3), the remote object is called,
causing "Hello World" to appear on the console of node 0. At (4),
the announcer is destroyed. Node 1 terminates without terminating
node 0, which allows node 0 to be left running while node 1 is re-run
repeatedly.
node_1.cpp
#include <redplain/dref.h>
#include "announcer.h"
int main () {
dref<announcer> an_announcer(0); // 0 is node id // (2)
an_announcer.print("Hello World"); // (3)
redplain::delete_object(an_announcer); // (4)
return 0;
}
How are node_0 and
node_1 compiled and linked? Node_0 is compiled and linked from node_0.cpp,
announcer.cpp and redfox.a using rcc in place of g++. rcc is the
redFOX code generator and it wraps g++, running it in the background.
Rcc can be used to compile regular C++ files as well as redFOX application
code, but it is faster to run g++ directly.
Node_1 is compiled
and linked from node_1.cpp, announcer.cpp and redfox.a.
Hopefully, you now have an idea of what redFOX
does. For the full story, see the Programmer's
Manual.
|