Sha256: 5716fd3f15b0afa1da817253ef066dce7f87ba7c829f5081de0ffdbfeab3a0bb

Contents?: true

Size: 1.43 KB

Versions: 1

Compression:

Stored size: 1.43 KB

Contents

require 'thread'
require 'logger'
require 'set'

Thread.abort_on_exception = true

module Xi
  class Clock
    DEFAULT_CPS  = 1.0
    INTERVAL_SEC = 10 / 1000.0

    def initialize(cps: DEFAULT_CPS)
      @mutex = Mutex.new
      @cps = cps
      @playing = true
      @streams = [].to_set
      @play_thread = Thread.new { thread_routine }
    end

    def subscribe(stream)
      @mutex.synchronize { @streams << stream }
    end

    def unsubscribe(stream)
      @mutex.synchronize { @streams.delete(stream) }
    end

    def cps
      @mutex.synchronize { @cps }
    end

    def cps=(new_cps)
      @mutex.synchronize { @cps = new_cps }
    end

    def playing?
      @mutex.synchronize { @playing }
    end

    def stopped?
      !playing?
    end

    def play
      @mutex.synchronize { @playing = true }
      self
    end
    alias_method :start, :play

    def stop
      @mutex.synchronize { @playing = false }
      self
    end
    alias_method :pause, :play

    def inspect
      "#<#{self.class.name}:#{"0x%014x" % object_id} cps=#{cps.inspect} #{playing? ? :playing : :stopped}>"
    end

    private

    def thread_routine
      loop do
        do_tick
        sleep INTERVAL_SEC
      end
    end

    def do_tick
      cycles = Time.now.to_f * cps
      return unless playing?
      @streams.each { |s| s.notify(cycles) }
    rescue => err
      logger.error(err)
    end

    def logger
      @logger ||= Logger.new(STDOUT)
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
xi-lang-0.1.0 lib/xi/clock.rb