Class: Bogo::Stack

Inherits:
Object
  • Object
show all
Includes:
MonitorMixin
Defined in:
lib/bogo/stack.rb

Overview

Simple call stack implementation

Defined Under Namespace

Classes: Action, Context, Entry, Error, Hooks

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeStack

Create a new stack



512
513
514
515
516
517
518
519
520
# File 'lib/bogo/stack.rb', line 512

def initialize
  super
  @actions = [].freeze
  @prepared = false
  @context = Context.new(stack: self)
  @hooks = Hooks.new(stack: self)
  @started = false
  @parallel = false
end

Instance Attribute Details

#actionsArray<Action> (readonly)

Returns list of actions in the stack.

Returns:



501
502
503
# File 'lib/bogo/stack.rb', line 501

def actions
  @actions
end

#contextContext (readonly)

Returns context for the stack.

Returns:

  • (Context)

    context for the stack



503
504
505
# File 'lib/bogo/stack.rb', line 503

def context
  @context
end

#hooksHooks (readonly)

Returns hooks for stack.

Returns:

  • (Hooks)

    hooks for stack



505
506
507
# File 'lib/bogo/stack.rb', line 505

def hooks
  @hooks
end

#parallelBoolean (readonly)

Returns actions run in parallel.

Returns:

  • (Boolean)

    actions run in parallel



507
508
509
# File 'lib/bogo/stack.rb', line 507

def parallel
  @parallel
end

Instance Method Details

#call(context: nil) ⇒ Object

Execute the next action in the stack

Parameters:

  • ctx (Context)

    start with given context



685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
# File 'lib/bogo/stack.rb', line 685

def call(context: nil)
  synchronize do
    be_prepared!
    if context
      be_unstarted!
      @context = context.for(self)
    end
    if @parallel
      acts = @actions.dup
      @actions = []
      acts.each do |action|
        Thread.new { action.call(context: @context) }
      end
    else
      action = pop
      action.call(context: context) if action
    end
  end
end

#insert(at:, callable:, adjust: 0) ⇒ self Also known as: insert_at

Insert item into stack at given index

Parameters:

  • at (Integer)

    index to add item

  • callable (Class, Proc)

    object that responds to #call or class with #call instance method

  • adjust (Integer) (defaults to: 0)

    adjust index point

Returns:

  • (self)


588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
# File 'lib/bogo/stack.rb', line 588

def insert(at:, callable:, adjust: 0)
  synchronize do
    be_unprepared!
    idx = yield stack if idx.nil? && block_given?
    if !idx.is_a?(Integer) && !idx.is_a?(Action)
      raise ArgumentError,
        "Expecting `Integer` or `#{Action.name}` but received `#{idx.class.name}`"
    end
    callable = Action.new(stack: self, callable: callable) if
      !callable.is_a?(Action)
    @actions = actions.dup
    @actions.insert(idx + adjust, callable)
    @actions.freeze
  end
  self
end

#insert_after(idx: nil, callable: nil, &block) ⇒ self

Insert item after given index

Parameters:

  • idx (Integer) (defaults to: nil)

    index to add item after

  • callable (Class, Proc) (defaults to: nil)

    object that responds to #call or class with #call instance method

Returns:

  • (self)


624
625
626
# File 'lib/bogo/stack.rb', line 624

def insert_after(idx: nil, callable: nil, &block)
  insert(idx: idx, callable: callable, adjust: -1, &block)
end

#insert_before(idx: nil, callable: nil, &block) ⇒ self

Insert item before given index

Parameters:

  • idx (Integer) (defaults to: nil)

    index to add item before

  • callable (Class, Proc) (defaults to: nil)

    object that responds to #call or class with #call instance method

Returns:

  • (self)


613
614
615
# File 'lib/bogo/stack.rb', line 613

def insert_before(idx: nil, callable: nil, &block)
  insert(idx: idx, callable: callable, adjust: 1, &block)
end

#parallelize!self

