Example #1
0
 def __init__(self, name=None):
     """
     :param name: Names are like PIDs in real life. They must be a unique string in our system.
     They are converted to an uppercase representation, so, names are NOT case sensitive!
     """
     self.name = self._unique_name() if name is None else name
     self.name = self.name.upper()  # convert names to uppercase!
     self.__workplan = None  # the workplan stores every event in the future
     self.__history = Workplan()  # we store the history here...
Example #2
0
class Process(object):
    def __init__(self, name=None):
        """
        :param name: Names are like PIDs in real life. They must be a unique string in our system.
        They are converted to an uppercase representation, so, names are NOT case sensitive!
        """
        self.name = self._unique_name() if name is None else name
        self.name = self.name.upper()  # convert names to uppercase!
        self.__workplan = None  # the workplan stores every event in the future
        self.__history = Workplan()  # we store the history here...

    @property
    def history(self):
        """
        :returns: Events in the past
        :return: Workplan
        """
        return self.__history

    @property
    def workplan(self):
        """
        get the current workplan
        :return: Workplan. Empty if not initialized
        """
        if self.__workplan is None:
            return Workplan()
        return self.__workplan

    @workplan.setter
    def workplan(self, workplan):
        self.__workplan = workplan

    def doWork(self, time=None):
        """
        tell process to do some work from the workplan
        :param time: how long should the process work?
        If no time is provided, work one TimeSection (plus Action Section)
        :return Section: finished section
        :Raise ProcessTerminatedMessage if process is done!
        """

        try:
            active_section = self.__workplan.pop()  # get section from workplan
        except IndexError:
            # there is no more section in workplan. Process Terminated.
            # we use a clever messaging system to inform the Scheduler as soon as a process terminated.
            raise ProcessTerminatedMessage("Workplan empty - Process terminated!", last_section=self.__history.head())

        new_history_section = deepcopy(active_section)  # create a copy of the section

        if time is None:
            time = active_section.duration  # work till the end of the active section (typically for FiFo)

        worked_time = min(active_section.duration, time)  # calculate time you can spend in section

        # maintain history and workplan
        if active_section.duration - worked_time > 0:
            # add updated section at the first place of the workplan (if time left)
            active_section.duration -= worked_time
            self.workplan.insert(active_section)  # don't touch active_section from now an...

        new_history_section.duration = worked_time  # time spent working...
        new_history_section.ending_at = SystemTimer().timecounter  # injecting a new attribute
        new_history_section.starting_at = SystemTimer().timecounter - worked_time
        self.history.insert(new_history_section, i=len(self.history.plan))  # insert element at the end of the history

        # - decide if we should update system timer here or at the scheduler after call (work).
        # I think we should update system timer here: It's not sure that the work-function is working for the whole time
        # it the workplan says, we work only 10ms, but the scheduler granted a timeslice for 20, we will return after 10
        # to avoid double checks, update system timer here.
        # .......
        # okay, the Scheduler Should be responsible for the ticks
        # SystemTimer().setRelativeTime(worked_time)  # A NEW STEP WAS DONE! NOTIFY EVERYONE!!!!

        # if time left, work again!
        if worked_time < time:
            self.doWork(time - worked_time)
        return new_history_section

    def _unique_name(self):
        """
        helper function to generate a unique name
        """
        return uuid1().urn

    def _random_name(self):
        """
        generate a random name - this is not necessary, but fancy!
        attention! no guarantee to be unique.
        """
        warn(DeprecationWarning)
        randname = []
        charset = ["A", "B", "C", "D", "E", "F"]
        for i in range(4):
            randname.append(choice(charset))
        return "".join(randname)

    def __repr__(self):
        return "<Process %s>" % self.name