lib/litescheduler.rb in litescheduler-0.1.0 vs lib/litescheduler.rb in litescheduler-0.2.0

- old
+ new

@@ -1,8 +1,102 @@ # frozen_string_literal: true require_relative "litescheduler/version" +require "singleton" -module Litescheduler - class Error < StandardError; end - # Your code goes here... +class Litescheduler + include Singleton + + attr_reader :environment, :scheduler, :max_contexts, :storage, :context, :mutex + + def initialize + @environment = detect_environment + @scheduler = detect_scheduler + @max_contexts = detect_max_contexts + @storage = detect_storage + @context = detect_context + # a single mutex per process (is that ok?) + @mutex = Thread::Mutex.new + end + + # spawn a new execution context + def spawn(&block) + case @scheduler + when :fiber then Fiber.schedule(&block) + when :polyphony then spin(&block) + when :iodine then Thread.new(&block) + when :threaded then Thread.new(&block) + else + raise StandardError.new("Unknown scheduler: `#{@scheduler}`") + end + end + + # switch the execution context to allow others to run + def switch + if @scheduler == :fiber + Fiber.scheduler.yield + true + elsif @scheduler == :polyphony + Fiber.current.schedule + Thread.current.switch_fiber + true + else + # Thread.pass + false + end + end + + # bold assumption, we will only synchronize threaded code + # this is a no-op for fibers + def synchronize(&block) + # do nothing, just run the block as is + return yield if @scheduler == :fiber + return yield if @scheduler == :polyphony + + @mutex.synchronize(&block) + end + + private + + # Detect the Rack or Rails environment. + def detect_environment + return Rails.env if defined? Rails + return ENV["RACK_ENV"] if ENV.key?("RACK_ENV") + return ENV["APP_ENV"] if ENV.key?("APP_ENV") + + "development" + end + + # identify which scheduler we are running in + # we currently support :fiber, :polyphony, :iodine & :threaded + # in the future we might want to expand to other schedulers + def detect_scheduler + return :fiber if Fiber.scheduler + return :polyphony if defined? Polyphony + return :iodine if defined? Iodine + + :threaded + end + + def detect_max_contexts + return 50 if scheduler == :fiber + return 50 if scheduler == :polyphony + + 5 + end + + def detect_storage + if scheduler == :fiber || scheduler == :poylphony + Fiber.current.storage + else + Thread.current + end + end + + def detect_context + if scheduler == :fiber || scheduler == :poylphony + Fiber.current + else + Thread.current + end + end end