forked from crystal-lang/crystal
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Skeleton for ExecutionContext types as per RFC #2
- Add the `ExecutionContext` module; - Add the `ExecutionContext::Scheduler` module; - Add the `execution_context` compile-time flag. When the `execution_context` flag is set: - Don't load `Crystal::Scheduler`; - Plug `ExecutionContext` instead of `Crystal::Scheduler`.
- Loading branch information
1 parent
712a1f7
commit 60b2050
Showing
12 changed files
with
365 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
require "../crystal/event_loop" | ||
require "../crystal/system/thread" | ||
require "../crystal/system/thread_linked_list" | ||
require "../fiber" | ||
require "../fiber/stack_pool" | ||
require "./scheduler" | ||
|
||
{% raise "ERROR: execution contexts require the `preview_mt` compilation flag" unless flag?(:preview_mt) %} | ||
|
||
module ExecutionContext | ||
@@default : ExecutionContext? | ||
|
||
@[AlwaysInline] | ||
def self.default : ExecutionContext | ||
@@default.not_nil!("expected default execution context to have been setup") | ||
end | ||
|
||
# :nodoc: | ||
def self.init_default_context : Nil | ||
raise NotImplementedError.new("No execution context implementations (yet)") | ||
end | ||
|
||
# Returns the default number of workers to start in the execution context. | ||
def self.default_workers_count : Int32 | ||
ENV["CRYSTAL_WORKERS"]?.try(&.to_i?) || Math.min(System.cpu_count.to_i, 32) | ||
end | ||
|
||
# :nodoc: | ||
protected class_getter(execution_contexts) { Thread::LinkedList(ExecutionContext).new } | ||
|
||
# :nodoc: | ||
property next : ExecutionContext? | ||
|
||
# :nodoc: | ||
property previous : ExecutionContext? | ||
|
||
# :nodoc: | ||
def self.unsafe_each(&) : Nil | ||
@@execution_contexts.try(&.unsafe_each { |execution_context| yield execution_context }) | ||
end | ||
|
||
def self.each(&) : Nil | ||
execution_contexts.each { |execution_context| yield execution_context } | ||
end | ||
|
||
@[AlwaysInline] | ||
def self.current : ExecutionContext | ||
Thread.current.execution_context | ||
end | ||
|
||
# Tells the current scheduler to suspend the current fiber and resume the | ||
# next runnable fiber. The current fiber will never be resumed; you're | ||
# responsible to reenqueue it. | ||
# | ||
# This method is safe as it only operates on the current `ExecutionContext` | ||
# and `Scheduler`. | ||
@[AlwaysInline] | ||
def self.reschedule : Nil | ||
Scheduler.current.reschedule | ||
end | ||
|
||
# Tells the current scheduler to suspend the current fiber and to resume | ||
# *fiber* instead. The current fiber will never be resumed; you're responsible | ||
# to reenqueue it. | ||
# | ||
# Raises `RuntimeError` if the fiber doesn't belong to the current execution | ||
# context. | ||
# | ||
# This method is safe as it only operates on the current `ExecutionContext` | ||
# and `Scheduler`. | ||
def self.resume(fiber : Fiber) : Nil | ||
if fiber.execution_context == current | ||
Scheduler.current.resume(fiber) | ||
else | ||
raise RuntimeError.new("Can't resume fiber from #{fiber.execution_context} into #{current}") | ||
end | ||
end | ||
|
||
# Creates a new fiber then calls `#enqueue` to add it to the execution | ||
# context. | ||
# | ||
# May be called from any `ExecutionContext` (i.e. must be thread-safe). | ||
def spawn(*, name : String? = nil, &block : ->) : Fiber | ||
Fiber.new(name, self, &block).tap { |fiber| enqueue(fiber) } | ||
end | ||
|
||
# Legacy support for the `same_thread` argument. Each execution context may | ||
# decide to support it or not (e.g. a single threaded context can accept it). | ||
abstract def spawn(*, name : String? = nil, same_thread : Bool, &block : ->) : Fiber | ||
|
||
abstract def stack_pool : Fiber::StackPool | ||
abstract def stack_pool? : Fiber::StackPool? | ||
|
||
abstract def event_loop : Crystal::EventLoop | ||
|
||
# Enqueues a fiber to be resumed inside the execution context. | ||
# | ||
# May be called from any ExecutionContext (i.e. must be thread-safe). | ||
abstract def enqueue(fiber : Fiber) : Nil | ||
end |
Oops, something went wrong.