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