Structured Event-Driven Concurrency for Lua
[
v0.5 |
v0.4 |
v0.3 |
v0.2.1 |
v0.1
]
This is the unstable main branch.
Please, switch to stable v0.5.
[ About | Hello World! | Install & Run | Environments | Documentation | Resources ]
Atmos is a programming library for Lua that reconciles Structured Concurrency, Event-Driven Programming, and Functional Streams, extending classical structured programming with three main functionalities:
- Structured Deterministic Concurrency:
- A
taskprimitive with deterministic scheduling provides predictable behavior and safe abortion. - Structured primitives compose concurrent tasks with lexical scope (e.g.,
watching,every,par_or). - A
taskscontainer primitive holds attached tasks and control their lifecycle.
- A
- Event Signaling Mechanisms:
- An
awaitprimitive suspends a task and wait for events. - An
emitprimitive signals events and awake awaiting tasks.
- An
- Functional Streams (à la ReactiveX):
- Functional combinators for lazy (infinite) lists.
- Interoperability with tasks & events: tasks and events as streams, and streams as events.
- Safe finalization of stateful (task-based) streams.
Atmos is inspired by synchronous programming languages like Céu and Esterel.
During 5 seconds, displays Hello World! every second:
require "atmos.env.clock"
call(function ()
watching(clock{s=5}, function ()
every(clock{s=1}, function ()
print("Hello World!")
end)
end)
end)
We first import the builtin clock environment, which provides timers to
applications.
The call primitive receives a function with the application logic in Atmos,
as follows:
- The
watchingcommand will execute its inner function during 5 seconds. - The
everyloop will execute its inner function every second. - Once the
watchingterminates, thecallreturns back to Lua.
In Atmos, the lifetimes and schedules of tasks are determined by lexical structure. Tasks that would awake "simultaneously" instead do so in order of appearance in the source code. This enables reasoning about programs more statically based on the structure of the source code. Tasks that abort also abort their inner taks, which have a "last chance" to execute if applicable. Applying this to the above example:
- On the first, second, third, and fourth second,
everyawakes and prints"Hello World!" - On the fifth second,
watchingandeveryare both scheduled to awake. - The
everyawakes before the enclosingwatching, printing"Hello World!"for the fifth (and last) time. - Therefore,
callreturns after five seconds having printed"Hello World!"five times.
See the relevant section in the guide for other, more complex examples.
Now, the same specification, but using streams:
require "atmos.env.clock"
local S = require "atmos.streams"
call(function ()
local s1 = S.from(clock{s=1})
:tap(function()
print("Hello World!")
end)
local s2 = S.from(clock{s=5}):take(1)
S.paror(s1,s2):to() -- note that s1 comes before s2!
end)
s1is a periodic 1-second stream that prints the message on every occurrence, through thetapcombinator.s2is a periodic 5-seconds stream that terminates after its first occurrence, because oftake(1).S.parormerges the streams, terminating when either of them terminate.tois a sink that starts and exhausts the full stream pipeline.
sudo luarocks --lua-version=5.4 install atmos 0.5
lua5.4 <lua-path>/atmos/env/clock/exs/hello.lua
You may also clone the repository and copy part of the source tree, as follows,
into your Lua path (e.g., /usr/local/share/lua/5.4):
atmos
├── env/
│ ├── clock/
│ │ ├── exs/
│ │ │ ├── hello.lua
│ │ │ └── hello-rx.lua
│ │ └── init.lua
│ ├── iup/
│ │ ├── exs/
│ │ │ └── button-counter.lua
│ │ └── init.lua
│ ├── pico/
│ │ ├── exs/
│ │ │ └── click-drag-cancel.lua
│ │ └── init.lua
│ ├── sdl/
│ │ ├── exs/
│ │ │ ├── click-drag-cancel.lua
│ │ │ └── DejaVuSans.ttf
│ │ └── init.lua
│ └── socket/
│ ├── exs/
│ │ └── cli-srv.lua
│ └── init.lua
├── init.lua
├── run.lua
├── streams.lua
└── util.lua
Atmos depends on f-streams.
An environment is an external component that bridges input events from the real world into an Atmos application.
The standard distribution of Atmos provides the following environments:
atmos.env.clock: A simple pure-Lua environment that usesos.clockto issue timer events.atmos.env.socket: An environment that relies on luasocket to provide network communication.atmos.env.sdl: An environment that relies on lua-sdl2 to provide window, mouse, key, and timer events.sudo luarocks --lua-version=5.4 install lua-sdl2 2.0
atmos.env.pico: An environment that relies on pico-sdl-lua as a simpler alternative do SDL.sudo luarocks --lua-version=5.4 install pico-sdl 0.2
atmos.env.iup: An environment that relies on IUP (iup-lua) to provide graphical user interfaces (GUIs).
- A toy problem: Drag, Click, or Cancel
- A simple but complete 2D game in Atmos:
- Academic publications (Céu):
- Mailing list (Céu & Atmos):
