Module: Inform::Events

Included in:
Object
Defined in:
lib/story_teller/events.rb,
lib/story_teller/events.rb

Overview

The Inform::Events module

Constant Summary collapse

REGISTRY =
Struct.new(:memo).new({})
THREADS_PER_PROCESSOR =
10
DEFAULT_ADD_EVENT_PARAMS =
{ delay: 0 }.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.active_objectsObject



548
549
550
# File 'lib/story_teller/events.rb', line 548

def active_objects
  @active_objects ||= defined?(Java) ? java.util.concurrent.ConcurrentLinkedQueue.new : []
end

.available_processorsObject

rubocop: disable Metrics/AbcSize rubocop: disable Metrics/CyclomaticComplexity rubocop: disable Metrics/MethodLength



577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
# File 'lib/story_teller/events.rb', line 577

def available_processors
  return java.lang.Runtime.runtime.available_processors if defined?(Java)
  case RbConfig::CONFIG['host_os']
  when /darwin9/
    if File.exist?(`which hwprefs`)
      `hwprefs cpu_count`.strip.to_i
    else
      # Better than nothing
      require 'etc'
      Etc.nprocessors
    end
  when /darwin/
    if File.exist?(`which hwprefs`)
      `hwprefs thread_count`.strip.to_i
    else
      `sysctl -n hw.ncpu`.strip.to_i
    end
  when /linux/
     `grep -c processor /proc/cpuinfo`.strip.to_i
  when /freebsd/
    `sysctl -n hw.ncpu`.strip.to_i
  when /mswin|mingw/
    require 'win32ole'
    cpu = WIN32OLE.connect("winmgmts://").ExecQuery("select NumberOfCores from Win32_Processor")
    cpu.to_enum.first.NumberOfCores
  else
    # Better than nothing
    require 'etc'
    Etc.nprocessors
  end
end

.each(event_class = Inform::Event, &block) ⇒ Object



569
570
571
# File 'lib/story_teller/events.rb', line 569

def each(event_class = Inform::Event, &block)
  events[event_class].each { |event| block.call(event) } if block_given?
end

.init_java_poolObject



675
676
677
# File 'lib/story_teller/events.rb', line 675

def init_java_pool
  com.google.common.util.concurrent.MoreExecutors.listeningDecorator(pooled_executor)
end

.init_java_pooled_executorObject



640
641
642
# File 'lib/story_teller/events.rb', line 640

def init_java_pooled_executor
  Executors.newFixedThreadPool(available_processors * THREADS_PER_PROCESSOR)
end

.init_java_scheduled_executorObject



626
627
628
629
630
631
# File 'lib/story_teller/events.rb', line 626

def init_java_scheduled_executor
  executor = java.util.concurrent.Executors.newScheduledThreadPool(
    available_processors * THREADS_PER_PROCESSOR)
  executor.setRemoveOnCancelPolicy(true)
  executor
end

.init_java_schedulerObject



658
659
660
# File 'lib/story_teller/events.rb', line 658

def init_java_scheduler
  com.google.common.util.concurrent.MoreExecutors.listeningDecorator(ScheduledExecutor)
end

.init_poolObject



668
669
670
671
672
# File 'lib/story_teller/events.rb', line 668

def init_pool
  # TODO: Implement
  # require 'ruby-concurrency'
  # Concurrent::ThreadPoolExecutor.new(available_processors * THREADS_PER_PROCESSOR)
end

.init_scheduled_executorObject



619
620
621
622
623
# File 'lib/story_teller/events.rb', line 619

def init_scheduled_executor
  # TODO: Implement
  # require 'ruby-concurrency'
  # Concurrent::ScheduledThreadPoolExecutor.new(available_processors * THREADS_PER_PROCESSOR)
end

.init_schedulerObject



651
652
653
654
655
# File 'lib/story_teller/events.rb', line 651

def init_scheduler
  # TODO: Implement
  # require 'ruby-concurrency'
  # Concurrent::ThreadPoolExecutor.new(available_processors * THREADS_PER_PROCESSOR)
end

.object_eventsObject



558
559
560
561
562
# File 'lib/story_teller/events.rb', line 558

def object_events
  Inform::Events.possibilities[identity] ||=
    defined?(Java) ? java.util.concurrent.ConcurrentHashMap.new : {}
  Inform::Events.possibilities[identity]
end

.poolObject



663
664
665
# File 'lib/story_teller/events.rb', line 663

def pool
  REGISTRY.memo[:pool] ||= defined?(Java) ? init_java_pool : init_pool
end

.pooled_executorObject



