hegemon 0.0.1 → 0.0.2

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 +223 -1
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a3c4e4c6087e43a78b89a9b70561a2c53978eb66
4
- data.tar.gz: 2ecc3d78169f174681623f0835ad590a896e202e
3
+ metadata.gz: 16c25ed67f2ba46414da653d229bd42fc2305bb6
4
+ data.tar.gz: 07eb0d874631e68ea5bca5457186bfa9b8d766bf
5
5
  SHA512:
6
- metadata.gz: 2cbd7490ec74838d7ad5ac3c2808564490a4ec630813b3599d7a570efd6e3feb93d259db935a9ea6f94d85b3d6c9e15834ad2b8b650563fd8460c2eb8c12b1e8
7
- data.tar.gz: d748f7d8650510f8ac56a9d8612d66cfa478b9b5402cf2ca50925c479776b4aa9fd7d0d0859516be86eb83db18789920d7714c56293160d2e9eaa58aa21fb87b
6
+ metadata.gz: 2420e9542dfdcc16a5a7bba5b5c00e13c181628a79c4e637450c31c38da86d06cc1ae571fc204ec86e3ed363acdb588a849ef442c816471c1cf111379c6abd63
7
+ data.tar.gz: a2bcef08cee2efe18568c88ae54a012035b8afa4d3ebba9f815bfce887ab71075d9b0c4d3122fb98bd23cfd6b4f1842570827eb2be6559a8366fa771c2bd26bf
@@ -1 +1,223 @@
1
- require 'threadlock'
1
+ require 'threadlock'
2
+
3
+ Thread.abort_on_exception = true
4
+ def puts(*args); $stdout.puts(*args); end
5
+
6
+ module Hegemon
7
+
8
+ #***
9
+ # Accessor functions
10
+ #***
11
+
12
+ def state; @_hegemon_state; end
13
+ def states; @_hegemon_states.keys; end
14
+ def state_obj; @_hegemon_states[@_hegemon_state]; end
15
+ def state_objs; @_hegemon_states.clone; end
16
+
17
+ threadlock :state, :states, :state_obj, :state_objs, :lock=>:@_hegemon_lock
18
+
19
+ #***
20
+ # Declarative functions
21
+ #***
22
+ # Run these inside of your object's #initialize method
23
+ # to set the parameters of the state machine
24
+ # All user-provided action blocks will have the scope of the instance object
25
+ # in which the state machine parameters are initialized, and all parameters
26
+ # should be initialized in the same place (in #initialize, typically)
27
+ #***
28
+
29
+ ##
30
+ # Bypass all transition requirements and actions to directly impose state +s+
31
+ # This should not be used in the public API except to set the initial state
32
+ def impose_state(s); @_hegemon_state = s; end
33
+ threadlock :impose_state, :lock=>:@_hegemon_lock
34
+
35
+ ##
36
+ # Declare a state in the state machine
37
+ # [+state+] The state name to use, as a symbol
38
+ # [+&block+] The state's declarative block
39
+ # (refer to Declarative Functions of HegemonState)
40
+ def declare_state(state, &block)
41
+ @_hegemon_states ||= Hash.new
42
+ @_hegemon_states[state] = HegemonState.new(self, state, &block)
43
+ end
44
+ threadlock :declare_state, :lock=>:@_hegemon_lock
45
+
46
+ # Attempt a transition from the current state to state +s+
47
+ def request_state(s, *flags)
48
+ return false unless @_hegemon_states[@_hegemon_state].transitions[s]
49
+ @_hegemon_states[@_hegemon_state].transitions[s].try(*flags)
50
+ end
51
+ threadlock :request_state, :lock=>:@_hegemon_lock
52
+
53
+ # Check for relevant state updates and do.
54
+ # Using :only_auto flag will ignore all transitions with auto_update false
55
+ def update_state(*flags)
56
+ return false unless @_hegemon_states[@_hegemon_state]
57
+ trans = @_hegemon_states[@_hegemon_state].transitions
58
+ trans = trans.select{|k,t| t.auto_update} if (flags.include? :only_auto)
59
+ trans.each {|k,t| return true if t.try}
60
+ false end
61
+ threadlock :update_state, :lock=>:@_hegemon_lock
62
+
63
+ def block_until_state(s);
64
+ raise ArgumentError, "Cannot block until undefined state :#{s}" \
65
+ unless @_hegemon_states.keys.include? s
66
+ sleep 0 until @_hegemon_state==s
67
+ end
68
+
69
+ def do_state_tasks(i=0)
70
+ return nil unless @_hegemon_states[@_hegemon_state]
71
+ @_hegemon_states[@_hegemon_state].do_tasks(i)
72
+ nil end
73
+ threadlock :do_state_tasks, :lock=>:@_hegemon_lock
74
+
75
+ def iter_hegemon_auto_loop(i=0)
76
+ do_state_tasks(i)
77
+ update_state(:only_auto)
78
+ end
79
+ threadlock :iter_hegemon_auto_loop, :lock=>:@_hegemon_lock
80
+
81
+ # Run the automatic hegemon thread
82
+ def start_hegemon_auto_thread
83
+ if (not @_hegemon_auto_thread) \
84
+ or (not @_hegemon_auto_thread.status)
85
+
86
+ @_end_hegemon_auto_thread = false
87
+ @_hegemon_auto_thread = Thread.new do
88
+ i = 0
89
+ until @_end_hegemon_auto_thread
90
+ iter_hegemon_auto_loop(i)
91
+ i += 1
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ def join_hegemon_auto_thread
98
+ @_hegemon_auto_thread.join if @_hegemon_auto_thread
99
+ end
100
+
101
+ def end_hegemon_auto_thread
102
+ @_end_hegemon_auto_thread = true
103
+ end
104
+ threadlock :end_hegemon_auto_thread, :lock=>:@_hegemon_lock
105
+ end
106
+
107
+
108
+ class HegemonState
109
+
110
+ attr_reader :state
111
+
112
+ def initialize(object, state, &block)
113
+
114
+ raise ScriptError, "HegemonState must be initialized with a block"\
115
+ unless block.is_a? Proc
116
+
117
+ @object = object
118
+ @state = state
119
+
120
+ @tasks = []
121
+ @transitions = Hash.new
122
+
123
+ instance_eval(&block)
124
+ end
125
+
126
+ def task(&block); @tasks << block if block; end
127
+
128
+ def transition_to(state, &block)
129
+ @transitions[state] = HegemonTransition.new(@object, @state, state, &block)
130
+ end
131
+
132
+ def do_tasks(i=0)
133
+ @tasks.each {|proc| @object.instance_exec(i,&proc) }
134
+ end
135
+
136
+ def transitions; @transitions; end
137
+
138
+ threadlock self.instance_methods-Object.instance_methods
139
+
140
+ end
141
+
142
+
143
+ class HegemonTransition
144
+
145
+ attr_reader :src_state, :dest_state
146
+
147
+ def initialize(object, src_state, dest_state, &block)
148
+
149
+ raise ScriptError, "HegemonTransition must be initialized with a block"\
150
+ unless block.is_a? Proc
151
+
152
+ @object = object
153
+ @src_state = src_state
154
+ @dest_state = dest_state
155
+
156
+ @conditions = []
157
+ @sufficients = []
158
+ @requirements = []
159
+ @befores = []
160
+ @afters = []
161
+
162
+ @progress = nil
163
+ @auto_update = true
164
+
165
+ instance_eval(&block)
166
+ end
167
+
168
+ def condition (&block); @conditions << block if block; end
169
+ def sufficient (&block); @sufficients << block if block; end
170
+ def requirement(&block); @requirements << block if block; end
171
+ def before (&block); @befores << block if block; end
172
+ def after (&block); @afters << block if block; end
173
+
174
+ # Get or set the @auto_update value
175
+ def auto_update(val=:just_ask)
176
+ (val==:just_ask) ?
177
+ (@auto_update) :
178
+ (@auto_update = (true and val))
179
+ end
180
+
181
+ def ready?(*flags)
182
+ return false unless @object.state==@src_state
183
+ return false if @progress
184
+
185
+ result = (procs_and @requirements)
186
+ return result if (flags.include? :force)
187
+
188
+ return result && ((procs_or @sufficients) or (procs_and @conditions))
189
+ end
190
+
191
+ def try(*flags)
192
+ (ready?(*flags)) ?
193
+ (perform; true) :
194
+ (false)
195
+ end
196
+
197
+ private
198
+
199
+ def perform
200
+ @progress = :pre
201
+ procs_run(@befores)
202
+ @progress = :impose
203
+ @object.impose_state(@dest_state)
204
+ @progress = :post
205
+ procs_run(@afters)
206
+ @progress = nil
207
+ nil end
208
+
209
+ def procs_run(list)
210
+ list.each {|proc| @object.instance_eval(&proc) }
211
+ nil end
212
+
213
+ def procs_and(list)
214
+ list.each {|proc| return false if not @object.instance_eval(&proc)}
215
+ true end
216
+
217
+ def procs_or(list)
218
+ list.each {|proc| return true if @object.instance_eval(&proc)}
219
+ false end
220
+
221
+ threadlock self.instance_methods-Object.instance_methods
222
+
223
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hegemon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe McIlvain
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-05 00:00:00.000000000 Z
11
+ date: 2013-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: threadlock