hegemon 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hegemon.rb +195 -32
  3. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 49bad6b2e72c34ac00fb694f3d7b40d1b8bd168a
4
- data.tar.gz: ccf88b8f9e69b31726b5f2bf8a9fc23b0eed5333
3
+ metadata.gz: 3b434952e8994ae0a8d76f3892f7519a3ef21fbd
4
+ data.tar.gz: dfcfaf716ddaefe24334316dbc03597bdb42150f
5
5
  SHA512:
6
- metadata.gz: a95f34e0f58946285972a6694eae01058d1b9fe5cc010c090790102c965aa49cb51482d5ab2967e8d8425f0ca0901b3dabac3a93dd2756ececdca63118bbc924
7
- data.tar.gz: 6593a9e1dd3dfe3c2a5fca87e3aeb4859d0a4ed6d76bb7f6da94f8c8f8a5edde55a4950e4bef3a1660c168ce287f70b69c6b84451f11b569cdbdbeaee323f1d3
6
+ metadata.gz: dd1b9994151efd8aa79065d1f3cf96753661d17d57ee317ec2deb5d948cce280013996f1516eefca9353d0c082de73aca8417d683315f83ae879242849098d70
7
+ data.tar.gz: 138a26699c3523e855e554bb71f555f9154d8d11d66c086586cd19ec3208e1d7169a6f61ef43126df41476ffce105f15fa7cd1a3520cb064478eab3a407a7dcc
@@ -4,53 +4,170 @@ Thread.abort_on_exception = true
4
4
 
5
5
  module Hegemon
6
6
 
7
- #***
8
- # Accessor functions
9
- #***
7
+ ##
8
+ # :section: Accessor Methods
9
+ #
10
10
 
11
+ # Return the current state (as a symbol)
11
12
  def state; @_hegemon_state; end
13
+ # Return the list of declared states (as an array of symbols)
12
14
  def states; @_hegemon_states.keys; end
15
+ # Return the current state (as a HegemonState object)
13
16
  def state_obj; @_hegemon_states[@_hegemon_state]; end
17
+ # Return the current state (as a Hash of HegemonState objects keyed by symbol)
14
18
  def state_objs; @_hegemon_states.clone; end
15
19
 
16
- threadlock :state, :states, :state_obj, :state_objs, :lock=>:@_hegemon_lock
20
+ # threadlock :state, :states, :state_obj, :state_objs, :lock=>:@_hegemon_lock
17
21
 
18
- #***
19
- # Declarative functions
20
- #***
21
- # Run these inside of your object's #initialize method
22
- # to set the parameters of the state machine
23
- # All user-provided action blocks will have the scope of the instance object
24
- # in which the state machine parameters are initialized, and all parameters
25
- # should be initialized in the same place (in #initialize, typically)
26
- #***
27
22
 
28
- ##
29
- # Bypass all transition requirements and actions to directly impose state +s+
30
- # This should not be used in the public API except to set the initial state
31
- def impose_state(s); @_hegemon_state = s; end
32
- threadlock :impose_state, :lock=>:@_hegemon_lock
33
23
 
34
24
  ##
35
- # Declare a state in the state machine
36
- # [+state+] The state name to use, as a symbol
37
- # [+&block+] The state's declarative block
38
- # (refer to Declarative Functions of HegemonState)
25
+ # :section: Declarative Methods
26
+ #
27
+
28
+ #
29
+ # Declare a state in the state machine.
30
+ # Returns the HegemonState object created.
31
+ #
32
+ # [+state+]
33
+ # The state name to use, as a symbol
34
+ # [+block+]
35
+ # The state's declarative block.
36
+ # All code within gets evaluated not in its original binding,
37
+ # but in the context of a new HegemonState instance object.
38
+ # For stable use, only call methods in this block that are
39
+ # listed in HegemonState@Declarative+Methods.
40
+ #
41
+ # The state and associated state machine data and methods will be
42
+ # associated with the object referred to by +self+ object in the context
43
+ # in which the declarative method is called.
44
+ #
45
+ # This means that in typical usage, the declarative methods listed
46
+ # in Hegemon@Declarative+Methods (including declare_state) should be
47
+ # called only from within an instance method, such as +initialize+.
48
+ #
49
+ # The following example creates a skeleton state machine in each
50
+ # +MyStateMachine+ instance object with two states: +:working+ and +:idle+.
51
+ #
52
+ # require 'hegemon'
53
+ #
54
+ # class MyStateMachine
55
+ # include Hegemon
56
+ #
57
+ # def initialize
58
+ # declare_state :working do
59
+ # # various HegemonState Declarative Methods
60
+ # end
61
+ # declare_state :idle do
62
+ # # various HegemonState Declarative Methods
63
+ # end
64
+ # end
65
+ # end
66
+ #
39
67
  def declare_state(state, &block)
