Class: Motel::Runner

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/motel/runner.rb

Overview

Motel::Runner is a singleton class/object which acts as the primary mechanism to run locations in the system. It contains a thread pool which contains a specified number of threads which to move the managed locations in accordance to their location strategies.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Runner

Returns a new instance of Runner.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/motel/runner.rb', line 22

def initialize(args = {})
  # is set to true upon runner termination
  @terminate = false

  # TODO use ruby tree to store locations w/ heirarchy
  # management queues, locations to be scheduled and locations to be run
  @schedule_queue = []
  @run_queue = []


  # locks protecting queues from concurrent access and conditions indicating queues have items
  @schedule_lock  = Mutex.new
  @run_lock       = Mutex.new
  @schedule_cv    = ConditionVariable.new
  @run_cv         = ConditionVariable.new

  @run_thread = nil
end

Instance Attribute Details

#run_threadObject (readonly)

For testing purposes



20
21
22
# File 'lib/motel/runner.rb', line 20

def run_thread
  @run_thread
end

#terminateObject (readonly)

For testing purposes



20
21
22
# File 'lib/motel/runner.rb', line 20

def terminate
  @terminate
end

Instance Method Details

#<<(location) ⇒ Object

Wrapper around run, except return ‘self’ when done



81
82
83
84
# File 'lib/motel/runner.rb', line 81

def <<(location)
  run(location)
  return self
end

#clearObject

Empty the list of locations being managed/tracked



49
50
51
52
53
54
55
# File 'lib/motel/runner.rb', line 49

def clear
  @schedule_lock.synchronize {
    @run_lock.synchronize {
      @schedule_queue.clear
      @run_queue.clear
  }}
end

#joinObject

Block until runner is shutdown before returning



118
119
120
121
# File 'lib/motel/runner.rb', line 118

def join
  @run_thread.join unless @run_thread.nil?
  @run_thread = nil
end

#locationsObject

Return complete list of locations being managed/tracked



42
43
44
45
# File 'lib/motel/runner.rb', line 42

def locations
  # need conccurrent protection here, or copy the elements into another array and return that?
  @schedule_queue + @run_queue
end

#run(location) ⇒ Object

Add location to runner to be managed, after this is called, the location’s movement strategy’s move method will be invoked periodically



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/motel/runner.rb', line 59

def run(location)
  @schedule_lock.synchronize {
    # autogenerate location.id if nil
    if location.id.nil?
      @run_lock.synchronize {
        i = 1
        until false
          break if @schedule_queue.find { |l| l.id == i }.nil? && @run_queue.find { |l| l.id == i }.nil?
          i += 1
        end
        location.id = i
      }
    end

    Logger.debug "adding location #{location.id} to runner queue"
    @schedule_queue.push location
    @schedule_cv.signal
  }
  return location
end

#start(args = {}) ⇒ Object

Start moving the locations. If :async => true is passed in, this will immediately return, else this will block until stop is called.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/motel/runner.rb', line 88

def start(args = {})
  @num_threads = 5
  @num_threads = args[:num_threads] if args.has_key? :num_threads
  @terminate = false

  if args.has_key?(:async) && args[:async]
    Logger.debug "starting async motel runner"
    @run_thread = Thread.new { run_cycle }
  else
    Logger.debug "starting motel runner"
    run_cycle
  end

end

#stopObject

Stop locations movement



104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/motel/runner.rb', line 104

def stop
  Logger.debug "stopping motel runner"
  @terminate = true
  @schedule_lock.synchronize {
    @schedule_cv.signal
  }
  @run_lock.synchronize {
    @run_cv.signal
  }
  join
  Logger.debug "motel runner stopped"
end