Permalink
Browse files

license and readme

  • Loading branch information...
steveyen committed Aug 8, 2009
1 parent 99586ea commit 3750723db0dabfc1aaabb4baf411fd83c6be7f94
Showing with 94 additions and 19 deletions.
  1. +22 −0 LICENSE
  2. +33 −0 README
  3. +24 −19 actor_post_office.lua
  4. +15 −0 test_ping.lua
View
22 LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2009 NorthScale, Inc.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
View
33 README
@@ -0,0 +1,33 @@
+actor_post_office
+
+Simple, erlang-like actor system for Lua.
+
+Single main thread, non-distributed, local-only, based on coroutines.
+
+It should be compatible with LuaLanes & LuaThreads, if you wish to
+build a program with multiple apartments of OS threads.
+
+Example, from test_ping.lua file...
+
+ apo = require('actor_post_office')
+
+ function player(self_addr, name)
+ while true do
+ ball = apo.recv()
+ print(name .. " got ball, hits " .. ball.hits)
+ apo.send(ball.from, { from = self_addr, hits = ball.hits + 1 })
+ end
+ end
+
+ mike_addr = apo.spawn(player, "Mike")
+ mary_addr = apo.spawn(player, "Mary")
+
+ apo.send(mike_addr, { from = mary_addr, hits = 1})
+
+A very similar, more advanced and featureful system is ConcurrentLua,
+which was an inspiration to me for learning coroutines.
+
+-- steve.yen
+
+
+
View
@@ -17,15 +17,14 @@ local last_addr = 0
local map_addr_to_coro = {} -- table, key'ed by addr.
local map_coro_to_addr = {} -- table, key'ed by coro.
-local envelopes_in = {}
-local envelopes_out = {}
+local envelopes = {}
----------------------------------------
local main_todos = {} -- array of funcs/closures, to be run on main thread.
local function run_main_todos()
- -- Only do work on main thread.
+ -- Check first if we're the main thread.
if coroutine.running() == nil then
local todo = nil
repeat
@@ -39,6 +38,17 @@ end
----------------------------------------
+local function next_addr()
+ local curr_addr
+
+ repeat
+ last_addr = last_addr + 1
+ curr_addr = tostring(last_addr)
+ until map_addr_to_coro[curr_addr] == nil
+
+ return curr_addr
+end
+
local function unregister(addr)
local coro = map_addr_to_coro[addr]
if coro then
@@ -50,9 +60,7 @@ end
local function register(coro)
unregister(map_coro_to_addr[coro])
- last_addr = last_addr + 1
-
- local curr_addr = tostring(last_addr)
+ local curr_addr = next_addr()
map_addr_to_coro[curr_addr] = coro
map_coro_to_addr[coro] = curr_addr
@@ -63,7 +71,7 @@ end
----------------------------------------
local function deliver_envelope(envelope)
- -- Must be main thread.
+ -- Must be invoked on main thread.
if envelope then
local coro = map_addr_to_coro[envelope.dest_addr]
if coro and coroutine.status(coro) ~= 'dead' then
@@ -75,14 +83,14 @@ local function deliver_envelope(envelope)
end
local function step()
- -- Must be main thread.
+ -- Must be invoked on main thread.
run_main_todos()
- return deliver_envelope(table.remove(envelopes_in, 1))
+ return deliver_envelope(table.remove(envelopes, 1))
end
local function loop_until_empty()
- -- Only do work on main thread.
+ -- Check first if we're the main thread.
if coroutine.running() == nil then
local go = true
while go do
@@ -91,7 +99,7 @@ local function loop_until_empty()
end
end
-local function loop(timeout)
+local function loop()
while true do
loop_until_empty()
end
@@ -100,7 +108,7 @@ end
----------------------------------------
local function send_msg(dest_addr, msg)
- table.insert(envelopes_in, { dest_addr = dest_addr, msg = msg })
+ table.insert(envelopes, { dest_addr = dest_addr, msg = msg })
loop_until_empty()
end
@@ -144,13 +152,10 @@ end
----------------------------------------
local actor_post_office = {
- spawn = spawn,
- send = send,
- send_msg = send_msg,
-
- recv = recv,
- step = step,
-
+ spawn = spawn,
+ recv = recv,
+ send = send,
+ step = step,
loop = loop,
loop_until_empty = loop_until_empty
}
View
@@ -0,0 +1,15 @@
+apo = require('actor_post_office')
+
+function player(self_addr, name)
+ while true do
+ ball = apo.recv()
+ print(name .. " got ball, hits " .. ball.hits)
+ apo.send(ball.from, { from = self_addr, hits = ball.hits + 1 })
+ end
+end
+
+mike_addr = apo.spawn(player, "Mike")
+mary_addr = apo.spawn(player, "Mary")
+
+apo.send(mike_addr, { from = mary_addr, hits = 1})
+

0 comments on commit 3750723

Please sign in to comment.