Skip to content

Instantly share code, notes, and snippets.

@beardhatcode
Created October 11, 2018 16:11
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 beardhatcode/d085244c8cf6430ac3fdb6cfca2ebef3 to your computer and use it in GitHub Desktop.
Save beardhatcode/d085244c8cf6430ac3fdb6cfca2ebef3 to your computer and use it in GitHub Desktop.
use "time"
use "random"
use "collections"
primitive Eating
primitive Thinking
class iso Stick
var taken:Bool = false
let id:USize val
new create(id':USize)=>
id = id'
actor Table
let _env: Env val
let _sticks: Array[(Stick iso|None)] ref
new create(env: Env, num: USize) =>
_sticks = Array[(Stick iso|None)]()
for i in Range(0,num) do
_sticks.push(recover Stick(i) end)
end
_env = env
be takeStick(num: USize, who:Philosopher,number:USize)=>
try
who.stick(num, _sticks.update(num,None)?)
else
who.stick(num, None.create())
end
be realeaseStick(num: USize,stick:Stick) =>
try
_sticks.update(num,consume stick)?
end
actor Philosopher
var state: Bool val = true
let _env: Env val
let _sticks:(USize,USize)
var _sticksOwn:((Stick iso|None),(Stick iso|None))
var _sticksPending:(Bool,Bool)
let _table:Table tag
let number:USize val
let rand:Rand = Rand()
new create(number': USize, env: Env, table: Table tag, left_stick:USize, right_stick:USize) =>
number = number'
_sticks = (left_stick,right_stick)
_sticksOwn = (None.create(),None.create())
_sticksPending = (false,false)
_table = table
_env = env
fun ref eat() =>
state = true
_env.out.print("@EATING " + number.string())
let l:Philosopher tag = this
let timers = Timers
let timer = Timer(recover iso object is TimerNotify
fun ref apply(timer: Timer ref, count: U64 val) : Bool val=> state = false; l.returnSticks(); false
fun ref cancel( timer: Timer ref) => None.create()
end end
, rand.next()/36893487000, 0)
timers(consume timer)
be stick(num:USize, s: (Stick iso|None)) =>
if ((_sticksPending._1 == false) and (_sticksPending._2 == false)) then return end
match s
| Stick(_sticks._1) => _sticksOwn = (consume s as Stick iso, _sticksOwn._2);_sticksPending = (false,_sticksPending._2)
| Stick(_sticks._2) => _sticksOwn = (_sticksOwn._1, consume s);_sticksPending = (_sticksPending._1, false)
| None => _sticksPending = (if num == _sticks._1 then false else _sticksPending._1 end, if num == _sticks._2 then false else _sticksPending._2 end)
end
_env.out.print("Stick got "+number.string()+" ("+_sticksOwn._1.string()+_sticksOwn._2.string()+")")
if (_sticksOwn._1 and _sticksOwn._2) then
this.eat()
else
if ((_sticksPending._1 == false) and (_sticksPending._2 == false)) then
this.returnSticks()
end
end
be returnSticks() =>
_env.out.print("return sticks "+number.string())
(var stick1,var stick2) = _sticksOwn = (false,false)
match stick1
| Stick => _table.realeaseStick(consume stick1, this)
| None => true
end
match stick2
| Stick => _table.realeaseStick(consume stick2, this)
| None => true
end
this()
be requestSticks()=>
_env.out.print("Request sticks " + number.string())
_sticksPending = (true,true)
_table.takeStick(_sticks._1,this,number)
_table.takeStick(_sticks._2,this,number)
be apply() =>
let l:Philosopher tag = this
_env.out.print("@THINK " + number.string())
let timers = Timers
let timer = Timer(recover iso object is TimerNotify
fun ref apply(timer: Timer ref, count: U64 val) : Bool val=>
l.requestSticks()
false
fun ref cancel( timer: Timer ref) => None.create()
end end
, rand.next()/36893487000, 0)
timers(consume timer)
actor Main
new create(env: Env) =>
env.out.print("Let's eat2!")
let table = Table(env,4)
for i in Range(0, 4) do
Philosopher(i,env, table, i, (i+1) % 4)()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment