/src/lib/sequencer/events_set.e

http://github.com/tybor/Liberty · Specman e · 495 lines · 357 code · 58 blank · 80 comment · 6 complexity · 6a80df57414558d7f4accc1d46b8d460 MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class EVENTS_SET
  5. --
  6. -- A set of events to be waited for. Expected events are set via the `expect' feature when the EVENTS_SET
  7. -- is not `queryable'. After having been waited for (see `wait'), the EVENTS_SET becomes `queryable' and
  8. -- events may be checked by using the `event_occurred' feature. To reuse the EVENTS_SET (make it not
  9. -- `queryable' again) one may call `reset'.
  10. --
  11. -- ----------------------------- ------------------------
  12. -- | | <-- `wait' --- | |
  13. -- | State: `queryable' | | State: not `queryable' |
  14. -- | (may call `event_occurred') | | (may call `expect') |
  15. -- | | -- `reset' --> | |
  16. -- ----------------------------- ------------------------
  17. --
  18. -- May be useful for:
  19. -- * time/date waiting (see TIME_EVENTS and PERIODIC_JOB).
  20. -- * checking if data are available in files without locking (see INPUT_STREAM.event_can_read
  21. -- and OUTPUT_STREAM.event_can_write).
  22. --
  23. -- See also JOB
  24. --
  25. insert
  26. ANY
  27. PLATFORM
  28. create {ANY}
  29. make
  30. feature {}
  31. make
  32. require
  33. create_events
  34. do
  35. read_set := sequencer_create_set
  36. write_set := sequencer_create_set
  37. exception_set := sequencer_create_set
  38. reset
  39. ensure
  40. queryable = False
  41. end
  42. feature {ANY}
  43. queryable: BOOLEAN
  44. -- At creation this object is not `queryable'. You have to configure the conditions you want to wait
  45. -- for (data on file, timeout...) using `expect'. When the configuration is done, you start waiting
  46. -- using `wait'. Then this object is `queryable', that means that you can query the state of the
  47. -- events, using `event_occurred'.
  48. reset
  49. -- Reset the event descriptors.
  50. --
  51. -- See also:
  52. -- * `expect'
  53. -- * `wait'
  54. -- * `exception'
  55. require
  56. reset_events
  57. do
  58. timeout := Maximum_integer
  59. expiration_valid := False
  60. current_time_valid := False
  61. sequencer_reset(read_set)
  62. sequencer_reset(write_set)
  63. sequencer_reset(exception_set)
  64. highest := -1
  65. read_size := 0
  66. write_size := 0
  67. exception_size := 0
  68. queryable := False
  69. ensure
  70. queryable = False
  71. end
  72. wait
  73. -- Blocks until requested condition (max time and/or data).
  74. --
  75. -- See also:
  76. -- * `expect'
  77. -- * `event_occurred'
  78. -- * `reset'
  79. require
  80. not queryable
  81. local
  82. now: MICROSECOND_TIME; s, us: INTEGER; remaining: REAL
  83. do
  84. if expiration_valid then
  85. now.update
  86. if now < expiration then
  87. remaining := now.elapsed_seconds(expiration)
  88. end
  89. if timeout / 1000 < remaining then
  90. remaining := timeout / 1000
  91. end
  92. else
  93. remaining := timeout / 1000
  94. end
  95. from
  96. s := remaining.floor.force_to_integer_32
  97. us := ((remaining - s) * 1000000).floor.force_to_integer_32
  98. until
  99. sequencer_wait(highest + 1,
  100. read_set, read_size, read_more,
  101. write_set, write_size, write_more,
  102. exception_set, exception_size, exception_more,
  103. s, us) /= -1
  104. loop
  105. end
  106. queryable := True
  107. current_time_valid := False
  108. ensure
  109. queryable
  110. end
  111. expect (event: EVENT_DESCRIPTOR)
  112. -- `wait' will return if that `event' happens.
  113. require
  114. not event_expected(event)
  115. not queryable
  116. action: mark_event_as_expected(event)
  117. do
  118. event.expect(Current)
  119. ensure
  120. event_expected(event)
  121. end
  122. event_occurred (event: EVENT_DESCRIPTOR): BOOLEAN
  123. -- True if `wait' returned because that `event' happened.
  124. require
  125. event_expected(event)
  126. queryable
  127. do
  128. Result := event.occurred(Current)
  129. end
  130. feature {EVENTS_SET_HANDLER} -- low level features
  131. expect_readable (descriptor: INTEGER)
  132. do
  133. sequencer_watch(read_set, descriptor)
  134. read_size := read_size + 1
  135. highest := highest.max(descriptor)
  136. end
  137. can_read (descriptor: INTEGER): BOOLEAN
  138. do
  139. Result := sequencer_is_ready(read_set, descriptor)
  140. end
  141. expect_writeable (descriptor: INTEGER)
  142. do
  143. sequencer_watch(write_set, descriptor)
  144. write_size := write_size + 1
  145. highest := highest.max(descriptor)
  146. end
  147. can_write (descriptor: INTEGER): BOOLEAN
  148. do
  149. Result := sequencer_is_ready(write_set, descriptor)
  150. end
  151. expect_exception (descriptor: INTEGER)
  152. do
  153. sequencer_watch(exception_set, descriptor)
  154. exception_size := exception_size + 1
  155. highest := highest.max(descriptor)
  156. end
  157. has_exception (descriptor: INTEGER): BOOLEAN
  158. do
  159. Result := sequencer_is_ready(exception_set, descriptor)
  160. end
  161. set_read_size (rs: like read_size)
  162. require
  163. rs > read_size
  164. do
  165. read_size := rs
  166. end
  167. set_write_size (ws: like write_size)
  168. require
  169. ws > write_size
  170. do
  171. write_size := ws
  172. end
  173. set_exception_size (es: like exception_size)
  174. require
  175. es > exception_size
  176. do
  177. exception_size := es
  178. end
  179. set_highest (h: like highest)
  180. require
  181. h > highest
  182. do
  183. highest := h
  184. end
  185. feature {EVENT_DESCRIPTOR}
  186. after (timeout_ms: INTEGER)
  187. -- `timeout_ms' is the max time in milliseconds to wait when
  188. -- wait begins.
  189. require
  190. timeout_ms >= 0
  191. not queryable
  192. do
  193. timeout := timeout.min(timeout_ms)
  194. end
  195. at (date: MICROSECOND_TIME)
  196. -- `date' is the last moment that`wait' can wait.
  197. require
  198. not queryable
  199. do
  200. if expiration_valid then
  201. expiration := date.min(expiration)
  202. else
  203. expiration := date
  204. expiration_valid := True
  205. end
  206. end
  207. when_data (file: INPUT_STREAM)
  208. require
  209. file /= Void
  210. file.is_connected
  211. file.has_descriptor
  212. not queryable
  213. do
  214. expect_readable(file.descriptor)
  215. end
  216. is_data (file: INPUT_STREAM): BOOLEAN
  217. require
  218. file /= Void
  219. file.is_connected
  220. file.has_descriptor
  221. queryable
  222. do
  223. Result := can_read(file.descriptor)
  224. end
  225. when_connection (server: SOCKET_SERVER)
  226. require
  227. server /= Void
  228. not queryable
  229. do
  230. expect_readable(server.fd)
  231. end
  232. is_connection (server: SOCKET_SERVER): BOOLEAN
  233. require
  234. server /= Void
  235. queryable
  236. do
  237. Result := can_read(server.fd)
  238. end
  239. when_free (file: OUTPUT_STREAM)
  240. require
  241. file /= Void
  242. file.is_connected
  243. file.has_descriptor
  244. not queryable
  245. do
  246. expect_writeable(file.descriptor)
  247. end
  248. is_free (file: OUTPUT_STREAM): BOOLEAN
  249. require
  250. file /= Void
  251. file.is_connected
  252. file.has_descriptor
  253. queryable
  254. do
  255. Result := can_write(file.descriptor)
  256. end
  257. when_exception (file: STREAM)
  258. require
  259. file /= Void
  260. file.is_connected
  261. file.has_descriptor
  262. not queryable
  263. do
  264. expect_exception(file.descriptor)
  265. end
  266. is_exception (file: STREAM): BOOLEAN
  267. require
  268. file /= Void
  269. file.is_connected
  270. file.has_descriptor
  271. queryable
  272. do
  273. Result := has_exception(file.descriptor)
  274. end
  275. when_expecter (expecter: EVENTS_EXPECTER)
  276. require
  277. expecter /= Void
  278. not queryable
  279. do
  280. expecter.expect(read_set, write_set, exception_set)
  281. read_more := expecter.expected_read
  282. write_more := expecter.expected_write
  283. exception_more := expecter.expected_exception
  284. highest := highest.max(expecter.expected_highest)
  285. end
  286. has_expecter (expecter: EVENTS_EXPECTER): BOOLEAN
  287. require
  288. expecter /= Void
  289. queryable
  290. do
  291. Result := expecter.happened(read_set, write_set, exception_set)
  292. end
  293. feature {JOB, TIME_EVENT}
  294. current_time: MICROSECOND_TIME
  295. do
  296. if not current_time_valid then
  297. current_time_valid := True
  298. current_time_memory.update
  299. end
  300. Result := current_time_memory
  301. end
  302. feature {ANY} -- Expected events
  303. event_expected (a_event: EVENT_DESCRIPTOR): BOOLEAN
  304. -- True in check modes if the event is expected. Always False in boost mode. Exported to {ANY} only
  305. -- because the language requires it.
  306. --
  307. -- CAVEAT: '''Use only in require/ensure clauses.''' It's very important. In boost mode, it will
  308. -- always be False. It's meant to catch programming mistakes, not as a guard. If you feel the need to
  309. -- call that feature, please check your algorithm. Twice. And don't use it.
  310. --
  311. -- Tip: only call `event_occurred' on events that passed to `expect' (I mean, the ''same'' object,
  312. -- ''not'' a twin!)
  313. do
  314. Result := events /= Void and then events.fast_has(a_event)
  315. ensure
  316. definition: Result = events.fast_has(a_event)
  317. equivalence: Result = a_event.expected(Current)
  318. end
  319. feature {} -- Expected events
  320. --| Clever use of assertions to be sure not to create arrays in boost mode
  321. events: FAST_ARRAY[EVENT_DESCRIPTOR]
  322. -- This array is created only if the assertion level is at least require_check. That's why all the
  323. -- functions below are used only in contracts.
  324. mark_event_as_expected (a_event: EVENT_DESCRIPTOR): BOOLEAN
  325. -- Mark the event as expected and return True. Use only in require clauses.
  326. do
  327. events.add_last(a_event)
  328. Result := True
  329. ensure
  330. Result
  331. end
  332. create_events: BOOLEAN
  333. -- Create the events array. Use only in require clauses.
  334. do
  335. if events = Void then
  336. create events.make(0)
  337. Result := True
  338. end
  339. end
  340. reset_events: BOOLEAN
  341. -- Empties the events array. Use only in require clauses.
  342. local
  343. i: INTEGER
  344. do
  345. from
  346. i := events.lower
  347. until
  348. i > events.upper
  349. loop
  350. events.item(i).reset(Current)
  351. i := i + 1
  352. end
  353. events.clear_count
  354. Result := True
  355. end
  356. feature {}
  357. timeout: INTEGER
  358. expiration: MICROSECOND_TIME
  359. expiration_valid: BOOLEAN
  360. current_time_memory: MICROSECOND_TIME
  361. current_time_valid: BOOLEAN
  362. read_set: POINTER
  363. read_size: INTEGER
  364. read_more: BOOLEAN
  365. write_set: POINTER
  366. write_size: INTEGER
  367. write_more: BOOLEAN
  368. exception_set: POINTER
  369. exception_size: INTEGER
  370. exception_more: BOOLEAN
  371. highest: INTEGER
  372. sequencer_create_set: POINTER
  373. external "plug_in"
  374. alias "{
  375. location: "${sys}/plugins"
  376. module_name: "sequencer"
  377. feature_name: "sequencer_create_set"
  378. }"
  379. end
  380. sequencer_reset (set: POINTER)
  381. external "plug_in"
  382. alias "{
  383. location: "${sys}/plugins"
  384. module_name: "sequencer"
  385. feature_name: "sequencer_reset"
  386. }"
  387. end
  388. sequencer_watch (set: POINTER; file: INTEGER)
  389. external "plug_in"
  390. alias "{
  391. location: "${sys}/plugins"
  392. module_name: "sequencer"
  393. feature_name: "sequencer_watch"
  394. }"
  395. end
  396. sequencer_is_ready (set: POINTER; file: INTEGER): BOOLEAN
  397. external "plug_in"
  398. alias "{
  399. location: "${sys}/plugins"
  400. module_name: "sequencer"
  401. feature_name: "sequencer_is_ready"
  402. }"
  403. end
  404. sequencer_wait (n: INTEGER;
  405. rset: POINTER; rsize: INTEGER; rmote: BOOLEAN;
  406. wset: POINTER; wsize: INTEGER; wmore: BOOLEAN;
  407. eset:POINTER; esize: INTEGER; emore: BOOLEAN;
  408. s, us: INTEGER): INTEGER
  409. --return -1 if signal interrupt occurred
  410. external "plug_in"
  411. alias "{
  412. location: "${sys}/plugins"
  413. module_name: "sequencer"
  414. feature_name: "sequencer_wait"
  415. }"
  416. end
  417. end -- class EVENTS_SET
  418. --
  419. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  420. --
  421. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  422. -- of this software and associated documentation files (the "Software"), to deal
  423. -- in the Software without restriction, including without limitation the rights
  424. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  425. -- copies of the Software, and to permit persons to whom the Software is
  426. -- furnished to do so, subject to the following conditions:
  427. --
  428. -- The above copyright notice and this permission notice shall be included in
  429. -- all copies or substantial portions of the Software.
  430. --
  431. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  432. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  433. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  434. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  435. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  436. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  437. -- THE SOFTWARE.