def post(delay, *args, &task)
      raise ArgumentError, 'no block given' unless block_given?
      delay = TimerSet.calculate_delay!(delay)

      mutex.synchronize do
        return false unless running?

        if (delay) <= 0.01
          @task_executor.post(*args, &task)
        else
          @queue.push(Task.new(Garcon.monotonic_time + delay, args, task))
          @timer_executor.post(&method(:process_tasks))
        end
      end

      @condition.signal
      true
    end
def post(delay, *args, &task)
      raise ArgumentError, 'no block given' unless block_given?
      delay = TimerSet.calculate_delay!(delay)

      mutex.synchronize do
        return false unless running?

        if (delay) <= 0.01
          @task_executor.post(*args, &task)
        else
          @queue.push(Task.new(Garcon.monotonic_time + delay, args, task))
          @timer_executor.post(&method(:process_tasks))
        end
      end

      @condition.signal
      true
    end
Create a new set of timed tasks.

 @!macro [attach] executor_options

 @param [Hash] opts
   The options used to specify the executor on which to perform actions.

 @option opts [Executor] :executor
   When set use the given `Executor` instance. Three special values are
   also supported: `:task` returns the global task pool, `:operation`
   returns the global operation pool, and `:immediate` returns a new
  `ImmediateExecutor` object.

 Post a task to be execute run after a given delay (in seconds). If the
 delay is less than 1/100th of a second the task will be immediately post
 to the executor.

 @param [Float] delay
   The number of seconds to wait for before executing the task.

 @yield the task to be performed.

 @raise [ArgumentError] f the intended execution time is not in the future.

 @raise [ArgumentError] if no block is given.

 @return [Boolean]
   True if the message is post, false after shutdown.