This repository was archived by the owner on Nov 20, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdining3.lua
More file actions
163 lines (142 loc) · 4.18 KB
/
dining3.lua
File metadata and controls
163 lines (142 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
--[[
This is the classical example of the dining philosophers
by Edsger W. Dijsktra.
The solution proposed here demonstrates the use of the
join patterns to ensure safety.
Note that this version is fair : all philosophers are able
to eat regularly.
]]
require "pithreads"
require "utils"
-- the number of philosophers
NBPHILOS = tonumber(arg and arg[1]) or 5
-- the number of resources (forks,plates,chairs)
NBRES = tonumber(arg and arg[2]) or 5
-- then quantity of noodle in each plate (nil cancels termination)
QUANTITY = tonumber(arg and arg[3]) or 10
-- global statistics
STATS = {}
-- the behavior of forks
function Fork(thread,take)
while true do
thread:signal(take)
--print(thread.name.." taken")
thread:wait(take)
--print(thread.name.." released")
end
end
-- the behavior of plates
function Plate(thread,eat,quantity)
while quantity==nil or quantity>0 do
thread:send(eat,1) -- one noodle
if quantity~=nil then
quantity = quantity - 1
end
end
thread:send(eat,0)
end
-- the behavior of chairs
function Chair(thread,seat,fork1,fork2,plate)
local leave = thread:new("leave:"..thread.name)
local ok = true
while ok do
thread:send(seat,fork1,fork2,plate,leave)
--print(thread.name.." used")
ok = thread:receive(leave)
--print(thread.name.." leaved")
end
print(thread.name.." removed")
end
-- the bevahior of philosophers
function Philo(thread,seat,activate)
local total = 0
while true do
print(thread.name .. " thinks")
local fork1,fork2,eat,leave = thread:receive(seat)
print(thread.name .. " seats")
local reply = thread:receive(activate)
print(thread.name .. " gets the reply code")
thread:join({ fork1:receive(), fork2:receive() },
function(f1,f2) print(thread.name .. " takes the forks")
end)()
local nb = thread:receive(eat)
total = total + nb
STATS[thread.name] = total
print(thread.name .. " eats " .. tostring(nb) .. " noodle(s)")
thread:signal(fork1)
thread:signal(fork2)
print(thread.name .. " releases the forks")
thread:signal(reply)
print(thread.name .. " abandons the reply code")
if nb==0 then
thread:send(leave,false)
print(thread.name .. " .. Nothing to eat ? leave the table")
thread:wait(reply)
return -- the threadess should die
else
thread:send(leave,true)
print(thread.name .. " leaves the table")
thread:wait(reply)
end
end
end
-- the reply codes dispatcher
function Dispatcher(thread,activate,nbres,nbthreads)
while true do
local threadcount = 1
local replies = {}
while threadcount <= nbthreads do
local first = threadcount
for i=first,nbres+first-1 do
table.insert(replies,thread:new("reply"..tostring(i)))
thread:send(activate,replies[threadcount])
threadcount = threadcount + 1
end
for i=first,nbres+first-1 do
thread:wait(replies[i])
end
end
for i,reply in ipairs(replies) do
thread:signal(reply)
end
end
end
agent = pithreads.init()
local seat = agent:new("seat")
local activate = agent:new("activate")
-- creating the forks and plates
local forks = {}
local plates = {}
for i=1,NBRES do
-- create the i-th fork
local fork = agent:new("fork"..tostring(i))
table.insert(forks,fork)
agent:spawn("Fork"..tostring(i),Fork,fork)
-- create the i-th plate
local plate = agent:new("plate"..tostring(i))
table.insert(plates,plate)
agent:spawn("Plate"..tostring(i),Plate,plate,QUANTITY)
end
-- creating the chairs
agent:spawn("Chair1",Chair,seat,forks[NBRES],forks[1],plates[1])
for i=2,NBRES do
agent:spawn("Chair"..tostring(i),Chair,seat,forks[i-1],forks[i],plates[i])
end
local inits = {}
for i=1,NBPHILOS do
local init = agent:new("init"..tostring(i))
table.insert(inits,init)
-- create the i-th philosopher
agent:spawn("Philo"..tostring(i),Philo,seat,activate)
end
agent:spawn("Dispatcher",Dispatcher,activate,NBRES,NBPHILOS)
print("Starting the agent")
agent:run()
print("Ending the agent")
print("Consumption statistics:")
local totals = 0
for pname,total in pairs(STATS) do
print(pname..": "..tostring(total))
totals = totals + total
end
print("Total consumption = " ..tostring(totals))