40
68
  @_hegemon_states ||= Hash.new
41
69
  @_hegemon_states[state] = HegemonState.new(self, state, &block)
42
70
  end
43
71
  threadlock :declare_state, :lock=>:@_hegemon_lock
44
72
 
45
- # Attempt a transition from the current state to state +s+
46
- def request_state(s, *flags)
73
+
74
+ #
75
+ # Bypass all transition requirements and actions to
76
+ # directly impose state +state+ as the current state.
77
+ #
78
+ # This should *not* be used in the public API *except* to
79
+ # set the initial state of the state machine, because state changes
80
+ # imposed by impose_state do not obey any rules of the state machine.
81
+ #
82
+ # [+state+]
83
+ # The state to impose, as a symbol
84
+ #
85
+ # This method should be called in the same scope in which the state
86
+ # was declared with declare_state\.
87
+ #
88
+ # The following example creates a skeleton state machine in each
89
+ # +MyStateMachine+ instance object with two states: +:working+ and +:idle+
90
+ # and sets +:working+ as the initial state.
91
+ #
92
+ # require 'hegemon'
93
+ #
94
+ # class MyStateMachine
95
+ # include Hegemon
96
+ #
97
+ # def initialize
98
+ # impose_state :working
99
+ # declare_state :working do
100
+ # # various HegemonState Declarative Methods
101
+ # end
102
+ # declare_state :idle do
103
+ # # various HegemonState Declarative Methods
104
+ # end
105
+ # end
106
+ # end
107
+ def impose_state(s) # :args: state
108
+ @_hegemon_state = s
109
+ nil end
110
+ threadlock :impose_state, :lock=>:@_hegemon_lock
111
+
112
+
113
+
114
+ ##
115
+ # :section: State Action Methods
116
+ #
117
+
118
+ #
119
+ # Request a transition from the current state to state +state+.
120
+ # Returns +true+ if the transition was performed, else returns +false+.
121
+ #
122
+ # [+state+]
123
+ # The state to which transition is desired, as a symbol
124
+ # [+flags+]
125
+ # All subsequent arguments are interpreted as flags,
126
+ # and the only meaningful flag is +:force+
127
+ # (See transition requirements below).
128
+ #
129
+ # In order for the transition to occur, the transition must
130
+ # have been defined (using HegemonState#transition_to), and the
131
+ # transition rules declared in the HegemonTransition declarative block
132
+ # have been suitably met by any one of the following situations:
133
+ # * *All* HegemonTransition#requirement blocks evaluate as +true+
134
+ # and the +:force+ flag was included in +flags+.
135
+ # * At least *one* HegemonTransition#sufficient block and *all*
136
+ # HegemonTransition#requirement blocks evaluate as +true+
137
+ # * *All* HegemonTransition#condition blocks and *all*
138
+ # HegemonTransition#requirement blocks evaluate as +true+
139
+ #
140
+ # Note that evaluation of the rule blocks stops when a match is found,
141
+ # so rule blocks with code that has "side effects" are discouraged.
142
+ #
143
+ def request_state(s, *flags) # :args: state, *flags
47
144
  return false unless @_hegemon_states[@_hegemon_state].transitions[s]
48
145
  @_hegemon_states[@_hegemon_state].transitions[s].try(*flags)
49
146
  end
50
147
  threadlock :request_state, :lock=>:@_hegemon_lock
51
148
 
52
- # Check for relevant state updates and do.
53
- # Using :only_auto flag will ignore all transitions with auto_update false
149
+ #
150
+ # Check the list of possible transitions from the current state
151
+ # and perform the first transition that is found to be ready, if any.
152
+ # Returns +true+ if the transition was performed, else returns +false+.
153
+ #
154
+ # [+flags+]
155
+ # All subsequent arguments are interpreted as flags,
156
+ # and the only meaningful flag is +:only_auto+.
157
+ # Use of the +:only_auto+ flag indicates that all state
158
+ # transitions which have disabled automatic updating with
159
+ # HegemonTransition#auto_update should be ignored.
160
+ #
161
+ # In order for a transition to occur, the transition rules
162
+ # declared in the HegemonTransition declarative block have been
163
+ # suitably met by any one of the following situations:
164
+ # * *All* HegemonTransition#requirement blocks evaluate as +true+
165
+ # and the +:force+ flag was included in +flags+.
166
+ # * At least *one* HegemonTransition#sufficient block and *all*
167
+ # HegemonTransition#requirement blocks evaluate as +true+
168
+ # * *All* HegemonTransition#condition blocks and *all*
169
+ # HegemonTransition#requirement blocks evaluate as +true+
170
+ #
54
171
  def update_state(*flags)