634
635
636
637
# File 'lib/story_teller/events.rb', line 634

def pooled_executor
  REGISTRY.memo[:pooled_executor] ||=
    defined?(Java) ? init_java_pooled_executor : init_pooled_executor
end

.possibilitiesObject



553
554
555
# File 'lib/story_teller/events.rb', line 553

def possibilities
  @possibilities ||= defined?(Java) ? java.util.concurrent.ConcurrentHashMap.new : {}
end

.scheduled_executorObject



613
614
615
616
# File 'lib/story_teller/events.rb', line 613

def scheduled_executor
  REGISTRY.memo[:scheduled_executor] ||=
    defined?(Java) ? init_java_scheduled_executor : init_scheduled_executor
end

.schedulerObject



645
646
647
648
# File 'lib/story_teller/events.rb', line 645

def scheduler
  REGISTRY.memo[:scheduler] ||=
    defined?(Java) ? init_java_scheduler : init_scheduler
end

Instance Method Details

#active?Boolean Also known as: already_active?

Returns:

  • (Boolean)


745
746
747
# File 'lib/story_teller/events.rb', line 745

def active?
  !events.empty?
end

#add_event(params = {}, event_params = { cause: self }, &block) ⇒ Object Also known as: eventually, later, queue, enqueue



697
698
699
700
701
702
703
704
705
706
# File 'lib/story_teller/events.rb', line 697

def add_event(params = {}, event_params = { cause: self }, &block)
  if (e = Thread.current[:event]).nil?
    params = { command: params } unless params.respond_to?(:merge)
    event_params[:name] = params.delete(:command) if params.include?(:command)
    Inform::Event.new(event_params.merge(params), &block)
  else
    event_params[:name] = params.delete(:command) if params.include?(:command)
    e.chain(event_params.merge(DEFAULT_ADD_EVENT_PARAMS.merge(event_params)), &block)
  end
end

#contextualizeObject



741
742
743
# File 'lib/story_teller/events.rb', line 741

def contextualize
  Thread.current[:event]&.contextualize(self)
end

#delay(delay, &block) ⇒ Object Also known as: after_delay, delayed_event



727
728
729
# File 'lib/story_teller/events.rb', line 727

def delay(delay, &block)
  Inform::Event.new({ cause: self, delay: delay }, &block)
end

#elementally(ctx, &block) ⇒ Object



737
738
739
# File 'lib/story_teller/events.rb', line 737

def elementally(ctx, &block)
  Inform::Event.new({ cause: self, context: ctx, type: :elemental, when: :immediately }, &block)
end

#event(params = {}, &block) ⇒ Object Also known as: new_event, now, react, respond

TODO: Figure out a way to determine if an existing event is already finished. That is, find a way to implicitly determine if any existing event is in the react_after phase instead of the react_before phase.



716
717
718
719
720
721
# File 'lib/story_teller/events.rb', line 716

def event(params = {}, &block)
  params = { command: params } unless params.respond_to?(:merge)
  event_params = { cause: self }
  event_params[:name] = params.delete(:command) if params.include?(:command)
  Inform::Event.new(event_params.merge(params), &block)
end

#events(klass = Inform::Event) ⇒ Object



565
566
567
# File 'lib/story_teller/events.rb', line 565

def events(klass = Inform::Event)
  object_events[klass] ||= defined?(ConcurrentLinkedQueue) ? ConcurrentLinkedQueue.new : []
end

#immediately(ctx, &block) ⇒ Object



733
734
735
# File 'lib/story_teller/events.rb', line 733

def immediately(ctx, &block)
  Inform::Event.new({ cause: self, context: ctx, when: :immediately }, &block)
end

#interrupt(event_class = nil) ⇒ Object



750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
# File 'lib/story_teller/events.rb', line 750

def interrupt(event_class = nil)
  interruption = Thread.current[:event]
  Inform::Events.each(event_class) do |event|
    # Do not artificially terminate the source of an interruption.
    next if event == interruption

    # Parameterizing Future#cancel with false is supposed to
    # abort the future without interrupting the executing thread.
    # Not interrupting the event future's thread may have the
    # consequence of a variety of data consistency issues.
    # event.future.cancel false if event != interruption

    # TODO: Test
    event.future.cancel false
  end
  false
end

#register_callback(ctx, *args, &callback) ⇒ Object



690
691
692
693
694
695
# File 'lib/story_teller/events.rb', line 690

def register_callback(ctx, *args, &callback)
  e = Thread.current[:event]
  return true if e.nil?
  e.chain({ context: ctx, args: args }, &callback)
  true
end