def __init__(self, priority=False, monitorQ=False, \ unitName="packet", capacity="unbounded", \ initialBuffered=None, **kwargs): """Constructor. :param priority: Boolean; if True, use priority queueing. :param monitorQ: Boolean; if True, support `enQ`, `deQ`, and `drp`. :param unitName: Description of units stored in `Queue`. :param capacity: Capacity of underlying Store [default='unbounded']. :param initialBuffered: Initialize list of buffered objects. :param kwargs: Keywords passed to `Traceable` constructors. """ # check that initialBuffered is properly formatted if initialBuffered and priority: isPrio = all([isinstance(s,tuple) for s in initialBuffered] ) if not isPrio: initialBuffered = [(p, 0) for p in initialBuffered] # call constructors Store.__init__(self, unitName=unitName, capacity=capacity, \ initialBuffered=initialBuffered, \ putQType=PriorityQ, getQType=PriorityQ) Traceable.__init__(self, **kwargs) # set other parameters self.tracename = self.tracename + "%d"%(self.uid) self.__priority = priority self.monitorQ = monitorQ self.enQ = SimEvent(name=self.name+".enQ") self.deQ = SimEvent(name=self.name+".deQ") self.drp = SimEvent(name=self.name+".drp") self.__dummy = SimEvent(name=self.name+".dummy") # set up Queue for priority if self.priority: self.theBuffer = _PriorityList(self.theBuffer) self.addSort(None) # setup addSort for priority queueing
def _put(self, arg): """Overload `SimPy` `Store._put()` method.""" nevents = len(self.sim._timestamps) if self.verbose>QUEUE_HIGH_VERBOSE or self.monitorQ: # get objects to request reqput = [] reqput += [self._buffer_object(p) for p in arg[0][3] ] # run _put prethebuff = self.__copy_theBuffer() preget = self.__copy_getQ() preputbuff = self.__copy_putQ(True) reqput += [p for p in preputbuff] rval = Store._put(self, arg) postthebuff = self.__copy_theBuffer() postget = self.__copy_getQ() postputbuff = self.__copy_putQ(True) # perform checks getbuff = [] for proc in [p for p in preget if (p not in postget)]: getbuff += [a for a in proc.got] putbuff = [a for a in reqput if \ ((a in postthebuff) or (a in getbuff) ) ] drpbuff = [a for a in reqput if \ ((a not in putbuff) and (a not in postputbuff) ) ] #self.log("logput") self.__log_all({'get': getbuff, \ 'put': putbuff, \ 'drp': drpbuff} ) else: rval = Store._put(self, arg) # fudge event queue to "de-prior" put event numnew = len(self.sim._timestamps) - nevents if (0<numnew): # process put p = heapq.nsmallest(1, [x for x in self.sim._timestamps if (x[0]==self.sim._t)]) putevt = p[0] pt = putevt[0] psortpr = putevt[1] assert (pt==self.sim._t), "[QUEUE]: _put(), put(at, sim._t) = (%s, %s)"%(pt, self.sim._t) assert (psortpr==self.sim._sortpr) if 1<numnew: glargest = heapq.nlargest(numnew-1, [x for x in self.sim._timestamps if (x[0]==self.sim._t)]) for k in range(numnew-1): g, krev = glargest[k], (numnew-2-k) # process put with get commands getevt, gt, gsortpr = g, g[0], g[1] assert (gt==self.sim._t), "[QUEUE]: _put(), get(at, sim._t) = (%s, %s)"%(gt, self.sim._t) assert (abs(psortpr+krev+1)==abs(gsortpr)), "getpr = %s, putpr = %s"%(p, g) # set new get pointer and make non-prior getevt[0] = gt + const.EPSILON getevt[1] = abs(gsortpr) + 1 putevt[1] = abs(psortpr) - (numnew - 1) else: assert False, "[QUEUE]: _put found unexpected number of events!" return rval
def addSort(self, sortFunc): """ Overload `Store.addSort()` for priority queueing. :param sortFunc: Sort method to reorder objects. `sortFunc` should take two arguments, namely `Queue` and a list containing the objects currently buffered by the `Queue`. When operating in `priority` mode, `sortFunc` will receive a priority buffer. That is a list containing 2-tuples of (*object*, *prioritylevel*). """ return Store.addSort(self, \ lambda me, buff: me.__callsort(sortFunc, buff) )
def _get(self, arg): """Overload `SimPy` `Store._get()` method.""" if self.verbose>QUEUE_HIGH_VERBOSE or self.monitorQ: # run _get prethebuff = self.__copy_theBuffer() preputbuff = self.__copy_putQ(True) rval = Store._get(self, arg) postthebuff = self.__copy_theBuffer() postputbuff = self.__copy_putQ(True) # perform checks obj = arg[1] getbuff = obj.got putbuff = [a for a in preputbuff if \ ((a in postthebuff) or (a in getbuff)) ] drpbuff = [a for a in preputbuff if \ ((a not in postputbuff) and (a not in postthebuff) ) ] #self.log("logget") self.__log_all({'get': getbuff, \ 'put': putbuff, \ 'drp': drpbuff} ) else: rval = Store._get(self, arg) return rval
(now(), [x.weight for x in self.got])) yield hold, self, 11 class Widget(Lister): def __init__(self, weight=0): self.weight = weight widgbuf = [] for i in range(10): widgbuf.append(Widget(5)) initialize() buf = Store(capacity=11, initialBuffered=widgbuf, monitored=True) for i in range(3): # define and activate 3 producer objects p = ProducerD() activate(p, p.produce()) for i in range(3): # define and activate 3 consumer objects c = ConsumerD() activate(c, c.consume()) simulate(until=50) print('LenBuffer: %s' % buf.bufferMon) # length of buffer print('getQ: %s' % buf.getQMon) # length of getQ print('putQ %s' % buf.putQMon) # length of putQ
print('%s car %s done by %s' % (now(), self.name, whichWash)) class CarGenerator(Process): def generate(self): i = 0 while True: yield hold, self, 2 c = Car('%d' % i) activate(c, c.lifecycle()) i += 1 washtime = 5 initialize() # put four cars into the queue of waiting cars for j in range(1, 5): c = Car(name='%d' % -j) activate(c, c.lifecycle()) waitingCars = Store(capacity=40) for i in range(2): cw = Carwash('Carwash %s' % i) activate(cw, cw.lifecycle()) cg = CarGenerator() activate(cg, cg.generate()) simulate(until=30) print('waitingCars %s' % [x.name for x in waitingCars.theBuffer])