Skip to content

Instantly share code, notes, and snippets.

@reusee
Created November 8, 2011 18:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reusee/1348701 to your computer and use it in GitHub Desktop.
Save reusee/1348701 to your computer and use it in GitHub Desktop.
lua object emulator
local yield = coroutine.yield
local create = coroutine.create
local status = coroutine.status
local resume = coroutine.resume
local setmetatable = setmetatable
local next = next
local pop = table.remove
local insert = table.insert
local type = type
local pairs = pairs
World_meta = {
__index = {
run = function(self)
while self:tick() do
end
end,
tick = function(self)
if self.stop then
do return false end
end
self:dispatch_signals()
self:do_tasks()
return true
end,
dispatch_signals = function(self)
while next(self.signals) ~= nil do
local signal = pop(self.signals)
local source = signal[1]
local target = signal[2]
local signal_type = signal[3]
local signal_data = signal[4]
if type(target) == 'string' then
target = self.named_objects[target]
end
insert(target.tasks, {'signal', source, signal_type, signal_data})
end
end,
do_tasks = function(self)
for _, obj in pairs(self.objects) do
if next(obj.tasks) ~= nil then
local task = pop(obj.tasks)
if type(task) == 'table' then
if task[1] == 'signal' then
local source = task[2]
local signal_type = task[3]
local signal_data = task[4]
for _, handler in pairs(obj.handlers[signal_type]) do
local c = create(handler)
resume(c, obj, source, signal_type, signal_data)
if status(c) ~= 'dead' then
insert(obj.tasks, c)
end
end
end
elseif type(task) == 'thread' then
resume(task)
if status(task) ~= 'dead' then
insert(obj.tasks, task)
end
end
end
end
end,
}
}
function World()
local world = {}
world.signals = {}
world.objects = {}
world.named_objects = {
world = world,
}
world.start_time = nil
world.count = nil
world.show_tps = false
world.stop = false
world.commands = {
stop = function()
world.stop = true
end,
}
setmetatable(world, World_meta)
return world
end
Thing_meta = {
__index = {
connect = function(self, signal_type, handler)
if self.handlers[signal_type] == nil then
self.handlers[signal_type] = {}
end
insert(self.handlers[signal_type], handler)
end,
send = function(self, target, signal_type, signal_data)
if target == 'world' then
self.world.commands[signal_type](signal_data)
else
insert(self.world.signals, {self, target, signal_type, signal_data})
end
end,
},
}
function Thing(world)
local obj = {}
obj.world = world
obj.tasks = {}
obj.handlers = {}
insert(world.objects, obj)
setmetatable(obj, Thing_meta)
return obj
end
world = World()
ping = Thing(world)
pong = Thing(world)
pong:connect('ping', function(self, source, signal, ttl)
if ttl < 1 then
self:send('world', 'stop')
end
--print('going to pong')
yield()
--print('really going to pong')
yield()
--print('i swear i am not a procrastinator')
yield()
--print('pong')
self:send(source, 'pong', ttl - 1)
end)
--pong:connect('ping', function(self, source, signal, ttl)
-- print('ah, someone pong me')
--end)
ping:connect('pong', function(self, source, signal, ttl)
if ttl < 1 then
self:send('world', 'stop')
end
--print('ping')
self:send(source, 'ping', ttl - 1)
end)
ping:send(pong, 'ping', 420000)
world:run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment