Class: Datadog::Core::Remote::Component::Barrier Private

Inherits:
Object
  • Object
show all
Defined in:
lib/datadog/core/remote/component.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Barrier provides a mechanism to fence execution until a condition happens

Instance Method Summary collapse

Constructor Details

#initialize(timeout = nil) ⇒ Barrier

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Barrier.



114
115
116
117
118
119
120
121
# File 'lib/datadog/core/remote/component.rb', line 114

def initialize(timeout = nil)
  @once = false
  @waited = false
  @timeout = timeout

  @mutex = Mutex.new
  @condition = ConditionVariable.new
end

Instance Method Details

#lift ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Release all current waiters



175
176
177
178
179
180
181
# File 'lib/datadog/core/remote/component.rb', line 175

def lift
  @mutex.synchronize do
    @once ||= true

    @condition.broadcast
  end
end

#wait_once(timeout = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Wait for first lift to happen, otherwise don't wait

Returns:

  • :lift if the barrier was lifted (worker completed a cycle)
  • :timeout if the wait timed out before the barrier was lifted
  • :pass if wait_once was already called previously

Uses a separate @waited flag to distinguish "already waited" (:pass) from "worker lifted before we could wait" (:lift). Without this, a race between Worker#start and wait_once can cause the first call to return :pass if the worker completes before wait_once runs.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/datadog/core/remote/component.rb', line 134

def wait_once(timeout = nil)
  # TTAS (Test and Test-And-Set) optimisation for subsequent calls.
  # @waited is only set inside the mutex and only transitions false -> true,
  # so an unsynchronized read is safe: a stale `false` just falls through
  # to the synchronized path which re-checks.
  return :pass if @waited

  @mutex.synchronize do
    return :pass if @waited

    if @once
      # Worker lifted the barrier before we could wait.
      # This is still the first call, so return :lift not :pass.
      lifted = true
    else
      timeout ||= @timeout

      # - starting with Ruby 3.2, ConditionVariable#wait returns nil on
      #   timeout and an integer otherwise
      # - before Ruby 3.2, ConditionVariable returns itself
      # so we have to rely on @once having been set
      if RubyVersion.is?(">= 3.2")
        lifted = @condition.wait(@mutex, timeout)
      else
        @condition.wait(@mutex, timeout)
        lifted = @once
      end
    end

    @waited = true

    if lifted
      :lift
    else
      @once = true
      :timeout
    end
  end
end