def read(self): if self._read_ev is not None: raise RuntimeError('Already reading') event = self._read_ev = Event(self.env) if self._read_buf: self._read_data(Event(self.env).succeed(b'')) else: self.socket.read(self.blocksize).callbacks.append(self._read_data) return event
def recv(self): if self._in_queue is None: raise self.reader.value # Enqueue reads if there are no pending incoming messages. if not self._in_queue: if self._recv_ev is not None: raise RuntimeError('Concurrent receive attempt') self._recv_ev = Event(self.env) return self._recv_ev return Event(self.env).succeed(self._in_queue.pop(0))
def _write_outgoing(self): """Pulls data from :attr:`outgoing` and pushes it to the peer.""" while True: if len(self.outgoing) == 0: if self._outgoing_error is None: self._outgoing_avail = Event(self.env) yield self._outgoing_avail data = self.outgoing[:self.max_segment_size] frame = Frame(self, data) yield self.env.timeout(self._latency()) if self._peer._frame_transmission: # Inform peer of the frame and wait for the acknowledgement. self._peer._frame_transmission.succeed(frame) sent = yield frame else: # Peer has closed the connection sent = 0 self._outgoing_error = errno.EPIPE if not frame.data: # The close frame has been sent. break self.outgoing = self.outgoing[sent:] if self._writer: self._try_write()
def event(self) -> Event: """Return a new :class:`~simpy.events.Event` instance. Yielding this event suspends a process until another process triggers the event. """ return Event(self)
def run(self, until=None): """Executes :meth:`step()` until the given criterion *until* is met. - If it is ``None`` (which is the default) this method will return if there are no further events to be processed. - If it is an :class:`~simpy.events.Event` the method will continue stepping until this event has been triggered and will return its value. - If it can be converted to a number the method will continue stepping until the environment's time reaches *until*. """ if until is None: until = Event(self) elif not isinstance(until, Event): at = float(until) if at <= self.now: raise ValueError('until(=%s) should be > the current ' 'simulation time.' % at) # Schedule the event with before all regular timeouts. until = Event(self) until.ok = True until._value = None self.schedule(until, URGENT, at - self.now) until.callbacks.append(_stop_simulate) try: while True: self.step() except EmptySchedule: pass if not until.triggered: return None if not until.ok: raise until.value return until.value
def run(self, until: Optional[Union[SimTime, Event]] = None) -> Optional[Any]: """Executes :meth:`step()` until the given criterion *until* is met. - If it is ``None`` (which is the default), this method will return when there are no further events to be processed. - If it is an :class:`~simpy.events.Event`, the method will continue stepping until this event has been triggered and will return its value. Raises a :exc:`RuntimeError` if there are no further events to be processed and the *until* event was not triggered. - If it is a number, the method will continue stepping until the environment's time reaches *until*. """ if until is not None: if not isinstance(until, Event): # Assume that *until* is a number if it is not None and # not an event. Create a Timeout(until) in this case. at: SimTime if isinstance(until, int): at = until else: at = float(until) if at <= self.now: raise ValueError( f'until(={at}) must be > the current simulation time.') # Schedule the event before all regular timeouts. until = Event(self) until._ok = True until._value = None self.schedule(until, URGENT, at - self.now) elif until.callbacks is None: # Until event has already been processed. return until.value until.callbacks.append(StopSimulation.callback) try: while True: self.step() except StopSimulation as exc: return exc.args[0] # == until.value except EmptySchedule: if until is not None: assert not until.triggered raise RuntimeError( f'No scheduled events left but "until" event was not ' f'triggered: {until}') return None
def _writer(self): env = self.env try: while True: if not self._out_queue: self._send_ev = Event(self.env) yield self._send_ev yield self.socket.write(self._out_queue.pop(0)) except BaseException as e: self._handle_error(self.writer, e)
def __init__(self, env, arrival_time, eid): self.eid = eid # start_event = env.timeout(arrival_time) start_event = env.timeout(0) xor1_yes = Event(env) xor1_no = Event(env) end_act_A = env.process( act_A(env, start_event, dur_A(self), self.eid)) end_act_B = env.process( act_B(env, end_act_A, dur_B(self), self.eid)) end_act_B.callbacks.append(xor1(xor1_yes, xor1_no)) end_act_C = env.process(act_C(env, xor1_yes, dur_C(self), self.eid)) end_act_D = env.process( act_D(env, end_act_C, dur_D(self), self.eid)) end_act_E = env.process(act_E(env, xor1_no, dur_E(self), self.eid)) end_act_F = env.process( act_F(env, AnyOf(env, [end_act_D, end_act_E]), dur_F(self), self.eid)) env.process(act_G(env, end_act_F, dur_G(self), self.eid))
def _read_incoming(self): """Pushes remote data frames into :attr:`incoming`.""" self._frame_transmission = Event(self.env) while True: if self._reader: self._try_read() if self._incoming_error is not None: break # Wait until there is room for incoming data. if len(self.incoming) >= self.max_buffer_size: self._incoming_avail = Event(self.env) yield self._incoming_avail continue frame = yield self._frame_transmission self._frame_transmission = Event(self.env) if frame is None: # A local close will end the frame transmission with None. continue if frame.data: read = min(self.max_buffer_size - len(self.incoming), len(frame.data)) self.incoming += frame.data[:read] # Simulate transmission of the frame acknowledgement. yield self.env.timeout(self._latency()) frame.succeed(read) else: # An empty frame has been received, this means the remote side # has closed the connection. self._incoming_error = errno.ECONNRESET self.env._unregister(self) frame.succeed() self._frame_transmission = None
def run(self, until=None): """Executes :meth:`step()` until the given criterion *until* is met. - If it is ``None`` (which is the default), this method will return when there are no further events to be processed. - If it is an :class:`~simpy.events.Event`, the method will continue stepping until this event has been triggered and will return its value. Raises a :exc:`RuntimeError` if there are no further events to be processed and the *until* event was not triggered. - If it is a number, the method will continue stepping until the environment's time reaches *until*. """ if until is not None: if not isinstance(until, Event): # Assume that *until* is a number if it is not None and # not an event. Create a Timeout(until) in this case. at = float(until) if at <= self.now: raise ValueError('until(=%s) should be > the current ' 'simulation time.' % at) # Schedule the event with before all regular timeouts. until = Event(self) until.ok = True until._value = None self.schedule(until, URGENT, at - self.now) elif until.callbacks is None: # Until event has already been processed. return until.value until.callbacks.append(StopSimulation.callback) try: while True: self.step() except StopSimulation as exc: return exc.args[0] # == until.value except EmptySchedule: if until is not None: # @ FIXED ASSERTION ERROR try: not until.triggered except: pass raise RuntimeError('No scheduled events left but "until" ' 'event was not triggered: %s' % until)
def write(self, packet): if self._write_ev is not None: raise RuntimeError('Already writing') if self.encode is not None: packet = self.encode(packet) if len(packet) > self.max_packet_size: raise ValueError('Packet too large. Allowed %d bytes but ' 'got %d bytes' % (self.max_packet_size, len(packet))) self._write_ev = Event(self.env) self._write_buf = Header.pack(len(packet)) + packet self.socket.write(self._write_buf).callbacks.append(self._write_data) return self._write_ev
def networkInHandler(self, cmd): if isinstance(cmd, Message): if cmd.type is StackMessageTypes.RECEIVE: logger.debug("%s: Entering receive mode.", self) # start receiving self._receiveCmd = cmd # set _receiving and a timeout event self._receiving = True self._receiveTimeout = SimMan.timeout(cmd.args["duration"]) self._receiveTimeout.callbacks.append( self._receiveTimeoutCallback) elif isinstance(cmd, Packet): payload = cmd packet = Packet( SimpleMacHeader(self.addr, payload.header.destMAC, flag=0), payload) self._packetQueue.append(packet) self._packetAddedEvent.succeed() self._packetAddedEvent = Event(SimMan.env)
def __init__(self, name: str, device: Device, frequencyBandSpec: FrequencyBandSpec, addr: bytes): """ Args: name: The layer's name device: The device that operates the SimpleMac layer addr: The 6-byte-long MAC address to be assigned to this MAC layer """ super(SimpleMac, self).__init__(name, owner=device) self._addPort("phy") self._addPort("network") self.addr = addr self._packetQueue = deque(maxlen=100) # allow 100 packets to be queued self._packetAddedEvent = Event(SimMan.env) self._mcs = BpskMcs(frequencyBandSpec) self._transmissionPower = 0.0 # dBm self._receiving = False self._receiveCmd = None self._receiveTimeout = None logger.debug("Initialization completed, MAC address: %s", self.addr, sender=self)
def event(self): """ Creates and returns a new :class:`~simpy.events.Event` object belonging to the current environment. """ return Event(self.env)
""" 一次等待多个事件.py: 有时候,你想同时等待多个事件。例如,您可能需要等待资源,但不是无限次的。或者你可能要等到所有的一系列事件发生。 因此SimPy中提供了AnyOf与AllOf事件,都是一个Condition事件。 两者都以事件列表作为参数,如果它们中的至少一个或全部被触发,则被触发。 """ import simpy from simpy.events import AnyOf, AllOf, Event env = simpy.Environment() events = [Event(env) for i in range(3)] a = AnyOf(env, events) # Triggers if at least one of "events" is triggered. b = AllOf(env, events) # Triggers if all each of "events" is triggered. # ''' def test_condition(env): t1, t2 = env.timeout(1, value='spam'), env.timeout(2, value='eggs') ret = yield t1 | t2 assert ret == {t1: 'spam'} t1, t2 = env.timeout(1, value='spam'), env.timeout(2, value='eggs') ret = yield t1 & t2 assert ret == {t1: 'spam', t2: 'eggs'} # You can also concatenate & and |
def __init__(self, type: Enum, args: Dict[str, Any] = None): self.type = type self.args = args self.eProcessed = Event(SimMan.env)
def schedule(self, delay): evt = Event(self.env) evt.callbacks.append(self.observe) evt._ok = True self.env.schedule(evt, priority=2, delay=delay)