# -*- generated by 1.0.2 -*-
import da
PatternExpr_238 = da.pat.TuplePattern([da.pat.ConstantPattern('ack'), da.pat.FreePattern('c2'), da.pat.BoundPattern('_BoundPattern242_')])
PatternExpr_281 = da.pat.TuplePattern([da.pat.ConstantPattern('request'), da.pat.FreePattern('c2'), da.pat.FreePattern('p')])
PatternExpr_306 = da.pat.TuplePattern([da.pat.ConstantPattern('release'), da.pat.FreePattern(None), da.pat.FreePattern('p')])
PatternExpr_370 = da.pat.TuplePattern([da.pat.ConstantPattern('done')])
PatternExpr_375 = da.pat.BoundPattern('_BoundPattern377_')
PatternExpr_378 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern384_')]), da.pat.TuplePattern([da.pat.ConstantPattern('done')])])
PatternExpr_470 = da.pat.TuplePattern([da.pat.ConstantPattern('done'), da.pat.BoundPattern('_BoundPattern473_')])
PatternExpr_476 = 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('_BoundPattern486_')])])
_config_object = {}
import sys
da.import_da('da.lib.laclock')
from da.lib.laclock import LamportClock

class P(LamportClock, 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_238, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_1', PatternExpr_281, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_280]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_2', PatternExpr_306, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_305]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_3', PatternExpr_370, sources=[PatternExpr_375], destinations=None, timestamps=None, record_history=True, handlers=[])])

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

    def run(self):
        self.output('My name is', self.nameof(self._id))

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

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

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

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

                def ExistentialOpExpr_236(p):
                    nonlocal c2
                    for (_, _, (_ConstantPattern253_, c2, _BoundPattern256_)) in self._PReceivedEvent_0:
                        if (_ConstantPattern253_ == 'ack'):
                            if (_BoundPattern256_ == p):
                                if (c2 > c):
                                    return True
                    return False
                if (not ExistentialOpExpr_236(p=p)):
                    return False
            return True
        _st_label_203 = 0
        while (_st_label_203 == 0):
            _st_label_203 += 1
            if (UniversalOpExpr_205() and UniversalOpExpr_231()):
                _st_label_203 += 1
            else:
                super()._label('_st_label_203', block=True)
                _st_label_203 -= 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), self._state.s)

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

    def _P_handler_305(self, p):
        for x in {('request', c, p) for (_ConstantPattern322_, c, _BoundPattern325_) in self._state.q if (_ConstantPattern322_ == 'request') if (_BoundPattern325_ == p)}:
            self._state.q.remove(x)
            break
    _P_handler_305._labels = None
    _P_handler_305._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_470, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[])])
    _config_object = {'channel': 'fifo', 'clock': 'lamport'}

    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)
        if (not (self.nameof(self._id) == 'aaa')):
            ps = self.new(P, num=nprocs)
            for p in ps:
                self._setup(p, ((ps - {p}), nrequests))
            self._start(ps)
            self.output('ps started')
            super()._label('_st_label_462', block=False)
            p = None

            def UniversalOpExpr_463():
                nonlocal p
                for p in ps:
                    if (not PatternExpr_476.match_iter(self._Node_ReceivedEvent_0, _BoundPattern486_=p)):
                        return False
                return True
            _st_label_462 = 0
            self._timer_start()
            while (_st_label_462 == 0):
                _st_label_462 += 1
                if UniversalOpExpr_463():
                    _st_label_462 += 1
                elif self._timer_expired:
                    _st_label_462 += 1
                else:
                    super()._label('_st_label_462', block=True, timeout=5)
                    _st_label_462 -= 1
            self.end(ps)
        else:
            super()._label('_st_label_492', block=False)
            _st_label_492 = 0
            while (_st_label_492 == 0):
                _st_label_492 += 1
                if False:
                    _st_label_492 += 1
                else:
                    super()._label('_st_label_492', block=True)
                    _st_label_492 -= 1
