134 lines
3.2 KiB
Lua
134 lines
3.2 KiB
Lua
local oo = require "loop.simple"
|
|
local socket = require "socket"
|
|
|
|
math.randomseed(socket.gettime() * 1000)
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Philosopher Component
|
|
--------------------------------------------------------------------------------
|
|
|
|
Philosopher = oo.class{
|
|
name = "unamed",
|
|
hunger = 0,
|
|
has_left_fork = false,
|
|
has_right_fork = false,
|
|
}
|
|
|
|
function Philosopher:__init(name)
|
|
return oo.rawnew(self, {
|
|
name = name,
|
|
--time = 1.5 + math.random() * 3.6,
|
|
})
|
|
end
|
|
|
|
function Philosopher:sleep()
|
|
--oil.sleep(self.time)
|
|
oil.sleep(1.5 + math.random() * 3.6)
|
|
end
|
|
|
|
function Philosopher:notify()
|
|
local state
|
|
if self.has_left_fork and self.has_right_fork then state = "eating"
|
|
elseif self.hunger < 3 then state = "thinking"
|
|
elseif self.hunger < 10 then state = "hungry"
|
|
elseif self.hunger < 40 then state = "starving"
|
|
else state = "dead"
|
|
end
|
|
self.info:push{
|
|
name = self.name,
|
|
state = state,
|
|
ticks_since_last_meal = self.hunger,
|
|
has_left_fork = self.has_left_fork,
|
|
has_right_fork = self.has_right_fork,
|
|
}
|
|
end
|
|
|
|
function Philosopher:is_hungry()
|
|
return self.hunger > 3
|
|
end
|
|
|
|
function Philosopher:eat_some()
|
|
self.hunger = self.hunger - 3
|
|
if not self:is_hungry() then
|
|
self.hunger = 0
|
|
print(self.name.." has eaten.")
|
|
end
|
|
end
|
|
|
|
function Philosopher:release_forks()
|
|
print(self.name.." droped forks.")
|
|
self.left_fork:release()
|
|
self.right_fork:release()
|
|
self.has_left_fork = false
|
|
self.has_right_fork = false
|
|
return self:notify()
|
|
end
|
|
|
|
function Philosopher:get_more_hungry()
|
|
self.hunger = self.hunger + 1
|
|
end
|
|
|
|
function Philosopher:try_get_fork(fork)
|
|
if (not self["has_"..fork.."_fork"]) and self[fork.."_fork"] then
|
|
self["has_"..fork.."_fork"] = self[fork.."_fork"]:get()
|
|
if self["has_"..fork.."_fork"] then
|
|
print(self.name.." got "..fork.." fork.")
|
|
self:notify()
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
function Philosopher:update()
|
|
if self.has_left_fork and self.has_right_fork then
|
|
if self:is_hungry()
|
|
then self:eat_some()
|
|
else self:release_forks()
|
|
end
|
|
else
|
|
self:get_more_hungry()
|
|
if self:is_hungry() then
|
|
if self:try_get_fork("left") then return end
|
|
if self:try_get_fork("right") then return end
|
|
end
|
|
end
|
|
end
|
|
|
|
function Philosopher:start()
|
|
if not self.running then
|
|
self.running = true
|
|
return oil.newthread(function()
|
|
while not self.stopped do
|
|
self:update()
|
|
self:sleep()
|
|
end
|
|
self.running = nil
|
|
end)
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Philosopher Home
|
|
--------------------------------------------------------------------------------
|
|
|
|
require "adaptor"
|
|
|
|
PhilosopherHome = oo.class(nil, Adaptor)
|
|
|
|
function PhilosopherHome:create(name)
|
|
return Philosopher(name)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Exporting
|
|
--------------------------------------------------------------------------------
|
|
|
|
require "oil"
|
|
oil.main(function()
|
|
local orb = oil.init()
|
|
orb:loadidlfile("philo.idl")
|
|
oil.writeto("philo.ior",
|
|
orb:tostring(
|
|
orb:newservant(PhilosopherHome, nil, "PhilosopherHome")))
|
|
orb:run()
|
|
end) |