Skip to content

Commit b7a287d

Browse files
authored
Align basilisp.core/deref with Clojure to use timeout in ms (#1008)
Hi, could you please consider patch to update the `basilisp.core/deref` timeout argument to us ms instead of secs. It addresses #1007 This is to align with the same in `clojure.core/deref`. I have add a `promise` basilisp test and updated an existing `future` one. The tests check that the timeout for an unfulfilled promise returns within a range of 100ms. I believe this range provides sufficient buffer to avoid interference from parallel processing on the host. Thanks --------- Co-authored-by: ikappaki <[email protected]>
1 parent 4900515 commit b7a287d

File tree

5 files changed

+40
-15
lines changed

5 files changed

+40
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
* Types created via `deftype` and `reify` may declare supertypes as abstract (taking precedence over true `abc.ABC` types) and specify their member list using `^:abstract-members` metadata (#942)
1919
* Load functions (`load`, `load-file`, `load-reader`, etc.) now return the value of the last form evaluated. (#984)
2020
* nREPL server no longer hangs waiting for client connections to close on exit (#1002)
21+
* Align `basilisp.core/deref` with Clojure to by updating the timeout input argument to be in milliseconds instead of seconds (#1007)
2122

2223
### Fixed
2324
* Fix inconsistent behavior with `basilisp.core/with` when the `body` contains more than one form (#981)

src/basilisp/core.lpy

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -921,13 +921,13 @@
921921
"Dereference a delay, atom, promise, future, volatile, or Var and returns its contents.
922922

923923
If ``o`` is an object implementing :py:class:`basilisp.lang.interfaces.IBlockingDeref`
924-
and ``timeout-s`` and ``timeout-val`` are supplied, ``deref`` will wait at most
925-
``timeout-s`` seconds, returning ``timeout-val`` if ``timeout-s`` seconds elapse and
926-
``o`` has not returned."
924+
(i.e. futures and promises) and ``timeout-ms`` and ``timeout-val`` are supplied, ``deref``
925+
will wait at most ``timeout-ms`` milliseconds, returning ``timeout-val`` if ``timeout-ms``
926+
milliseconds elapse and ``o`` has not returned."
927927
([o]
928928
(basilisp.lang.runtime/deref o))
929-
([o timeout-s timeout-val]
930-
(basilisp.lang.runtime/deref o timeout-s timeout-val)))
929+
([o timeout-ms timeout-val]
930+
(basilisp.lang.runtime/deref o timeout-ms timeout-val)))
931931

932932
(defn ^:inline compare-and-set!
933933
"Atomically set the value of ``atom`` to ``new-val`` if and only if ``old-val`` is

src/basilisp/lang/runtime.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,20 +1454,23 @@ def partial_f(*inner_args, **inner_kwargs):
14541454

14551455

14561456
@functools.singledispatch
1457-
def deref(o, timeout_s=None, timeout_val=None):
1457+
def deref(o, timeout_ms=None, timeout_val=None):
14581458
"""Dereference a Deref object and return its contents.
14591459
1460-
If o is an object implementing IBlockingDeref and timeout_s and
1461-
timeout_val are supplied, deref will wait at most timeout_s seconds,
1462-
returning timeout_val if timeout_s seconds elapse and o has not
1460+
If o is an object implementing IBlockingDeref and timeout_ms and
1461+
timeout_val are supplied, deref will wait at most timeout_ms milliseconds,
1462+
returning timeout_val if timeout_ms milliseconds elapse and o has not
14631463
returned."""
14641464
raise TypeError(f"Object of type {type(o)} cannot be dereferenced")
14651465

14661466

14671467
@deref.register(IBlockingDeref)
14681468
def _deref_blocking(
1469-
o: IBlockingDeref, timeout_s: Optional[float] = None, timeout_val=None
1469+
o: IBlockingDeref, timeout_ms: Optional[int] = None, timeout_val=None
14701470
):
1471+
timeout_s = None
1472+
if timeout_ms is not None:
1473+
timeout_s = timeout_ms / 1000 if timeout_ms != 0 else 0
14711474
return o.deref(timeout_s, timeout_val)
14721475

14731476

tests/basilisp/contrib/nrepl_server_test.lpy

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@
612612
:target #(nr/start-server! {:server* server* :nrepl-port-file filename :host "0.0.0.0"})
613613
:daemon true)
614614
(.start))
615-
(let [server (deref server* 1 nil)]
615+
(let [server (deref server* 1000 nil)]
616616
(is server)
617617
(try
618618
(is (bio/exists? filename))
@@ -636,7 +636,7 @@
636636
:target #(nr/start-server! {:server* server*})
637637
:daemon true)]
638638
(.start server-thread)
639-
(let [server (deref server* 1 nil)]
639+
(let [server (deref server* 1000 nil)]
640640
(is server)
641641
(let [[host_ port] (py->lisp (.-server-address server))]
642642
(binding [*nrepl-port* port]
@@ -648,5 +648,5 @@
648648
(let [shutdown-thread (future (doto server
649649
(.server-close))
650650
:done)
651-
status (deref shutdown-thread 1 :time-out)]
651+
status (deref shutdown-thread 1000 :time-out)]
652652
(is (= :done status))))))))))

tests/basilisp/test_core_fns.lpy

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,21 @@
13991399
(is (= "lo w" (subs "hello world" 3 7)))
14001400
(is (thrown? python/IndexError (subs "hello world" 12 3))))
14011401

1402+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1403+
;; State Management Functions ;;
1404+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1405+
1406+
(deftest promises-test
1407+
(testing "timeout expires on time"
1408+
(let [p (promise)
1409+
start (time/perf-counter)
1410+
;; block for 100ms
1411+
ret (deref p 100 :timed-out)
1412+
end (time/perf-counter)
1413+
diff (- end start)]
1414+
(is (= :timed-out ret))
1415+
(is (< 0.1 diff 0.5) (str "deref timeout is outside of [100ms, 500ms] range: " diff "ms")))))
1416+
14021417
;;;;;;;;;;;;;
14031418
;; Futures ;;
14041419
;;;;;;;;;;;;;
@@ -1416,8 +1431,14 @@
14161431
(is (= true (realized? fut)))))
14171432

14181433
(testing "timed deref of future"
1419-
(let [fut (future (time/sleep 3))]
1420-
(is (= :timed-out (deref fut 0.01 :timed-out)))
1434+
(let [fut (future (time/sleep 3))
1435+
start (time/perf-counter)
1436+
;; block for 100ms
1437+
ret (deref fut 100 :timed-out)
1438+
end (time/perf-counter)
1439+
diff (- end start)]
1440+
(is (= :timed-out ret))
1441+
(is (< 0.1 diff 0.5) (str "deref timeout outside of [100ms, 500ms] range: " diff "ms"))
14211442
(is (= false (future-cancelled? fut)))
14221443
(is (= false (future-done? fut)))
14231444
;; can't always cancel a sleep-ed Future

0 commit comments

Comments
 (0)