1. Fibers with Objects

We spawn to other objects for concurrent processing. This next code sample shows how to send both synchronous and asynchronous messages from the main thread to objects which will be evaluated within a Fiber.

Here is our base User object:

code/crystal/src/concurrency/user.cr
class User
  getter channel : Channel(String)
  private getter name : String, email : String

  def initialize(@name, @email)
    @channel = Channel(String).new
  end

  def to_s
    "#{name} <#{email}>"
  end

  def post_message(message : String)
    puts "To: #{to_s} -- #{message}"
  end
end

Code to send user messages:

code/crystal/src/concurrency/user_messaging.cr
require "./user"     # autoloads the above user.cr file

# USAGE
module UserMessaging
  # create users
  user_1 = User.new(name: "first",  email: "[email protected]")
  user_2 = User.new(name: "second", email: "[email protected]")

  # send messages
  puts "REAL-TIME - START"

  # send an async message
  spawn user_1.post_message("ASYNC sent 1st")

  # send a synchronous message
  user_1.post_message("REAL-TIME sent 2nd")
  user_1.post_message("REAL-TIME sent 3rd")

  puts "SWITCH to user_2"
  spawn user_2.post_message("ASYNC sent 4th")
  user_2.post_message("REAL-TIME sent 5th")

  puts "SWITCH back to user_1"
  user_1.post_message("REAL-TIME sent 6th")
  spawn user_1.post_message("ASYNC sent 7th")
  puts "REAL-TIME - DONE"

  # Allow Fibers (async messages) to execute
  Fiber.yield
end

Run with:

$ crystal src/concurrency/spawn_call.cr

Just a reminder, notice how all async messages happen after Fiber.yield