lib/openwfe/expressions/fe_reserve.rb in ruote-0.9.18 vs lib/openwfe/expressions/fe_reserve.rb in ruote-0.9.19
- old
+ new
@@ -1,34 +1,34 @@
#
#--
# Copyright (c) 2007-2008, John Mettraux, OpenWFE.org
# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
+#
+# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# . Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-#
-# . Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
+# list of conditions and the following disclaimer.
+#
+# . Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
-#
+#
# . Neither the name of the "OpenWFE" nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#++
#
#
@@ -40,173 +40,184 @@
#require 'thread'
module OpenWFE
+ #
+ # The 'reserve' expression ensures that its nested child expression
+ # executes while a reserved mutex is set.
+ #
+ # Thus
+ #
+ # concurrence do
+ # reserve :mutex => :m0 do
+ # sequence do
+ # participant :alpha
+ # participant :bravo
+ # end
+ # end
+ # reserve :mutex => :m0 do
+ # participant :charly
+ # end
+ # participant :delta
+ # end
+ #
+ # The sequence will not but run while the participant charly is active
+ # and vice versa. The participant delta is not concerned.
+ #
+ # The mutex is a regular variable name, thus a mutex named "//toto" could
+ # be used to prevent segments of totally different process instances from
+ # running.
+ #
+ class ReserveExpression < FlowExpression
+
#
- # The 'reserve' expression ensures that its nested child expression
- # executes while a reserved mutex is set.
+ # A mutex for the whole class, it's meant to prevent 'reserve'
+ # from reserving a workflow mutex simultaneaously.
#
- # Thus
+ #@@mutex = Mutex.new
+
+ names :reserve
+
#
- # concurrence do
- # reserve :mutex => :m0 do
- # sequence do
- # participant :alpha
- # participant :bravo
- # end
- # end
- # reserve :mutex => :m0 do
- # participant :charly
- # end
- # participant :delta
- # end
+ # The name of the mutex this expressions uses.
+ # It's a variable name, that means it can be prefixed with
+ # {nothing} (local scope), '/' (process scope) and '//' (engine /
+ # global scope).
#
- # The sequence will not but run while the participant charly is active
- # and vice versa. The participant delta is not concerned.
+ attr_accessor :mutex_name
+
#
- # The mutex is a regular variable name, thus a mutex named "//toto" could
- # be used to prevent segments of totally different process instances from
- # running.
+ # An instance variable for storing the applied workitem if the 'reserve'
+ # cannot be entered immediately.
#
- class ReserveExpression < FlowExpression
+ attr_accessor :applied_workitem
- #
- # A mutex for the whole class, it's meant to prevent 'reserve'
- # from reserving a workflow mutex simultaneaously.
- #
- #@@mutex = Mutex.new
- names :reserve
+ def apply (workitem)
- #
- # The name of the mutex this expressions uses.
- # It's a variable name, that means it can be prefixed with
- # {nothing} (local scope), '/' (process scope) and '//' (engine /
- # global scope).
- #
- attr_accessor :mutex_name
+ return reply_to_parent(workitem) \
+ if @children.size < 1
- #
- # An instance variable for storing the applied workitem if the 'reserve'
- # cannot be entered immediately.
- #
- attr_accessor :applied_workitem
+ @mutex_name = lookup_string_attribute :mutex, workitem
+ #FlowMutex.synchronize do
- def apply (workitem)
+ mutex = lookup_variable(@mutex_name) || FlowMutex.new(@mutex_name)
- return reply_to_parent(workitem) \
- if @children.size < 1
+ mutex.register self, workitem
+ #end
+ end
- @mutex_name = lookup_string_attribute :mutex, workitem
+ def reply (workitem)
- #FlowMutex.synchronize do
+ lookup_variable(@mutex_name).release self
- mutex = lookup_variable(@mutex_name) || FlowMutex.new(@mutex_name)
+ reply_to_parent workitem
+ end
- mutex.register self, workitem
- #end
- end
+ #
+ # takes care of exiting the critical section once the children
+ # have been cancelled
+ #
+ def cancel
- def reply (workitem)
+ super
- lookup_variable(@mutex_name).release self
-
- reply_to_parent workitem
- end
-
- #
- # Called by the FlowMutex to enter the 'reserved/critical' section.
- #
- def enter (workitem=nil)
-
- get_expression_pool.apply(
- @children[0], workitem || @applied_workitem)
- end
+ lookup_variable(@mutex_name).release self
end
#
- # A FlowMutex is a process variable (thus serializable) that keeps
- # track of the expressions in a critical section (1!) or waiting for
- # entering it.
+ # Called by the FlowMutex to enter the 'reserved/critical' section.
#
- #--
- # The current syncrhonization scheme is 1 thread mutex for all the
- # FlowMutex. Shouldn't be too costly and the operations under sync are
- # quite tiny.
- #++
- #
- class FlowMutex
+ def enter (workitem=nil)
- #--
- # Granularity level ? "big rock". Only one FlowMutex operation
- # a a time for the whole business process engine...
- #
- #@@class_mutex = Mutex.new
- #++
+ get_expression_pool.apply(
+ @children[0], workitem || @applied_workitem)
+ end
+ end
- attr_accessor :mutex_name
- attr_accessor :feis
+ #
+ # A FlowMutex is a process variable (thus serializable) that keeps
+ # track of the expressions in a critical section (1!) or waiting for
+ # entering it.
+ #
+ #--
+ # The current syncrhonization scheme is 1 thread mutex for all the
+ # FlowMutex. Shouldn't be too costly and the operations under sync are
+ # quite tiny.
+ #++
+ #
+ class FlowMutex
- def initialize (mutex_name)
+ #--
+ # Granularity level ? "big rock". Only one FlowMutex operation
+ # a a time for the whole business process engine...
+ #
+ #@@class_mutex = Mutex.new
+ #++
- @mutex_name = mutex_name
- @feis = []
- end
+ attr_accessor :mutex_name
+ attr_accessor :feis
- def register (fexp, workitem)
+ def initialize (mutex_name)
- @feis << fexp.fei
+ @mutex_name = mutex_name
+ @feis = []
+ end
- fexp.set_variable @mutex_name, self
+ def register (fexp, workitem)
- if @feis.size == 1
- #
- # immediately let the expression enter the critical section
- #
- fexp.store_itself
- fexp.enter workitem
- else
- #
- # later...
- #
- fexp.applied_workitem = workitem
- fexp.store_itself
- end
- end
+ @feis << fexp.fei
- def release (releaser)
+ fexp.set_variable @mutex_name, self
- next_fei = nil
+ if @feis.size == 1
+ #
+ # immediately let the expression enter the critical section
+ #
+ fexp.store_itself
+ fexp.enter workitem
+ else
+ #
+ # later...
+ #
+ fexp.applied_workitem = workitem
+ fexp.store_itself
+ end
+ end
- #@@class_mutex.synchronize do
+ def release (releaser)
- current_fei = @feis.delete_at 0
+ next_fei = nil
- releaser.set_variable @mutex_name, self
+ #@@class_mutex.synchronize do
- log.warn "release() BAD! c:#{current_fei} r:#{releaser.fei}" \
- if releaser.fei != current_fei
+ current_fei = @feis.delete_at 0
- next_fei = @feis.first
- #end
+ releaser.set_variable @mutex_name, self
- return unless next_fei
+ log.warn "release() BAD! c:#{current_fei} r:#{releaser.fei}" \
+ if releaser.fei != current_fei
- releaser.get_expression_pool.fetch_expression(next_fei).enter
- end
+ next_fei = @feis.first
+ #end
- #--
- # Used by the ReserveExpression when looking up for a FlowMutex
- # and registering into it.
- #
- #def self.synchronize (&block)
- # @@class_mutex.synchronize do
- # block.call
- # end
- #end
- #++
+ return unless next_fei
+
+ releaser.get_expression_pool.fetch_expression(next_fei).enter
end
+
+ #--
+ # Used by the ReserveExpression when looking up for a FlowMutex
+ # and registering into it.
+ #
+ #def self.synchronize (&block)
+ # @@class_mutex.synchronize do
+ # block.call
+ # end
+ #end
+ #++
+ end
end