The Set class in the boduch Python library is essentially a Python list that publishes events. These events that are published by Set instances have the potential to be handled in a multi-threaded environment. If Set instances are being both "pushed" to and "pulled" from in a multi-threaded environment, this could be very dangerous. Data that is expected to exist in the set instance when "pulled" may not have arrived yet. In this scenario, it would be useful to know what state the Set instance is in. By combining both the Set and StateMachine classes as demonstrated below, we end up with a "stateful" Python list. The implementation of the StatefulSet shown here isn't fully thread safe. This is because it is incomplete. However, the code used in the main program is thread safe.
#example; Creating a multi-threaded Python list with a boduch Set.
#Necessary imports.
from boduch.event import threaded, subscribe, EventSetPush
from boduch.handle import Handle, HandleSetPush
from boduch.data import Set
from boduch.state import StateMachine
from boduch.type import is_type
from boduch import PRIORITY_MINOR, PRIORITY_CRITICAL
#A handle for Set.push() method invocations.
class HandlePreStatefulSetPush(Handle):
#This gets a higher than critical priority since it is
#intended to run before the core behavior.
priority=PRIORITY_CRITICAL+1
def __init__(self, *args, **kw):
Handle.__init__(self, *args, **kw)
def run(self):
#Check if we are handling a StatefulSet event. If
#so, set goes into a pushing state.
set_obj=self.get_event_data("set")
if is_type(set_obj, "StatefulSet"):
set_obj.change_state("PUSHING")
#A handle for Set.push() method invocations.
class HandlePostStatefulSetPush(Handle):
#This handle gets a minor priority since it is
#intended to run after all the pushing is complete.
priority=PRIORITY_MINOR
def __init__(self, *args, **kw):
Handle.__init__(self, *args, **kw)
def run(self):
#Check if we are handling a StatefulSet event. If
#so, set goes into a ready state.
set_obj=self.get_event_data("set")
if is_type(set_obj, "StatefulSet"):
set_obj.change_state("READY")
#A stateful version of the Set class.
class StatefulSet(StateMachine, Set):
def __init__(self, *args, **kw):
#Initialize the base classes and populate the
#potential set states.
StateMachine.__init__(self, *args, **kw)
Set.__init__(self, *args, **kw)
self.add_state("READY")
self.add_state("PUSHING")
def _push(self, data):
#Change to a pushing state before actually pushing data.
self.change_state("PUSHING")
self.push(data)
def _get(self, index):
#Don't attempt to return anything while in a pushing state.
while self=="PUSHING":
print "Hold on, still pushing data."
pass
return self[index]
#Subscribe the custom stateful handles.
subscribe(EventSetPush, HandlePreStatefulSetPush)
subscribe(EventSetPush, HandlePostStatefulSetPush)
#Main program.
if __name__=="__main__":
#Enable threaded event mode.
threaded(True)
#Instantiate a stateful set.
set_obj=StatefulSet()
#Populate the set while retrieving data in a thread-safe manor.
for i in range(0,10):
set_obj._push("SET DATA"+str(i))
print set_obj._get(i)
No comments :
Post a Comment