|
| 1 | +require 'concurrent/configuration' |
| 2 | +require 'concurrent/executor/one_by_one' |
| 3 | +require 'concurrent/ivar' |
| 4 | +require 'concurrent/logging' |
| 5 | + |
| 6 | +module Concurrent |
| 7 | + |
| 8 | + # {include:file:lib/concurrent/actress/doc.md} |
| 9 | + module Actress |
| 10 | + |
| 11 | + require 'concurrent/actress/type_check' |
| 12 | + require 'concurrent/actress/errors' |
| 13 | + require 'concurrent/actress/core_delegations' |
| 14 | + require 'concurrent/actress/envelope' |
| 15 | + require 'concurrent/actress/reference' |
| 16 | + require 'concurrent/actress/core' |
| 17 | + require 'concurrent/actress/context' |
| 18 | + |
| 19 | + require 'concurrent/actress/ad_hoc' |
| 20 | + |
| 21 | + # @return [Reference, nil] current executing actor if any |
| 22 | + def self.current |
| 23 | + Thread.current[:__current_actress__] |
| 24 | + end |
| 25 | + |
| 26 | + # implements ROOT |
| 27 | + class Root |
| 28 | + include Context |
| 29 | + # to allow spawning of new actors, spawn needs to be called inside the parent Actor |
| 30 | + def on_message(message) |
| 31 | + if message.is_a?(Array) && message.first == :spawn |
| 32 | + spawn message[1], &message[2] |
| 33 | + else |
| 34 | + # ignore |
| 35 | + end |
| 36 | + end |
| 37 | + end |
| 38 | + |
| 39 | + # A root actor, a default parent of all actors spawned outside an actor |
| 40 | + ROOT = Core.new(parent: nil, name: '/', class: Root).reference |
| 41 | + |
| 42 | + # @param block for actress_class instantiation |
| 43 | + # @param args see {.spawn_optionify} |
| 44 | + def self.spawn(*args, &block) |
| 45 | + if Actress.current |
| 46 | + Core.new(spawn_optionify(*args).merge(parent: Actress.current), &block).reference |
| 47 | + else |
| 48 | + ROOT.ask([:spawn, spawn_optionify(*args), block]).value |
| 49 | + end |
| 50 | + end |
| 51 | + |
| 52 | + # as {.spawn} but it'll raise when Actor not initialized properly |
| 53 | + def self.spawn!(*args, &block) |
| 54 | + spawn(spawn_optionify(*args).merge(initialized: ivar = IVar.new), &block).tap { ivar.no_error! } |
| 55 | + end |
| 56 | + |
| 57 | + # @overload spawn_optionify(actress_class, name, *args) |
| 58 | + # @param [Context] actress_class to be spawned |
| 59 | + # @param [String, Symbol] name of the instance, it's used to generate the path of the actor |
| 60 | + # @param args for actress_class instantiation |
| 61 | + # @overload spawn_optionify(opts) |
| 62 | + # see {Core#initialize} opts |
| 63 | + def self.spawn_optionify(*args) |
| 64 | + if args.size == 1 && args.first.is_a?(Hash) |
| 65 | + args.first |
| 66 | + else |
| 67 | + { class: args[0], |
| 68 | + name: args[1], |
| 69 | + args: args[2..-1] } |
| 70 | + end |
| 71 | + end |
| 72 | + end |
| 73 | +end |
0 commit comments