In this lesson we introduce the notion of a vane, which should be thought of as a kernel module for Arvo (if you don't know what that means yet, just keep reading). We first present a primer on what vanes are and how they communicate, followed by an examination of the simplest vane, known as Behn (pronounced like "bane"), which is Arvo's timekeeper.
Following this lesson, we will introduce Gall, a vane used to build user space apps. Then we have a walkthrough where we construct an egg timer as a Gall app that interacts with Behn.
In order to introduce vanes, we must first introduce the concept of a kernel. The kernel is in some sense the "core" of an operating system, in that it has complete control over all events in the system and may perform any operation. It is the first part of the operating system to boot, and is responsible for spawning all other processes and routing their communication to one another. The tasks a kernel performs are very low level - managing memory, prioritizing processes, keeping track of time, managing hardware I/O, etc.
Kernel code is generally kept to be as minimal as possible, and so almost anything non-trivial is put into an extension called a kernel module. Vanes are kernel modules for Arvo. Arvo currently has eight vanes known as Ames, Behn, Clay, Dill, Eyre, Ford, Gall, and Hall. You can read a short description of each one in Arvo, along with a more thorough explanation of how vanes communicate than the following.
Vanes communicate with one another by exchanging chunks of data known as
moves. We will get into more detail above what a
move is in our example of Behn below, (and also see Arvo) but at a high level one should think of a
move as either a request from one vane to another or a response to a request. In our egg timer app, Gall and Behn will be exchanging
Notably, vanes are not something that a user ever interacts with directly. They live in an area of the memory called "kernel space", while all user processes live in user space. Applications in user space make system calls to the kernel, which the kernel may or may not obey (for security and stability purposes). These requests could be things such as asking for the time, getting the input of a hardware device, making an http request, or moving a file. In our egg timer app, we will be making system calls to ask Behn to handle the timer aspect.
In this section we introduce the simplest Arvo vane, Behn. This is not exhaustive, but just enough to know what is going on inside of Behn when we make a system call to it in the egg timer app. We discuss relevant types, some arms that are only called internally, and arms that may be called by another vane via a
Behn is an Arvo vane that acts as a simple timer. It allows vanes and applications to set timer events, which are managed in a simple priority queue.
An app or vane can make a request to Behn to be informed when a specified amount of time has elapsed. Behn then produces effects to begin a unix timer for that request. The unix timer informs Behn after the specified time has elapses, which then informs the requestee. There is no guarantee that the requestee will be informed of the elapsed timer at the precise moment it requested, or even that it will be close. The only guarantee is that the requester will be informed at some point after the allotted time has passed.
We review here some of the commonly used types in the Behn vane as found in
+$ timer [date=@da =duct]
timer consists of a
@da (an absolute date at which the timer will go off) and a
duct (representing the causal stack that began the timer). As part of its state,
Behn keeps track of a list of
+$ behn-state $: timers=(list timer) unix-duct=duct next-wake=(unit @da) drips=drip-manager ==
We see that a
behn-state is a list of all
Behn is currently keeping track of.
unix-duct is Behn's link to the unix timer.
next-wake is the next time that
Behn is supposed to inform a requestee that the specified timer has elapsed. We will ignore
drips for the purpose of this tutorial.
Arvo vanes communicate via
+$ move [p=duct q=(wind note gift:able)]
duct is a call stack, which is a list of
paths that represent a step in a causal chain of events. A
wind is a kernel action. See the following arm from
++ wind :: new kernel action |* [a=mold b=mold] :: forward+reverse $% [%pass p=path q=a] :: advance [%slip p=a] :: lateral [%give p=b] :: retreat ==
Here we see that
wind produces a wet gate that takes in two molds, which for the
move type for Behn are
gifts. When a vane needs to request something of another vane, it
note. When a vane produces a result that was requested, it
gift to the callee.
The following arms are part of the
event-core of Behn, which are essentially the internal functions of the Behn vane that are not directly accessible to other vanes and applications. We will not review all of them here, we only list some of most important ones.
This arm is what Behn uses to tell the unix timer when to
This arm is a dry gate that takes in a
timer and adds it to the list of
timers in the
++set-timer automatically places the new
timer in chronological order, so that the timer at the front of the list of
timers is the
timer that will expire the soonest.
++ wait |=(date=@da set-unix-wake(timers.state (set-timer [date duct])))
This arm is called when Behn is
note telling Behn to
%wait. This adds a
timer to the list of
timers in the
state and correspondingly tells the unix timer to tell Behn when the specified time has passed.
++ rest |=(date=@da set-unix-wake(timers.state (unset-timer [date duct])))
This undoes a
++wait operation. That is,
++rest removes a timer from the list of
This arm is ultimately called by the unix timer to let Behn know that a previously specified amount of time has elapsed.
++ born set-unix-wake(next-wake.state ~, unix-duct.state duct)
This arm is called when Behn is first launched. It gives Behn a
duct to the unix timer and initializes the
behn-state with the face
state with a null list of
Arvo talks to Behn via four arms,
++take, which ultimately call arms in the
event-core of which we have listed a subset above. Here we will only look at
When Behn is
note from another vane, that is enacted upon by Arvo via the
++call gate. The
note specifies what action to take, which are references to the internal arms. This is done by including in the
note a symbol such as
%wake, which ultimately call the arms with those names in the
When Behn is ready to inform another vane or application that a timer has elapsed, Arvo activates the
++take gate. That is, Arvo
gift from Behn that includes the symbol
%passes it to the the requestee.
%wake is the only kind of
gift that Behn can make, but other vanes may possess multiple responses.