Skip to content
Merged
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
11 changes: 9 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
### Next Release v0.8.1 (TBD)
### Next Release v0.9.0 (Target Date: 5 April 2015)

* Pure Java implementations of
- `AtomicBoolean`
Expand All @@ -7,7 +7,14 @@
* Fixed bug when pruning Ruby thread pools
* Fixed bug in time calculations within `ScheduledTask`
* Default `count` in `CountDownLatch` to 1
* Use monotonic clock for timeouts on all platforms where supported
* Use monotonic clock for all timers via `Concurrent.monotonic_time`
- Use `Process.clock_gettime(Process::CLOCK_MONOTONIC)` when available
- Fallback to `java.lang.System.nanoTime()` on unsupported JRuby versions
- Pure Ruby implementation for everything else
- Effects `Concurrent.timer`, `Concurrent.timeout`, `TimerSet`, `TimerTask`, and `ScheduledTask`
* Deprecated all clock-time based timer scheduling
- Only support scheduling by delay
- Effects `Concurrent.timer`, `TimerSet`, and `ScheduledTask`

## Current Release v0.8.0 (25 January 2015)

Expand Down
148 changes: 0 additions & 148 deletions doc/scheduled_task.md

This file was deleted.

18 changes: 18 additions & 0 deletions lib/concurrent.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@
require 'concurrent/timer_task'
require 'concurrent/tvar'

# @!macro [new] monotonic_clock_warning
#
# @note Time calculations one all platforms and languages are sensitive to
# changes to the system clock. To alleviate the potential problems
# associated with changing the system clock while an application is running,
# most modern operating systems provide a monotonic clock that operates
# independently of the system clock. A monotonic clock cannot be used to
# determine human-friendly clock times. A monotonic clock is used exclusively
# for calculating time intervals. Not all Ruby platforms provide access to an
# operating system monotonic clock. On these platforms a pure-Ruby monotonic
# clock will be used as a fallback. An operating system monotonic clock is both
# faster and more reliable than the pure-Ruby implementation. The pure-Ruby
# implementation should be fast and reliable enough for most non-realtime
# operations. At this time the common Ruby platforms that provide access to an
# operating system monotonic clock are MRI 2.1 and above and JRuby (all versions).
#
# @see http://linux.die.net/man/3/clock_gettime Linux clock_gettime(3)

# Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell,
# F#, C#, Java, and classic concurrency patterns.
#
Expand Down
24 changes: 6 additions & 18 deletions lib/concurrent/atomic/condition.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'concurrent/utility/monotonic_time'

module Concurrent

# Condition is a better implementation of standard Ruby ConditionVariable. The
Expand Down Expand Up @@ -41,14 +43,16 @@ def initialize
# @param [Mutex] mutex the locked mutex guarding the wait
# @param [Object] timeout nil means no timeout
# @return [Result]
#
# @!macro monotonic_clock_warning
def wait(mutex, timeout = nil)
start_time = clock_time
start_time = Concurrent.monotonic_time
@condition.wait(mutex, timeout)

if timeout.nil?
Result.new(nil)
else
Result.new(start_time + timeout - clock_time)
Result.new(start_time + timeout - Concurrent.monotonic_time)
end
end

Expand All @@ -65,21 +69,5 @@ def broadcast
@condition.broadcast
true
end

private

if defined?(Process::CLOCK_MONOTONIC)
def clock_time
Process.clock_gettime Process::CLOCK_MONOTONIC
end
elsif RUBY_PLATFORM == 'java'
def clock_time
java.lang.System.nanoTime() / 1_000_000_000.0
end
else
def clock_time
Time.now.to_f
end
end
end
end
11 changes: 6 additions & 5 deletions lib/concurrent/executor/ruby_thread_pool_executor.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
require 'thread'

require_relative 'executor'
require 'concurrent/atomic/event'
require 'concurrent/executor/executor'
require 'concurrent/executor/ruby_thread_pool_worker'
require 'concurrent/utility/monotonic_time'

module Concurrent

Expand Down Expand Up @@ -91,7 +92,7 @@ def initialize(opts = {})
@largest_length = 0

@gc_interval = opts.fetch(:gc_interval, 1).to_i # undocumented
@last_gc_time = Time.now.to_f - [1.0, (@gc_interval * 2.0)].max
@last_gc_time = Concurrent.monotonic_time - [1.0, (@gc_interval * 2.0)].max
end

# @!macro executor_module_method_can_overflow_question
Expand Down Expand Up @@ -225,13 +226,13 @@ def ensure_capacity?
#
# @!visibility private
def prune_pool
if Time.now.to_f - @gc_interval >= @last_gc_time
if Concurrent.monotonic_time - @gc_interval >= @last_gc_time
@pool.delete_if { |worker| worker.dead? }
# send :stop for each thread over idletime
@pool.
select { |worker| @idletime != 0 && Time.now.to_f - @idletime > worker.last_activity }.
select { |worker| @idletime != 0 && Concurrent.monotonic_time - @idletime > worker.last_activity }.
each { @queue << :stop }
@last_gc_time = Time.now.to_f
@last_gc_time = Concurrent.monotonic_time
end
end

Expand Down
5 changes: 3 additions & 2 deletions lib/concurrent/executor/ruby_thread_pool_worker.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'thread'
require 'concurrent/logging'
require 'concurrent/utility/monotonic_time'

module Concurrent

Expand All @@ -12,7 +13,7 @@ def initialize(queue, parent)
@queue = queue
@parent = parent
@mutex = Mutex.new
@last_activity = Time.now.to_f
@last_activity = Concurrent.monotonic_time
@thread = nil
end

Expand Down Expand Up @@ -64,7 +65,7 @@ def run(thread = Thread.current)
# let it fail
log DEBUG, ex
ensure
@last_activity = Time.now.to_f
@last_activity = Concurrent.monotonic_time
@parent.on_end_task
end
end
Expand Down
Loading