Skip to content

Commit

Permalink
Use nanoseconds for Instant and Duration
Browse files Browse the repository at this point in the history
This removes the need for using floating point operations and
allocations, making it easier and cheaper to pass times/durations to the
VM. Operations such as adding a Duration to an Instant are now also more
reliable/consistent, as they're no longer susceptible to floating point
rounding errors.

The limitation is that we can only represent durations/monotonic clocks
that span up to 292 years, but this should prove more than sufficient
for 99.99% of all use cases of these types.

Changelog: changed
  • Loading branch information
yorickpeterse committed Sep 27, 2022
1 parent 8eac159 commit 64d8097
Show file tree
Hide file tree
Showing 17 changed files with 169 additions and 162 deletions.
2 changes: 1 addition & 1 deletion compiler/src/type_check/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1419,7 +1419,7 @@ pub(crate) fn define_builtin_functions(state: &mut State) -> bool {
(BIF::StdoutFlush, nil, int),
(BIF::StdoutWriteBytes, int, int),
(BIF::StdoutWriteString, int, int),
(BIF::TimeMonotonic, float, never),
(BIF::TimeMonotonic, int, never),
(BIF::TimeSystem, float, never),
(BIF::TimeSystemOffset, int, never),
(BIF::StringToLower, string, never),
Expand Down
13 changes: 0 additions & 13 deletions libstd/src/std/float.inko
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@ trait pub ToFloat {
fn pub to_float -> Float
}

# A type that can be converted into a Float by taking over ownership of the
# source value.
trait pub IntoFloat {
# Moves `self` into a `Float`.
fn pub move into_float -> Float
}

# A 64-bit floating point number.
class builtin Float {
# Returns a NaN.
Expand Down Expand Up @@ -223,12 +216,6 @@ impl ToFloat for Float {
}
}

impl IntoFloat for Float {
fn pub move into_float -> Float {
self
}
}

impl Clone for Float {
fn pub clone -> Self {
_INKO.float_clone(self)
Expand Down
8 changes: 1 addition & 7 deletions libstd/src/std/int.inko
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# The Int type.
import std::clone::Clone
import std::cmp::(Compare, Equal, Ordering)
import std::float::(IntoFloat, ToFloat)
import std::float::ToFloat
import std::fmt::(Format, Formatter)
import std::hash::(Hash, Hasher)
import std::ops::(
Expand Down Expand Up @@ -233,12 +233,6 @@ impl ToFloat for Int {
}
}

impl IntoFloat for Int {
fn pub move into_float -> Float {
to_float
}
}

impl Compare for Int {
fn pub cmp(other: ref Self) -> Ordering {
if self > other {
Expand Down
8 changes: 4 additions & 4 deletions libstd/src/std/net/socket.inko
Original file line number Diff line number Diff line change
Expand Up @@ -348,17 +348,17 @@ class pub Socket {

# Returns the value of the `SO_LINGER` option.
fn pub linger !! Error -> Duration {
let seconds =
let nanos =
try _INKO.socket_get_linger(@fd) else (e) throw Error.from_int(e)

Duration.from_seconds(seconds)
Duration.from_nanoseconds(nanos)
}

# Sets the value of the `SO_LINGER` option.
fn pub mut linger=(value: ref Duration) !! Error {
let secs = value.to_seconds
let nanos = value.to_nanoseconds

try _INKO.socket_set_linger(@fd, secs) else (e) throw Error.from_int(e)
try _INKO.socket_set_linger(@fd, nanos) else (e) throw Error.from_int(e)
}

# Returns the value of the `SO_RCVBUF` option.
Expand Down
12 changes: 9 additions & 3 deletions libstd/src/std/process.inko
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ fn pub panic(message: ref String) -> Never {
#
# The actual time the process is suspended for may be larger than the given
# duration.
#
# If the specified duration is less than or equal to zero, the process is
# rescheduled immediately.
fn pub sleep(time: ref Duration) {
_INKO.process_suspend(time.to_seconds)
_INKO.process_suspend(time.to_nanoseconds)
}

# Suspends the current process until one or more futures in the `pending` array
Expand Down Expand Up @@ -67,9 +70,12 @@ class builtin Future[T, E] {
#
# Similar to `Future.await`, this method blocks the calling process until
# either a value is produced or the timeout expires.
#
# If the given duration is less than or equal to zero, the process is
# rescheduled (more or less, but not necessarily) immediately after this call.
fn pub move await_for(time: ref Duration) !! E -> Option[T] {
let secs = time.to_seconds
let val = try { _INKO.future_get_for(self, secs) } else (e) { throw e as E }
let nanos = time.to_nanoseconds
let val = try { _INKO.future_get_for(self, nanos) } else (e) { throw e as E }

if _INKO.is_undefined(val) { Option.None } else { Option.Some(val as T) }
}
Expand Down
2 changes: 1 addition & 1 deletion libstd/src/std/test.inko
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ impl Reporter for Plain {
let dur = if duration.to_seconds >= 1.0 {
"{duration.to_seconds.round(decimals)} seconds"
} else {
"{duration.to_milliseconds.round(decimals)} milliseconds"
"{duration.to_milliseconds} milliseconds"
}

let failures = if failed {
Expand Down
Loading

0 comments on commit 64d8097

Please sign in to comment.