55
172
  return false unless @_hegemon_states[@_hegemon_state]
56
173
  trans = @_hegemon_states[@_hegemon_state].transitions
@@ -59,48 +176,94 @@ module Hegemon
59
176
  false end
60
177
  threadlock :update_state, :lock=>:@_hegemon_lock
61
178
 
62
- def block_until_state(s);
179
+ #
180
+ # Sleep the current thread until the current state is equal to +state+
181
+ #
182
+ # [+state+]
183
+ # The symbol to compare against the current state against
184
+ #
185
+ def block_until_state(s); # :args: state
63
186
  raise ArgumentError, "Cannot block until undefined state :#{s}" \
64
187
  unless @_hegemon_states.keys.include? s
65
188
  sleep 0 until @_hegemon_state==s
66
- end
189
+ nil end
67
190
 
68
- def do_state_tasks(i=0)
191
+ #
192
+ # Perform all HegemonState#task\s associated with the current state.
193
+ # Tasks are performed in the order they were declared in the
194
+ # HegemonState declarative block.
195
+ #
196
+ # [+iter_num+ = 0]
197
+ # Specify the iteration number to be passed to the task block.
198
+ # When called by the +hegemon_auto_thread+ (see start_hegemon_auto_thread),
199
+ # this number counts up from zero for each iteration of the
200
+ # +hegemon_auto_thread+ loop. If no value is specified, +0+ is used.
201
+ #
202
+ def do_state_tasks(iter_num = 0)
69
203
  return nil unless @_hegemon_states[@_hegemon_state]
70
- @_hegemon_states[@_hegemon_state].do_tasks(i)
204
+ @_hegemon_states[@_hegemon_state].do_tasks(iter_num)
71
205
  nil end
72
206
  threadlock :do_state_tasks, :lock=>:@_hegemon_lock
73
207
 
208
+
209
+
210
+ ##
211
+ # :section: Thread Action Methods
212
+ #
213
+
74
214
  def iter_hegemon_auto_loop(i=0)
75
215
  do_state_tasks(i)
76
216
  update_state(:only_auto)
77
217
  end
218
+ private :iter_hegemon_auto_loop
78
219
  threadlock :iter_hegemon_auto_loop, :lock=>:@_hegemon_lock
79
220
 
80
- # Run the automatic hegemon thread
81
- def start_hegemon_auto_thread
221
+ #
222
+ # Run the +hegemon_auto_thread+ if it is not already running.
223
+ # Returns the Thread object.
224
+ # The +hegemon_auto_thread+ continually calls do_state_tasks and update_state,
225
+ # counting up from +0+ the value passed to do_state_tasks, until the
226
+ # thread is stopped with end_hegemon_auto_thread\.
227
+ #
228
+ # [+throttle = 0.1+]
229
+ # The amount of time to sleep between iterations, 0.1 seconds by default.
230
+ #
231
+ def start_hegemon_auto_thread(throttle = 0.1)
82
232
  if (not @_hegemon_auto_thread) \
83
233
  or (not @_hegemon_auto_thread.status)
84
234
 
85
235
  @_end_hegemon_auto_thread = false
236
+ @_hegemon_auto_thread_throttle ||= throttle
86
237
  @_hegemon_auto_thread = Thread.new do
87
238
  i = 0
88
239
  until @_end_hegemon_auto_thread
89
240
  iter_hegemon_auto_loop(i)
90
241
  i += 1
242
+ sleep @_hegemon_auto_thread_throttle
91
243
  end
92
244
  end
93
245
  end
246
+ @_hegemon_auto_thread
94
247
  end
95
248
 
249
+ #
250
+ # Block until the +hegemon_auto_thread+ is finished.
251
+ #
96
252
  def join_hegemon_auto_thread
97
253
  @_hegemon_auto_thread.join if @_hegemon_auto_thread
98
254
  end
99
255
 
256
+ #
257
+ # Raise a flag to stop the loop inside +hegemon_auto_thread+.
258
+ #
100
259
  def end_hegemon_auto_thread
101
260
  @_end_hegemon_auto_thread = true
102
261
  end
103
262
  threadlock :end_hegemon_auto_thread, :lock=>:@_hegemon_lock
263
+
264
+ #
265
+ # :section:
266
+ ##
104
267
  end
105
268
 
106
269
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hegemon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe McIlvain