Factor common TimeSpec methods into module.

This commit is contained in:
Patrick Mahoney 2012-02-01 20:32:40 -06:00
parent 71aa552213
commit ffe1298731
4 changed files with 40 additions and 21 deletions

View File

@ -83,10 +83,6 @@ module ProcessShared
sem_wait(@sem) sem_wait(@sem)
end end
NS_PER_S = 1e9
US_PER_NS = 1000
TV_NSEC_MAX = (NS_PER_S - 1)
# Decrement the value of the semaphore if it can be done # Decrement the value of the semaphore if it can be done
# immediately (i.e. if it was non-zero). Otherwise, wait up to # immediately (i.e. if it was non-zero). Otherwise, wait up to
# +timeout+ seconds until another process increments via {#post}. # +timeout+ seconds until another process increments via {#post}.
@ -100,24 +96,9 @@ module ProcessShared
def try_wait(timeout = nil) def try_wait(timeout = nil)
if timeout if timeout
now = TimeVal.new now = TimeVal.new
abs_timeout = TimeSpec.new
LibC.gettimeofday(now, nil) LibC.gettimeofday(now, nil)
abs_timeout = now.to_time_spec
abs_timeout[:tv_sec] = now[:tv_sec]; abs_timeout.add_seconds!(timeout)
abs_timeout[:tv_nsec] = now[:tv_usec] * US_PER_NS
# add timeout in seconds to abs_timeout; careful with rounding
sec = timeout.floor
nsec = ((timeout - sec) * NS_PER_S).floor
abs_timeout[:tv_sec] += sec
abs_timeout[:tv_nsec] += nsec
while abs_timeout[:tv_nsec] > TV_NSEC_MAX
abs_timeout[:tv_sec] += 1
abs_timeout[:tv_nsec] -= NS_PER_S
end
sem_timedwait(@sem, abs_timeout) sem_timedwait(@sem, abs_timeout)
else else
sem_trywait(@sem) sem_trywait(@sem)

View File

@ -1,8 +1,11 @@
require 'ffi' require 'ffi'
require 'process_shared/time_spec'
module ProcessShared module ProcessShared
module Posix module Posix
class TimeSpec < FFI::Struct class TimeSpec < FFI::Struct
include ProcessShared::TimeSpec
layout(:tv_sec, :time_t, layout(:tv_sec, :time_t,
:tv_nsec, :long) :tv_nsec, :long)
end end

View File

@ -1,10 +1,23 @@
require 'ffi' require 'ffi'
require 'process_shared/posix/time_spec'
module ProcessShared module ProcessShared
module Posix module Posix
class TimeVal < FFI::Struct class TimeVal < FFI::Struct
US_PER_NS = 1000
layout(:tv_sec, :time_t, layout(:tv_sec, :time_t,
:tv_usec, :suseconds_t) :tv_usec, :suseconds_t)
def to_time_spec
ts = TimeSpec.new
ts[:tv_sec] = self[:tv_sec];
ts[:tv_nsec] = self[:tv_usec] * US_PER_NS
ts
end
end end
end end
end end

View File

@ -0,0 +1,22 @@
module ProcessShared
module TimeSpec
NS_PER_S = 1e9
US_PER_NS = 1000
TV_NSEC_MAX = (NS_PER_S - 1)
# Assuming self responds to setting the value of [:tv_sec] and
# [:tv_nsec], add +secs+ to the time spec.
def add_seconds!(float_sec)
# add timeout in seconds to abs_timeout; careful with rounding
sec = float_sec.floor
nsec = ((float_sec - sec) * NS_PER_S).floor
self[:tv_sec] += sec
self[:tv_nsec] += nsec
while self[:tv_nsec] > TV_NSEC_MAX
self[:tv_sec] += 1
self[:tv_nsec] -= NS_PER_S
end
end
end
end