hegemon 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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