Enable parallel execution of stack actions

Returns:

  • (self)


525
526
527
528
529
530
# File 'lib/bogo/stack.rb', line 525

def parallelize!
  synchronize do
    be_unprepared!
    @parallel = true
  end
end

#popAction?

Remove last action from the stack

Returns:



631
632
633
634
635
636
637
638
# File 'lib/bogo/stack.rb', line 631

def pop
  synchronize do
    @actions = actions.dup
    action = actions.pop
    @actions.freeze
    action
  end
end

#prepareself

Prepare the stack to be called

Returns:

  • (self)


671
672
673
674
675
676
677
678
679
680
# File 'lib/bogo/stack.rb', line 671

def prepare
  synchronize do
    be_unprepared!
    @actions = hooks.apply!
    @actions.freeze
    actions.each(&:prepare)
    @prepared = true
  end
  self
end

#prepared?TrueClass, FalseClass

Returns stack is prepared for execution.

Returns:

  • (TrueClass, FalseClass)

    stack is prepared for execution



664
665
666
# File 'lib/bogo/stack.rb', line 664

def prepared?
  @prepared
end

#push(callable = nil, &block) ⇒ Action

Push a new callable action onto the end of the stack

Parameters:

  • callable (Class, Proc) (defaults to: nil)

    object that responds to #call or class with #call instance method

Returns:

  • (Action)

    generated Action instance



537
538
539
540
541
542
543
544
# File 'lib/bogo/stack.rb', line 537

def push(callable=nil, &block)
  synchronize do
    be_unprepared!
    act = Action.new(stack: self, callable: callable, &block)
    @actions = ([act]+ actions).freeze
    act
  end
end

#remove(idx = nil) {|Array<Action>| ... } ⇒ Action, NilClass

Remove item from the stack

Parameters:

  • idx (Integer, Action) (defaults to: nil)

    index or Action of Action to remove

Yields:

  • (Array<Action>)

    stack content is provided to block

Yield Returns:

  • (Integer, Action)

    index or Action of Action to remove

Returns:

  • (Action, NilClass)

    removed entry



566
567
568
569
570
571
572
573
574
575
576
577
578
579
# File 'lib/bogo/stack.rb', line 566

def remove(idx=nil)
  synchronize do
    be_unprepared!
    idx = yield stack if idx.nil? && block_given?
    if !idx.is_a?(Integer) && !idx.is_a?(Action)
      raise ArgumentError,
        "Expecting `Integer` or `#{Action.name}` but received `#{idx.class}`"
    end
    @actions = actions.dup
    entry = @actions.delete(idx)
    @actions.freeze
    entry
  end
end

#shiftAction?

Remove first action from the stack

Returns:



643
644
645
646
647
648
649
650
651
# File 'lib/bogo/stack.rb', line 643

def shift
  synchronize do
    be_unprepared!
    @actions = actions.dup
    action = actions.shift
    @actions.freeze
    action
  end
end

#sizeInteger

Returns number of actions in stack.

Returns:

  • (Integer)

    number of actions in stack



654
655
656
# File 'lib/bogo/stack.rb', line 654

def size
  actions.size
end

#started?TrueClass, FalseClass

Returns stack has started execution.

Returns:

  • (TrueClass, FalseClass)

    stack has started execution



659
660
661
# File 'lib/bogo/stack.rb', line 659

def started?
  @started
end

#unshift(callable = nil, &block) ⇒ Action

Unshift a new callable action onto the start of the stack

Parameters:

  • callable (Class, Proc) (defaults to: nil)

    object that responds to #call or class with #call instance method

Returns:

  • (Action)

    generated Action instance



551
552
553
554
555
556
557
558
# File 'lib/bogo/stack.rb', line 551

def unshift(callable=nil, &block)
  synchronize do
    be_unprepared!
    act = Action.new(stack: self, callable: callable, &block)
    @actions = (actions + [act]).freeze
    act
  end
end