• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ruby-concurrency / concurrent-ruby / #2835

05 Oct 2014 10:16PM UTC coverage: 45.201% (-49.6%) from 94.81%
#2835

push

jdantonio
Merge pull request #158 from obrok/promise-composition

Promise composition

2 of 15 new or added lines in 1 file covered. (13.33%)

1514 existing lines in 84 files now uncovered.

1375 of 3042 relevant lines covered (45.2%)

0.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.0
/lib/concurrent/delay.rb
1
require 'thread'
1✔
2
require 'concurrent/obligation'
1✔
3
require 'concurrent/options_parser'
1✔
4

5
module Concurrent
1✔
6

7
  # Lazy evaluation of a block yielding an immutable result. Useful for expensive
8
  # operations that may never be needed.
9
  #
10
  # A `Delay` is similar to `Future` but solves a different problem.
11
  # Where a `Future` schedules an operation for immediate execution and
12
  # performs the operation asynchronously, a `Delay` (as the name implies)
13
  # delays execution of the operation until the result is actually needed.
14
  # 
15
  # When a `Delay` is created its state is set to `pending`. The value and
16
  # reason are both `nil`. The first time the `#value` method is called the
17
  # enclosed opration will be run and the calling thread will block. Other
18
  # threads attempting to call `#value` will block as well. Once the operation
19
  # is complete the *value* will be set to the result of the operation or the
20
  # *reason* will be set to the raised exception, as appropriate. All threads
21
  # blocked on `#value` will return. Subsequent calls to `#value` will immediately
22
  # return the cached value. The operation will only be run once. This means that
23
  # any side effects created by the operation will only happen once as well.
24
  #
25
  # `Delay` includes the `Concurrent::Dereferenceable` mixin to support thread
26
  # safety of the reference returned by `#value`.
27
  #
28
  # @since 0.6.0
29
  #
30
  # @see Concurrent::Dereferenceable
31
  #
32
  # @see http://clojuredocs.org/clojure_core/clojure.core/delay
33
  # @see http://aphyr.com/posts/306-clojure-from-the-ground-up-state
34
  class Delay
1✔
35
    include Obligation
1✔
36

37
    # Create a new `Delay` in the `:pending` state.
38
    #
39
    # @yield the delayed operation to perform
40
    #
41
    # @param [Hash] opts the options to create a message with
42
    # @option opts [String] :dup_on_deref (false) call `#dup` before returning the data
43
    # @option opts [String] :freeze_on_deref (false) call `#freeze` before returning the data
44
    # @option opts [String] :copy_on_deref (nil) call the given `Proc` passing the internal value and
45
    #   returning the value returned from the proc
46
    #
47
    # @raise [ArgumentError] if no block is given
48
    def initialize(opts = {}, &block)
1✔
49
      raise ArgumentError.new('no block given') unless block_given?
6✔
50

51
      init_obligation
6✔
52
      @state = :pending
6✔
53
      @task  = block
6✔
54
      set_deref_options(opts)
6✔
55
      @task_executor = OptionsParser.get_task_executor_from(opts)
6✔
56
      @computing     = false
6✔
57
    end
58

59
    def wait(timeout)
1✔
60
      execute_task_once
10✔
61
      super timeout
10✔
62
    end
63

64
    # reconfigures the block returning the value if still #incomplete?
65
    # @yield the delayed operation to perform
66
    # @return [true, false] if success
67
    def reconfigure(&block)
1✔
UNCOV
68
      mutex.lock
×
UNCOV
69
      raise ArgumentError.new('no block given') unless block_given?
×
UNCOV
70
      unless @computing
×
UNCOV
71
        @task = block
×
UNCOV
72
        true
×
73
      else
UNCOV
74
        false
×
75
      end
76
    ensure
UNCOV
77
      mutex.unlock
×
78
    end
79

80
    private
1✔
81

82
    def execute_task_once
1✔
83
      mutex.lock
10✔
84
      execute = @computing = true unless @computing
10✔
85
      task    = @task
10✔
86
      mutex.unlock
10✔
87

88
      if execute
10✔
89
        @task_executor.post do
4✔
90
          begin
91
            result  = task.call
4✔
92
            success = true
4✔
93
          rescue => ex
UNCOV
94
            reason = ex
×
95
          end
96
          mutex.lock
4✔
97
          set_state success, result, reason
4✔
98
          event.set
4✔
99
          mutex.unlock
4✔
100
        end
101
      end
102
    end
103
  end
104
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc