"""
December2005.py
Andrew Francis

The purpose of this example is to demonstrate the use of the deadlock
detector on a more complex problem.
"""


import stackless
from   DeadlockDetector2      import DeadlockDetector


class CustomTasklet(stackless.tasklet):
    name = ""

    def __repr__(self):
        return self.name


class CustomChannel(stackless.channel):
    name = ""

    def __repr__(self):
        return self.name 



class TestActivity(object):

    # sources - hashTable of input  channels
    # targets - hashTable of output channels
    def __init__(self, name, sources, targets):
        self.sources = sources
        self.targets = targets
        self.name = name


    def execute(self):
        global detector
        list = []
        [list.append(channel) for channel in self.sources.values() + self.targets.values()]
        detector.registerResources(stackless.getcurrent(), list)

        print self.name, " about to Join"
        for target in self.targets:
            print self.name, "joining ", target
            self.targets[target].receive()
            print self.name, "--joined-- ", target
            
        print self.name, "finished joining"
        
        print self.name, "*** finished Executing ***"
        
        print self.name, "about to update dependents"
        for source in self.sources:
            print self.name, "updating ", source
            self.sources[source].send(True)
        print self.name, "finishing"


class StacklessTests(object):
   
    def __init__(self):
        global detector
        self.detector = DeadlockDetector()
        detector = self.detector


    def makeTasklet(self, name, sources, targets):
        print "NAME", name
        activity = TestActivity(name, sources, targets)
        t = CustomTasklet(activity.execute)()
        t.name = name
       
        
    def TestOne(self):
 
        channelAtoC = CustomChannel()
        channelAtoC.name = "AtoC"

        channelBtoC = CustomChannel()
        channelBtoC.name = "BtoC" 

        channelBtoE = CustomChannel()
        channelBtoE.name = "BtoE"

        channelCtoD = CustomChannel()
        channelCtoD.name = "CtoD"

        channelCtoE = CustomChannel()
        channelCtoE.name = "CtoE"

        channelDtoF = CustomChannel()
        channelDtoF.name = "DtoF"

        channelEtoF = CustomChannel()
        channelEtoF.name = "EtoF"
        
        self.makeTasklet("A", {"AtoC":channelAtoC},{})
        self.makeTasklet("B", {"BtoC":channelBtoC, "BtoE":channelBtoE},{})
        self.makeTasklet("C", {"CtoD":channelCtoD, "CtoE":channelCtoE}, \
                         {"AtoC":channelAtoC, "BtoC":channelBtoC})
        self.makeTasklet("D", {"DtoF":channelDtoF}, {"CtoD":channelCtoD})
        self.makeTasklet("E", {"EtoF":channelEtoF}, \
                              {"CtoE":channelCtoE, "BtoE":channelBtoE})
        self.makeTasklet("F", {}, {"EtoF":channelEtoF,"DtoF":channelDtoF})
        
        stackless.run()
        print self.detector.detect()
    
    
test = StacklessTests()
test.TestOne()

