# -*- generated by 1.0.12 -*-
import da
PatternExpr_235 = da.pat.TuplePattern([da.pat.ConstantPattern('ack'), da.pat.FreePattern('c2'), da.pat.BoundPattern('_BoundPattern239_')])
PatternExpr_279 = da.pat.TuplePattern([da.pat.ConstantPattern('request'), da.pat.FreePattern('c2'), da.pat.FreePattern('p')])
PatternExpr_305 = da.pat.TuplePattern([da.pat.ConstantPattern('release'), da.pat.FreePattern(None), da.pat.FreePattern('p')])
PatternExpr_364 = da.pat.TuplePattern([da.pat.ConstantPattern('done')])
PatternExpr_369 = da.pat.BoundPattern('_BoundPattern371_')
PatternExpr_372 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern378_')]), da.pat.TuplePattern([da.pat.ConstantPattern('done')])])
PatternExpr_454 = da.pat.TuplePattern([da.pat.ConstantPattern('done'), da.pat.BoundPattern('_BoundPattern457_')])
PatternExpr_460 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.FreePattern(None)]), da.pat.TuplePattern([da.pat.ConstantPattern('done'), da.pat.BoundPattern('_BoundPattern470_')])])
_config_object = {'channel': 'fifo', 'clock': 'lamport'}
import sys

class P(da.DistProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._PReceivedEvent_0 = []
        self._PReceivedEvent_3 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_0', PatternExpr_235, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_1', PatternExpr_279, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_278]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_2', PatternExpr_305, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_304]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_3', PatternExpr_364, sources=[PatternExpr_369], destinations=None, timestamps=None, record_history=True, handlers=[])])

    def setup(self, s, nrequests, **rest_476):
        super().setup(s=s, nrequests=nrequests, **rest_476)
        self._state.s = s
        self._state.nrequests = nrequests
        self._state.q = set()

    def run(self):

        def task():
            self.output('in cs')
        for i in range(self._state.nrequests):
            self.mutex(task)
        self.send(('done', self._id), to=self.parent())
        super()._label('_st_label_361', block=False)
        _st_label_361 = 0
        while (_st_label_361 == 0):
            _st_label_361 += 1
            if PatternExpr_372.match_iter(self._PReceivedEvent_3, _BoundPattern378_=self.parent(), SELF_ID=self._id):
                _st_label_361 += 1
            else:
                super()._label('_st_label_361', block=True)
                _st_label_361 -= 1
        self.output('terminating')

    def mutex(self, task):
        super()._label('request', block=False)
        c = self.logical_clock()
        self.send(('request', c, self._id), to=self._state.s)
        self._state.q.add(('request', c, self._id))
        super()._label('_st_label_200', block=False)
        p = c2 = None

        def UniversalOpExpr_202():
            nonlocal p, c2
            for (_ConstantPattern206_, c2, p) in self._state.q:
                if (_ConstantPattern206_ == 'request'):
                    if (not (((c2, p) == (c, self._id)) or ((c, self._id) < (c2, p)))):
                        return False
            return True
        p = c2 = None

        def UniversalOpExpr_228():
            nonlocal p, c2
            for p in self._state.s:

                def ExistentialOpExpr_233(p):
                    nonlocal c2
                    for (_, _, (_ConstantPattern250_, c2, _BoundPattern253_)) in self._PReceivedEvent_0:
                        if (_ConstantPattern250_ == 'ack'):
                            if (_BoundPattern253_ == p):
                                if (c2 > c):
                                    return True
                    return False
                if (not ExistentialOpExpr_233(p=p)):
                    return False
            return True
        _st_label_200 = 0
        while (_st_label_200 == 0):
            _st_label_200 += 1
            if (UniversalOpExpr_202() and UniversalOpExpr_228()):
                _st_label_200 += 1
            else:
                super()._label('_st_label_200', block=True)
                _st_label_200 -= 1
        super()._label('critical_section', block=False)
        task()
        super()._label('release', block=False)
        self._state.q.remove(('request', c, self._id))
        self.send(('release', self.logical_clock(), self._id), to=self._state.s)

    def _P_handler_278(self, c2, p):
        self._state.q.add(('request', c2, p))
        self.send(('ack', self.logical_clock(), self._id), to=p)
    _P_handler_278._labels = None
    _P_handler_278._notlabels = None

    def _P_handler_304(self, p):
        for x in {('request', c, p) for (_ConstantPattern321_, c, _BoundPattern324_) in self._state.q if (_ConstantPattern321_ == 'request') if (_BoundPattern324_ == p)}:
            self._state.q.remove(x)
            break
    _P_handler_304._labels = None
    _P_handler_304._notlabels = None

class Node_(da.NodeProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._Node_ReceivedEvent_0 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_Node_ReceivedEvent_0', PatternExpr_454, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[])])

    def run(self):
        nprocs = (int(sys.argv[1]) if (len(sys.argv) > 1) else 10)
        nrequests = (int(sys.argv[2]) if (len(sys.argv) > 2) else 1)
        ps = self.new(P, num=nprocs)
        for p in ps:
            self._setup(p, ((ps - {p}), nrequests))
        self._start(ps)
        super()._label('_st_label_446', block=False)
        p = None

        def UniversalOpExpr_447():
            nonlocal p
            for p in ps:
                if (not PatternExpr_460.match_iter(self._Node_ReceivedEvent_0, _BoundPattern470_=p)):
                    return False
            return True
        _st_label_446 = 0
        while (_st_label_446 == 0):
            _st_label_446 += 1
            if UniversalOpExpr_447():
                _st_label_446 += 1
            else:
                super()._label('_st_label_446', block=True)
                _st_label_446 -= 1
        self.send(('done',), to=ps)
