class Fiber
Overview
A Fiber
is a light-weight execution unit managed by the Crystal runtime.
It is conceptually similar to an operating system thread but with less overhead and completely internal to the Crystal process. The runtime includes a scheduler which schedules execution of fibers.
A Fiber
has a stack size of 8 MiB
which is usually also assigned
to an operating system thread. But only 4KiB
are actually allocated at first
so the memory footprint is very small.
Communication between fibers is usually passed through Channel
.
Cooperative
Fibers are cooperative. That means execution can only be drawn from a fiber when it offers it. It can't be interrupted in its execution at random. In order to make concurrency work, fibers must make sure to occasionally provide hooks for the scheduler to swap in other fibers. IO operations like reading from a file descriptor are natural implementations for this and the developer does not need to take further action on that. When IO access can't be served immediately by a buffer, the fiber will automatically wait and yield execution. When IO is ready it's going to be resumed through the event loop.
When a computation-intensive task has none or only rare IO operations, a fiber
should explicitly offer to yield execution from time to time using
Fiber.yield
to break up tight loops. The frequency of this call depends on
the application and concurrency model.
Event loop
The event loop is responsible for keeping track of sleeping fibers waiting for notifications that IO is ready or a timeout reached. When a fiber can be woken, the event loop enqueues it in the scheduler
Defined in:
fiber.crfiber/context.cr
fiber/context/x86_64-sysv.cr
fiber/stack_pool.cr
log/metadata.cr
Constructors
-
.new(name : String? = nil, &proc : -> )
Creates a new
Fiber
instance.
Class Method Summary
- .cancel_timeout
-
.current
Returns the current fiber.
-
.timeout(timeout : Time::Span?, select_action : Channel::TimeoutAction? = nil) : Nil
The current fiber will resume after a period of time and have the property
timed_out
set to true. -
.yield
Yields to the scheduler and allows it to swap execution to other waiting fibers.
Instance Method Summary
-
#dead?
The fiber's proc has terminated, and the fiber is now considered dead.
-
#enqueue
Adds this fiber to the scheduler's runnables queue for the current thread.
-
#inspect(io : IO) : Nil
Appends a String representation of this object which includes its class name, its object address and the values of all instance variables.
-
#name : String?
The name of the fiber, used as internal reference.
-
#name=(name : String?)
The name of the fiber, used as internal reference.
-
#resumable?
The fiber's proc is currently not running and fully saved its context.
-
#resume : Nil
Immediately resumes execution of this fiber.
-
#running?
The fiber's proc is currently running or didn't fully save its context.
-
#to_s(io : IO) : Nil
Appends a short String representation of this object which includes its class name and its object address.
Instance methods inherited from class Reference
==(other : self)==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference)
same?(other : Nil) same?, to_s(io : IO) : Nil to_s
Constructor methods inherited from class Reference
new
new
Instance methods inherited from class Object
! : Bool
!,
!=(other)
!=,
!~(other)
!~,
==(other)
==,
===(other : JSON::Any)===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(*values : Object) : Bool
in?(collection) : Bool in?, inspect : String
inspect(io : IO) : Nil inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO)
to_json to_json, to_pretty_json(io : IO, indent : String = " ")
to_pretty_json(indent : String = " ") to_pretty_json, to_s : String
to_s(io : IO) : Nil to_s, to_yaml(io : IO)
to_yaml to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as
Class methods inherited from class Object
from_json(string_or_io, root : String)from_json(string_or_io) from_json, from_yaml(string_or_io : String | IO) from_yaml
Constructor Detail
Creates a new Fiber
instance.
When the fiber is executed, it runs proc in its context.
name is an optional and used only as an internal reference.
Class Method Detail
The current fiber will resume after a period of time
and have the property timed_out
set to true.
The timeout can be cancelled with .cancel_timeout
Yields to the scheduler and allows it to swap execution to other waiting fibers.
This is equivalent to sleep 0.seconds
. It gives the scheduler an option
to interrupt the current fiber's execution. If no other fibers are ready to
be resumed, it immediately resumes the current fiber.
This method is particularly useful to break up tight loops which are only computation intensive and don't offer natural opportunities for swapping fibers as with IO operations.
counter = 0
spawn name: "status" do
loop do
puts "Status: #{counter}"
sleep(2.seconds)
end
end
while counter < Int32::MAX
counter += 1
if counter % 1_000_000 == 0
# Without this, there would never be an opportunity to resume the status fiber
Fiber.yield
end
end
Instance Method Detail
The fiber's proc has terminated, and the fiber is now considered dead. The fiber is impossible to resume, ever.
Adds this fiber to the scheduler's runnables queue for the current thread.
This signals to the scheduler that the fiber is eligible for being resumed the next time it has the opportunity to reschedule to an other fiber. There are no guarantees when that will happen.
Appends a String representation of this object which includes its class name, its object address and the values of all instance variables.
class Person
def initialize(@name : String, @age : Int32)
end
end
Person.new("John", 32).inspect # => #<Person:0x10fd31f20 @name="John", @age=32>
The fiber's proc is currently not running and fully saved its context. The fiber can be resumed safely.
Immediately resumes execution of this fiber.
There are no provisions for resuming the current fiber (where this
method is called). Unless it is explicitly added for rescheduling (for
example using #enqueue
) the current fiber won't ever reach any instructions
after the call to this method.
fiber = Fiber.new do
puts "in fiber"
end
fiber.resume
puts "never reached"
The fiber's proc is currently running or didn't fully save its context. The fiber can't be resumed.
Appends a short String representation of this object which includes its class name and its object address.
class Person
def initialize(@name : String, @age : Int32)
end
end
Person.new("John", 32).to_s # => #<Person:0x10a199f20>