richards.lua 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115
  1. -- This code is derived from the SOM benchmarks, see AUTHORS.md file.
  2. --
  3. -- Copyright (c) 2016 Francois Perrad <[email protected]>
  4. --
  5. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  6. -- of this software and associated documentation files (the 'Software'), to deal
  7. -- in the Software without restriction, including without limitation the rights
  8. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. -- copies of the Software, and to permit persons to whom the Software is
  10. -- furnished to do so, subject to the following conditions:
  11. --
  12. -- The above copyright notice and this permission notice shall be included in
  13. -- all copies or substantial portions of the Software.
  14. --
  15. -- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. -- THE SOFTWARE.
  22. --[[
  23. The module 'bit' is available with:
  24. * LuaJIT
  25. * LuaBitOp extension which is available for:
  26. * Lua 5.1
  27. * Lua 5.2
  28. The module 'bit32' is available with:
  29. * Lua 5.2
  30. * Lua 5.3 when compiled with LUA_COMPAT_5_2
  31. The bitwise operators are added to Lua 5.3 as new lexemes (there causes
  32. lexical error in older version)
  33. --]]
  34. local band, bxor, rshift
  35. if _VERSION < 'Lua 5.3' then
  36. local bit = bit32 or require'bit'
  37. band = bit.band
  38. bxor = bit.bxor
  39. rshift = bit.rshift
  40. else
  41. band = assert(load'--[[band]] return function (a, b) return a & b end')()
  42. bxor = assert(load'--[[bxor]] return function (a, b) return a ~ b end')()
  43. rshift = assert(load'--[[rshift]] return function (a, b) return a >> b end')()
  44. end
  45. local alloc_array
  46. local ok, table_new = pcall(require, 'table.new') -- LuaJIT 2.1 extension
  47. if ok then
  48. alloc_array = function (n)
  49. local t = table_new(n, 1)
  50. t.n = n
  51. return t
  52. end
  53. else
  54. alloc_array = function (n)
  55. local t = {}
  56. t.n = n
  57. return t
  58. end
  59. end
  60. local Vector = {_CLASS = 'Vector'} do
  61. local floor = math.floor
  62. function Vector.new (size)
  63. local obj = {
  64. storage = alloc_array(size or 50),
  65. first_idx = 1,
  66. last_idx = 1,
  67. }
  68. return setmetatable(obj, {__index = Vector})
  69. end
  70. function Vector.with (elem)
  71. local v = Vector.new(1)
  72. v:append(elem)
  73. return v
  74. end
  75. function Vector:at (idx)
  76. if idx > self.storage.n then
  77. return nil
  78. end
  79. return self.storage[idx]
  80. end
  81. function Vector:at_put (idx, val)
  82. if idx > self.storage.n then
  83. local new_n = self.storage.n
  84. while idx > new_n do
  85. new_n = new_n * 2
  86. end
  87. local new_storage = alloc_array(new_n)
  88. for i = 1, self.storage.n do
  89. new_storage[i] = self.storage[i]
  90. end
  91. self.storage = new_storage
  92. end
  93. self.storage[idx] = val
  94. if self.last_idx < idx + 1 then
  95. self.last_idx = idx + 1
  96. end
  97. end
  98. function Vector:append (elem)
  99. if self.last_idx > self.storage.n then
  100. -- Need to expand capacity first
  101. local new_storage = alloc_array(2 * self.storage.n)
  102. for i = 1, self.storage.n do
  103. new_storage[i] = self.storage[i]
  104. end
  105. self.storage = new_storage
  106. end
  107. self.storage[self.last_idx] = elem
  108. self.last_idx = self.last_idx + 1
  109. end
  110. function Vector:is_empty ()
  111. return self.last_idx == self.first_idx
  112. end
  113. function Vector:each (fn)
  114. for i = self.first_idx, self.last_idx - 1 do
  115. fn(self.storage[i])
  116. end
  117. end
  118. function Vector:has_some (fn)
  119. for i = self.first_idx, self.last_idx - 1 do
  120. if fn(self.storage[i]) then
  121. return true
  122. end
  123. end
  124. return false
  125. end
  126. function Vector:get_one (fn)
  127. for i = self.first_idx, self.last_idx - 1 do
  128. local e = self.storage[i]
  129. if fn(e) then
  130. return e
  131. end
  132. end
  133. return nil
  134. end
  135. function Vector:remove_first ()
  136. if self:is_empty() then
  137. return nil
  138. end
  139. self.first_idx = self.first_idx + 1
  140. return self.storage[self.first_idx - 1]
  141. end
  142. function Vector:remove (obj)
  143. local new_array = alloc_array(self:capacity())
  144. local new_last = 1
  145. local found = false
  146. self:each(function (it)
  147. if it == obj then
  148. found = true
  149. else
  150. new_array[new_last] = it
  151. new_last = new_last + 1
  152. end
  153. end)
  154. self.storage = new_array
  155. self.last_idx = new_last
  156. self.first_idx = 1
  157. return found
  158. end
  159. function Vector:remove_all ()
  160. self.first_idx = 1
  161. self.last_idx = 1
  162. self.storage = alloc_array(self:capacity())
  163. end
  164. function Vector:size ()
  165. return self.last_idx - self.first_idx
  166. end
  167. function Vector:capacity ()
  168. return self.storage.n
  169. end
  170. function Vector:sort (fn)
  171. -- Make the argument, block, be the criterion for ordering elements of
  172. -- the receiver.
  173. -- Sort blocks with side effects may not work right.
  174. if self:size() > 0 then
  175. self:sort_range(self.first_idx, self.last_idx - 1, fn)
  176. end
  177. end
  178. function Vector:sort_range (i, j, fn)
  179. assert(fn)
  180. -- The prefix d means the data at that index.
  181. local n = j + 1 - i
  182. if n <= 1 then
  183. -- Nothing to sort
  184. return
  185. end
  186. local storage = self.storage
  187. -- Sort di, dj
  188. local di = storage[i]
  189. local dj = storage[j]
  190. -- i.e., should di precede dj?
  191. if not fn(di, dj) then
  192. local tmp = storage[i]
  193. storage[i] = storage[j]
  194. storage[j] = tmp
  195. local tt = di
  196. di = dj
  197. dj = tt
  198. end
  199. -- NOTE: For DeltaBlue, this is never reached.
  200. if n > 2 then -- More than two elements.
  201. local ij = floor((i + j) / 2) -- ij is the midpoint of i and j.
  202. local dij = storage[ij] -- Sort di,dij,dj. Make dij be their median.
  203. if fn(di, dij) then -- i.e. should di precede dij?
  204. if not fn(dij, dj) then -- i.e., should dij precede dj?
  205. local tmp = storage[j]
  206. storage[j] = storage[ij]
  207. storage[ij] = tmp
  208. dij = dj
  209. end
  210. else -- i.e. di should come after dij
  211. local tmp = storage[i]
  212. storage[i] = storage[ij]
  213. storage[ij] = tmp
  214. dij = di
  215. end
  216. if n > 3 then -- More than three elements.
  217. -- Find k>i and l<j such that dk,dij,dl are in reverse order.
  218. -- Swap k and l. Repeat this procedure until k and l pass each other.
  219. local k = i
  220. local l = j - 1
  221. while true do
  222. -- i.e. while dl succeeds dij
  223. while k <= l and fn(dij, storage[l]) do
  224. l = l - 1
  225. end
  226. k = k + 1
  227. -- i.e. while dij succeeds dk
  228. while k <= l and fn(storage[k], dij) do
  229. k = k + 1
  230. end
  231. if k > l then
  232. break
  233. end
  234. local tmp = storage[k]
  235. storage[k] = storage[l]
  236. storage[l] = tmp
  237. end
  238. -- Now l < k (either 1 or 2 less), and di through dl are all
  239. -- less than or equal to dk through dj. Sort those two segments.
  240. self:sort_range(i, l, fn)
  241. self:sort_range(k, j, fn)
  242. end
  243. end
  244. end
  245. end -- class Vector
  246. local Set = {_CLASS = 'Set'} do
  247. local INITIAL_SIZE = 10
  248. function Set.new (size)
  249. local obj = {
  250. items = Vector.new(size or INITIAL_SIZE)
  251. }
  252. return setmetatable(obj, {__index = Set})
  253. end
  254. function Set:size ()
  255. return self.items:size()
  256. end
  257. function Set:each (fn)
  258. self.items:each(fn)
  259. end
  260. function Set:has_some (fn)
  261. return self.items:has_some(fn)
  262. end
  263. function Set:get_one (fn)
  264. return self.items:get_one(fn)
  265. end
  266. function Set:add (obj)
  267. if not self:contains(obj) then
  268. self.items:append(obj)
  269. end
  270. end
  271. function Set:remove_all ()
  272. self.items:remove_all()
  273. end
  274. function Set:collect (fn)
  275. local coll = Vector.new()
  276. self:each(function (it)
  277. coll:append(fn(it))
  278. end)
  279. return coll
  280. end
  281. function Set:contains (obj)
  282. return self:has_some(function (it) return it == obj end)
  283. end
  284. end -- class Set
  285. local IdentitySet = {_CLASS = 'IdentitySet'} do
  286. setmetatable(IdentitySet, {__index = Set})
  287. function IdentitySet.new (size)
  288. local obj = Set.new(size)
  289. return setmetatable(obj, {__index = IdentitySet})
  290. end
  291. function IdentitySet:contains (obj)
  292. return self:has_some(function (it) return it == obj end)
  293. end
  294. end -- class IdentitySet
  295. local Entry = {_CLASS = 'Entry'} do
  296. function Entry.new (hash, key, value, next)
  297. local obj = {
  298. hash = hash,
  299. key = key,
  300. value = value,
  301. next = next,
  302. }
  303. return setmetatable(obj, {__index = Entry})
  304. end
  305. function Entry:match (hash, key)
  306. return self.hash == hash and self.key == key
  307. end
  308. end -- class Entry
  309. local Dictionary = {_CLASS = 'Dictionary'} do
  310. local INITIAL_CAPACITY = 16
  311. function Dictionary.new (size)
  312. local obj = {
  313. buckets = alloc_array(size or INITIAL_CAPACITY),
  314. size = 0,
  315. }
  316. return setmetatable(obj, {__index = Dictionary})
  317. end
  318. function Dictionary:hash (key)
  319. if not key then
  320. return 0
  321. end
  322. local hash = key:custom_hash()
  323. return bxor(hash, rshift(hash, 16))
  324. end
  325. function Dictionary:is_empty ()
  326. return self.size == 0
  327. end
  328. function Dictionary:get_bucket_idx (hash)
  329. return band(self.buckets.n - 1, hash) + 1
  330. end
  331. function Dictionary:get_bucket (hash)
  332. return self.buckets[self:get_bucket_idx(hash)]
  333. end
  334. function Dictionary:at (key)
  335. local hash = self:hash(key)
  336. local e = self:get_bucket(hash)
  337. while e do
  338. if e:match(hash, key) then
  339. return e.value
  340. end
  341. e = e.next
  342. end
  343. return nil
  344. end
  345. function Dictionary:contains_key (key)
  346. local hash = self:hash(key)
  347. local e = self:get_bucket(hash)
  348. while e do
  349. if e.match(hash, key) then
  350. return true
  351. end
  352. e = e.next
  353. end
  354. return false
  355. end
  356. function Dictionary:at_put (key, value)
  357. local hash = self:hash(key)
  358. local i = self:get_bucket_idx(hash)
  359. local current = self.buckets[i]
  360. if not current then
  361. self.buckets[i] = self:new_entry(key, value, hash)
  362. self.size = self.size + 1
  363. else
  364. self:insert_bucket_entry(key, value, hash, current)
  365. end
  366. if self.size > self.buckets.n then
  367. self:resize()
  368. end
  369. end
  370. function Dictionary:new_entry (key, value, hash)
  371. return Entry.new(hash, key, value, nil)
  372. end
  373. function Dictionary:insert_bucket_entry (key, value, hash, head)
  374. local current = head
  375. while true do
  376. if current:match(hash, key) then
  377. current.value = value
  378. return
  379. end
  380. if not current.next then
  381. self.size = self.size + 1
  382. current.next = self:new_entry(key, value, hash)
  383. return
  384. end
  385. current = current.next
  386. end
  387. end
  388. function Dictionary:resize ()
  389. local old_storage = self.buckets
  390. self.buckets = alloc_array(old_storage.n * 2)
  391. self:transfer_entries(old_storage)
  392. end
  393. function Dictionary:transfer_entries (old_storage)
  394. local buckets = self.buckets
  395. for i = 1, old_storage.n do
  396. local current = old_storage[i]
  397. if current then
  398. old_storage[i] = nil
  399. if not current.next then
  400. local hash = band(current.hash, buckets.n - 1) + 1
  401. buckets[hash] = current
  402. else
  403. self:split_bucket(old_storage, i, current)
  404. end
  405. end
  406. end
  407. end
  408. function Dictionary:split_bucket (old_storage, i, head)
  409. local lo_head, lo_tail = nil, nil
  410. local hi_head, hi_tail = nil, nil
  411. local current = head
  412. while current do
  413. if band(current.hash, old_storage.n) == 0 then
  414. if not lo_tail then
  415. lo_head = current
  416. else
  417. lo_tail.next = current
  418. end
  419. lo_tail = current
  420. else
  421. if not hi_tail then
  422. hi_head = current
  423. else
  424. hi_tail.next = current
  425. end
  426. hi_tail = current
  427. end
  428. current = current.next
  429. end
  430. if lo_tail then
  431. lo_tail.next = nil
  432. self.buckets[i] = lo_head
  433. end
  434. if hi_tail then
  435. hi_tail.next = nil
  436. self.buckets[i + old_storage.n] = hi_head
  437. end
  438. end
  439. function Dictionary:remove_all ()
  440. self.buckets = alloc_array(self.buckets.n)
  441. self.size = 0
  442. end
  443. function Dictionary:keys ()
  444. local keys = Vector.new(self.size)
  445. local buckets = self.buckets
  446. for i = 1, buckets.n do
  447. local current = buckets[i]
  448. while current do
  449. keys:append(current.key)
  450. current = current.next
  451. end
  452. end
  453. return keys
  454. end
  455. function Dictionary:values ()
  456. local vals = Vector.new(self.size)
  457. local buckets = self.buckets
  458. for i = 1, buckets.n do
  459. local current = buckets[i]
  460. while current do
  461. vals:append(current.value)
  462. current = current.next
  463. end
  464. end
  465. return vals
  466. end
  467. end -- class Dictionary
  468. local IdEntry = {_CLASS = 'IdEntry'} do
  469. setmetatable(IdEntry, {__index = Entry})
  470. function IdEntry.new (hash, key, value, next)
  471. local obj = Entry.new (hash, key, value, next)
  472. return setmetatable(obj, {__index = IdEntry})
  473. end
  474. function IdEntry:match (hash, key)
  475. return self.hash == hash and self.key == key
  476. end
  477. end -- class IdEntry
  478. local IdentityDictionary = {_CLASS = 'IdentityDictionary'} do
  479. setmetatable(IdentityDictionary, {__index = Dictionary})
  480. function IdentityDictionary.new (size)
  481. local obj = Dictionary.new (size)
  482. return setmetatable(obj, {__index = Dictionary})
  483. end
  484. function IdentityDictionary:new_entry (key, value, hash)
  485. return IdEntry.new(hash, key, value, nil)
  486. end
  487. end -- class IdentityDictionary
  488. local Random = {_CLASS = 'Random'} do
  489. function Random.new ()
  490. local obj = {seed = 74755}
  491. return setmetatable(obj, {__index = Random})
  492. end
  493. function Random:next ()
  494. self.seed = band(((self.seed * 1309) + 13849), 65535);
  495. return self.seed;
  496. end
  497. end -- class Random
  498. ---------------------------------
  499. local benchmark = {} do
  500. function benchmark:inner_benchmark_loop (inner_iterations)
  501. for _ = 1, inner_iterations do
  502. if not self:verify_result(self:benchmark()) then
  503. return false
  504. end
  505. end
  506. return true
  507. end
  508. function benchmark:benchmark ()
  509. error 'subclass_responsibility'
  510. end
  511. function benchmark:verify_result ()
  512. error 'subclass_responsibility'
  513. end
  514. end
  515. ---------------------------------
  516. local NO_TASK = nil
  517. local NO_WORK = nil
  518. local IDLER = 1
  519. local WORKER = 2
  520. local HANDLER_A = 3
  521. local HANDLER_B = 4
  522. local DEVICE_A = 5
  523. local DEVICE_B = 6
  524. local TRACING = false
  525. local RBObject = {_CLASS = 'RBObject'} do
  526. function RBObject:append (packet, queue_head)
  527. packet.link = NO_WORK
  528. if NO_WORK == queue_head then
  529. return packet
  530. end
  531. local mouse = queue_head
  532. local link = mouse.link
  533. while NO_WORK ~= link do
  534. mouse = link
  535. link = mouse.link
  536. end
  537. mouse.link = packet
  538. return queue_head
  539. end
  540. end -- abstract RBObject
  541. local DeviceTaskDataRecord = {_CLASS = 'DeviceTaskDataRecord'} do
  542. setmetatable(DeviceTaskDataRecord, {__index = RBObject})
  543. function DeviceTaskDataRecord.new ()
  544. local obj = {
  545. pending = NO_WORK,
  546. }
  547. return setmetatable(obj, {__index = DeviceTaskDataRecord})
  548. end
  549. end -- class DeviceTaskDataRecord
  550. local HandlerTaskDataRecord = {_CLASS = 'HandlerTaskDataRecord'} do
  551. setmetatable(HandlerTaskDataRecord, {__index = RBObject})
  552. function HandlerTaskDataRecord.new ()
  553. local obj = {
  554. work_in = NO_WORK,
  555. device_in = NO_WORK,
  556. }
  557. return setmetatable(obj, {__index = HandlerTaskDataRecord})
  558. end
  559. function HandlerTaskDataRecord:device_in_add (packet)
  560. self.device_in = self:append(packet, self.device_in)
  561. end
  562. function HandlerTaskDataRecord:work_in_add (packet)
  563. self.work_in = self:append(packet, self.work_in)
  564. end
  565. end -- class HandlerTaskDataRecord
  566. local IdleTaskDataRecord = {_CLASS = 'IdleTaskDataRecord'} do
  567. setmetatable(IdleTaskDataRecord, {__index = RBObject})
  568. function IdleTaskDataRecord.new ()
  569. local obj = {
  570. control = 1,
  571. count = 10000,
  572. }
  573. return setmetatable(obj, {__index = IdleTaskDataRecord})
  574. end
  575. end -- class IdleTaskDataRecord
  576. local WorkerTaskDataRecord = {_CLASS = 'WorkerTaskDataRecord'} do
  577. setmetatable(WorkerTaskDataRecord, {__index = RBObject})
  578. function WorkerTaskDataRecord.new ()
  579. local obj = {
  580. destination = HANDLER_A,
  581. count = 0,
  582. }
  583. return setmetatable(obj, {__index = WorkerTaskDataRecord})
  584. end
  585. end -- class WorkerTaskDataRecord
  586. local Packet = {_CLASS = 'Packet'} do
  587. setmetatable(Packet, {__index = RBObject})
  588. function Packet.new (link, identity, kind)
  589. local obj = {
  590. link = link,
  591. kind = kind,
  592. identity = identity,
  593. datum = 1,
  594. data = {0, 0, 0, 0},
  595. }
  596. return setmetatable(obj, {__index = Packet})
  597. end
  598. end -- class Packet
  599. local TaskState = {_CLASS = 'TaskState'} do
  600. setmetatable(TaskState, {__index = RBObject})
  601. function TaskState.new ()
  602. local obj = {
  603. task_holding = false,
  604. task_waiting = false,
  605. packt_pending = false,
  606. }
  607. return setmetatable(obj, {__index = TaskState})
  608. end
  609. function TaskState:is_packet_pending ()
  610. return self.packt_pending
  611. end
  612. function TaskState:is_task_waiting ()
  613. return self.task_waiting
  614. end
  615. function TaskState:is_task_holding ()
  616. return self.task_holding
  617. end
  618. function TaskState:packet_pending ()
  619. self.packt_pending = true
  620. self.task_waiting = false
  621. self.task_holding = false
  622. return self
  623. end
  624. function TaskState:running ()
  625. self.packt_pending = false
  626. self.task_waiting = false
  627. self.task_holding = false
  628. return self
  629. end
  630. function TaskState:waiting ()
  631. self.packt_pending = false
  632. self.task_holding = false
  633. self.task_waiting = true
  634. return self
  635. end
  636. function TaskState:waiting_with_packet ()
  637. self.task_holding = false
  638. self.task_waiting = true
  639. self.packt_pending = true
  640. return self
  641. end
  642. function TaskState:is_running ()
  643. return not self.packt_pending and not self.task_waiting and not self.task_holding
  644. end
  645. function TaskState:is_task_holding_or_waiting ()
  646. return self.task_holding or (not self.packt_pending and self.task_waiting)
  647. end
  648. function TaskState:is_waiting ()
  649. return not self.packt_pending and self.task_waiting and not self.task_holding
  650. end
  651. function TaskState:is_waiting_with_packet ()
  652. return self.packt_pending and self.task_waiting and not self.task_holding
  653. end
  654. function TaskState.create_packet_pending ()
  655. return TaskState.new():packet_pending()
  656. end
  657. function TaskState.create_running ()
  658. return TaskState.new():running()
  659. end
  660. function TaskState.create_waiting ()
  661. return TaskState.new():waiting()
  662. end
  663. function TaskState.create_waiting_with_packet ()
  664. return TaskState.new():waiting_with_packet()
  665. end
  666. end -- class TaskState
  667. local TaskControlBlock = {_CLASS = 'TaskControlBlock'} do
  668. setmetatable(TaskControlBlock, {__index = TaskState})
  669. function TaskControlBlock.new (link, identity, priority, initial_work_queue,
  670. initial_state, private_data, fn)
  671. local obj = {
  672. link = link,
  673. identity = identity,
  674. priority = priority,
  675. input = initial_work_queue,
  676. handle = private_data,
  677. packt_pending = initial_state:is_packet_pending(),
  678. task_waiting = initial_state:is_task_waiting(),
  679. task_holding = initial_state:is_task_holding(),
  680. fn = fn,
  681. }
  682. return setmetatable(obj, {__index = TaskControlBlock})
  683. end
  684. function TaskControlBlock:add_input_and_check_priority (packet, old_task)
  685. if NO_WORK == self.input then
  686. self.input = packet
  687. self.packt_pending = true
  688. if self.priority > old_task.priority then
  689. return self
  690. end
  691. else
  692. self.input = self:append(packet, self.input)
  693. end
  694. return old_task
  695. end
  696. function TaskControlBlock:run_task ()
  697. local message
  698. if self:is_waiting_with_packet() then
  699. message = self.input
  700. self.input = message.link
  701. if NO_WORK == self.input then
  702. self:running()
  703. else
  704. self:packet_pending()
  705. end
  706. else
  707. message = NO_WORK
  708. end
  709. return self.fn(message, self.handle)
  710. end
  711. end -- class TaskControlBlock
  712. local Scheduler = {_CLASS = 'Scheduler'} do
  713. setmetatable(Scheduler, {__index = RBObject})
  714. local DEVICE_PACKET_KIND = 0
  715. local WORK_PACKET_KIND = 1
  716. local DATA_SIZE = 4
  717. function Scheduler.new ()
  718. local obj = {
  719. -- init tracing
  720. layout = 0,
  721. -- init scheduler
  722. task_list = NO_TASK,
  723. current_task = NO_TASK,
  724. current_task_identity = 0,
  725. task_table = {NO_TASK, NO_TASK, NO_TASK, NO_TASK, NO_TASK, NO_TASK},
  726. queue_count = 0,
  727. hold_count = 0,
  728. }
  729. return setmetatable(obj, {__index = Scheduler})
  730. end
  731. function Scheduler:create_device (identity, priority, work, state)
  732. self:create_task(identity, priority, work, state,
  733. DeviceTaskDataRecord.new(),
  734. function (packet, data)
  735. if NO_WORK == packet then
  736. packet = data.pending
  737. if NO_WORK == packet then
  738. return self:wait()
  739. else
  740. data.pending = NO_WORK
  741. return self:queue_packet(packet)
  742. end
  743. else
  744. data.pending = packet
  745. if TRACING then
  746. self:trace(packet.datum)
  747. end
  748. return self:hold_self()
  749. end
  750. end)
  751. end
  752. function Scheduler:create_handler (identity, priority, work, state)
  753. self:create_task(identity, priority, work, state,
  754. HandlerTaskDataRecord.new(),
  755. function (packet, data)
  756. if NO_WORK ~= packet then
  757. if WORK_PACKET_KIND == packet.kind then
  758. data:work_in_add(packet)
  759. else
  760. data:device_in_add(packet)
  761. end
  762. end
  763. local work_packet = data.work_in
  764. if NO_WORK == work_packet then
  765. return self:wait()
  766. else
  767. local count = work_packet.datum
  768. if count > DATA_SIZE then
  769. data.work_in = work_packet.link
  770. return self:queue_packet(work_packet)
  771. else
  772. local device_packet = data.device_in
  773. if NO_WORK == device_packet then
  774. return self:wait()
  775. else
  776. data.device_in = device_packet.link
  777. device_packet.datum = work_packet.data[count]
  778. work_packet.datum = count + 1
  779. return self:queue_packet(device_packet)
  780. end
  781. end
  782. end
  783. end)
  784. end
  785. function Scheduler:create_idler (identity, priority, work, state)
  786. self:create_task(identity, priority, work, state,
  787. IdleTaskDataRecord.new(),
  788. function (_, data)
  789. data.count = data.count - 1
  790. if 0 == data.count then
  791. return self:hold_self()
  792. else
  793. if 0 == data.control & 1 then
  794. data.control = data.control / 2
  795. return self:release(DEVICE_A)
  796. else
  797. data.control = ((data.control - 1) / 2) ~ 53256
  798. return self:release(DEVICE_B)
  799. end
  800. end
  801. end)
  802. end
  803. function Scheduler:create_packet (link, identity, kind)
  804. return Packet.new(link, identity, kind)
  805. end
  806. function Scheduler:create_task (identity, priority, work, state, data, fn)
  807. local tcb = TaskControlBlock.new(self.task_list, identity, priority,
  808. work, state, data, fn)
  809. self.task_list = tcb
  810. self.task_table[identity] = tcb
  811. end
  812. function Scheduler:create_worker (identity, priority, work, state)
  813. self:create_task(identity, priority, work, state,
  814. WorkerTaskDataRecord.new(),
  815. function (packet, data)
  816. if NO_WORK == packet then
  817. return self:wait()
  818. else
  819. data.destination = (HANDLER_A == data.destination) and HANDLER_B or HANDLER_A
  820. packet.identity = data.destination
  821. packet.datum = 1
  822. for i = 1, DATA_SIZE do
  823. data.count = data.count + 1
  824. if data.count > 26 then
  825. data.count = 1
  826. end
  827. packet.data[i] = 65 + data.count - 1
  828. end
  829. return self:queue_packet(packet)
  830. end
  831. end)
  832. end
  833. function Scheduler:start ()
  834. local queue
  835. self:create_idler(IDLER, 0, NO_WORK, TaskState.create_running())
  836. queue = self:create_packet(NO_WORK, WORKER, WORK_PACKET_KIND)
  837. queue = self:create_packet(queue, WORKER, WORK_PACKET_KIND)
  838. self:create_worker(WORKER, 1000, queue, TaskState.create_waiting_with_packet())
  839. queue = self:create_packet(NO_WORK, DEVICE_A, DEVICE_PACKET_KIND)
  840. queue = self:create_packet(queue, DEVICE_A, DEVICE_PACKET_KIND)
  841. queue = self:create_packet(queue, DEVICE_A, DEVICE_PACKET_KIND)
  842. self:create_handler(HANDLER_A, 2000, queue, TaskState.create_waiting_with_packet())
  843. queue = self:create_packet(NO_WORK, DEVICE_B, DEVICE_PACKET_KIND)
  844. queue = self:create_packet(queue, DEVICE_B, DEVICE_PACKET_KIND)
  845. queue = self:create_packet(queue, DEVICE_B, DEVICE_PACKET_KIND)
  846. self:create_handler(HANDLER_B, 3000, queue, TaskState.create_waiting_with_packet())
  847. self:create_device(DEVICE_A, 4000, NO_WORK, TaskState.create_waiting())
  848. self:create_device(DEVICE_B, 5000, NO_WORK, TaskState.create_waiting())
  849. self:schedule()
  850. return self.queue_count == 23246 and self.hold_count == 9297
  851. end
  852. function Scheduler:find_task (identity)
  853. local task = self.task_table[identity]
  854. assert(task ~= NO_TASK, 'find_task failed')
  855. return task
  856. end
  857. function Scheduler:hold_self ()
  858. self.hold_count = self.hold_count + 1
  859. local current_task = self.current_task
  860. current_task.task_holding = true
  861. return current_task.link
  862. end
  863. function Scheduler:queue_packet (packet)
  864. local task = self:find_task(packet.identity)
  865. if NO_TASK == task then
  866. return NO_TASK
  867. end
  868. self.queue_count = self.queue_count + 1
  869. packet.link = NO_WORK
  870. packet.identity = self.current_task_identity
  871. return task:add_input_and_check_priority(packet, self.current_task)
  872. end
  873. function Scheduler:release (identity)
  874. local task = self:find_task(identity)
  875. if NO_TASK == task then
  876. return NO_TASK
  877. end
  878. task.task_holding = false
  879. if task.priority > self.current_task.priority then
  880. return task
  881. else
  882. return self.current_task
  883. end
  884. end
  885. function Scheduler:trace (id)
  886. self.layout = self.layout - 1
  887. if 0 >= self.layout then
  888. io.stdout:write'\n'
  889. self.layout = 50
  890. end
  891. io.stdout:write(tostring(id))
  892. end
  893. function Scheduler:wait ()
  894. local current_task = self.current_task
  895. current_task.task_waiting = true
  896. return current_task
  897. end
  898. function Scheduler:schedule ()
  899. self.current_task = self.task_list
  900. while self.current_task ~= NO_TASK do
  901. if self.current_task:is_task_holding_or_waiting() then
  902. self.current_task = self.current_task.link
  903. else
  904. self.current_task_identity = self.current_task.identity
  905. if TRACING then
  906. self:trace(self.current_task_identity - 1)
  907. end
  908. self.current_task = self.current_task:run_task()
  909. end
  910. end
  911. end
  912. end -- class Scheduler
  913. local richards = {} do
  914. setmetatable(richards, {__index = benchmark})
  915. function richards:benchmark ()
  916. return Scheduler.new():start()
  917. end
  918. function richards:verify_result (result)
  919. return result
  920. end
  921. end -- object richards
  922. return function(N)
  923. richards:inner_benchmark_loop(N)
  924. end