| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| module Qpid::Proton |
| |
| # @private |
| module TimeCompare |
| # t1 <= t2, where nil is treated as "distant future" |
| def before_eq(t1, t2) (t1 && t2) ? (t1 <= t2) : t1; end |
| |
| # min(t1, t2) where nil is treated as "distant future" |
| def earliest(t1, t2) before_eq(t1, t2) ? t1 : t2; end |
| end |
| |
| # @private |
| # A time-sorted list of objects. Thread unsafe. |
| class Schedule |
| include TimeCompare |
| Entry = Struct.new(:time, :item) |
| |
| def initialize() @entries = []; end |
| |
| def empty?() @entries.empty?; end |
| |
| def next_tick() |
| @entries.first.time unless @entries.empty? |
| end |
| |
| # @param at [Time] Insert item at time +at+ |
| # @param at [Numeric] Insert item at +Time.now \+ at+ |
| # @param at [0] Insert item at Time.at(0) |
| def insert(at, item) |
| time = case at |
| when 0 then Time.at(0) # Avoid call to Time.now for immediate tasks |
| when Numeric then Time.now + at |
| else at |
| end |
| index = time && ((0...@entries.size).bsearch { |i| @entries[i].time > time }) |
| @entries.insert(index || -1, Entry.new(time, item)) |
| end |
| |
| # Return next item due at or before time, else nil |
| def pop(time) |
| @entries.shift.item if !@entries.empty? && before_eq(@entries.first.time, time) |
| end |
| |
| def clear() @entries.clear; end |
| end |
| end |