Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 24 additions & 19 deletions core/src/Streamly/Internal/Data/Time/TimeSpec.hsc
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
{-# OPTIONS_GHC -Wno-identities #-}

#ifndef __GHCJS__
#include "config.h"
#endif

#include "Streamly/Internal/Data/Time/Clock/config-clock.h"

#include "MachDeps.h"

-- |
-- Module : Streamly.Internal.Data.Time.TimeSpec
-- Copyright : (c) 2019 Composewell Technologies
Expand All @@ -22,6 +14,14 @@ module Streamly.Internal.Data.Time.TimeSpec
)
where

#ifndef __GHCJS__
#include "config.h"
#endif

#include "Streamly/Internal/Data/Time/Clock/config-clock.h"

#include "MachDeps.h"

import Data.Int (Int64)
#if (WORD_SIZE_IN_BITS == 32)
import Data.Int (Int32)
Expand All @@ -41,20 +41,23 @@ tenPower9 :: Int64
tenPower9 = 1000000000

-------------------------------------------------------------------------------
-- TimeSpec representation
-- TimeSpec
-------------------------------------------------------------------------------

-- A structure storing seconds and nanoseconds as 'Int64' is the simplest and
-- fastest way to store practically large quantities of time with efficient
-- arithmetic operations. If we store nanoseconds using 'Integer' it can store
-- practically unbounded quantities but it may not be as efficient to
-- manipulate in performance critical applications. XXX need to measure the
-- performance.
-- | 'TimeSpec' can hold time values up to ~292 billion years at nanosecond
-- precision.
--
-- | Data type to represent practically large quantities of time efficiently.
-- It can represent time up to ~292 billion years at nanosecond resolution.
-- Use 'fromInteger' from the Num instance to create 'TimeSpec' from
-- nanoseconds. Use 'Eq' and 'Ord' instances for comparisons. Use the 'Num'
-- instance to perform arithmetic operations.
--
-- Note, we assume that 'nsec' is always less than 10^9. Also, when 'TimeSpec'
-- is negative then both 'sec' and 'nsec' must be negative.

-- XXX Use smart constructors to enforce these assumptions.
data TimeSpec = TimeSpec
{ sec :: {-# UNPACK #-} !Int64 -- ^ seconds
-- This could be Int32 instead but Int64 is as good.
, nsec :: {-# UNPACK #-} !Int64 -- ^ nanoseconds
} deriving (Eq, Read, Show)

Expand Down Expand Up @@ -88,11 +91,13 @@ adjustSign t@(TimeSpec s ns)
timeSpecToInteger :: TimeSpec -> Integer
timeSpecToInteger (TimeSpec s ns) = toInteger $ s * tenPower9 + ns

-- XXX Error on overflow?
-- | Note that the arithmetic operations may overflow silently.
instance Num TimeSpec where
{-# INLINE (+) #-}
t1 + t2 = adjustSign (addWithOverflow t1 t2)

-- XXX will this be more optimal if imlemented without "negate"?
-- XXX will this be more optimal if implemented without "negate"?
{-# INLINE (-) #-}
t1 - t2 = t1 + negate t2
t1 * t2 = fromInteger $ timeSpecToInteger t1 * timeSpecToInteger t2
Expand All @@ -104,7 +109,7 @@ instance Num TimeSpec where
{-# INLINE signum #-}
signum (TimeSpec s ns) | s == 0 = TimeSpec (signum ns) 0
| otherwise = TimeSpec (signum s) 0
-- This is fromNanoSecond64 Integer
-- | Convert 'Integer' nanoseconds to 'TimeSpec'.
{-# INLINE fromInteger #-}
fromInteger nanosec = TimeSpec (fromInteger s) (fromInteger ns)
where (s, ns) = nanosec `divMod` toInteger tenPower9
Expand Down
Loading