Skip to content
Snippets Groups Projects
Commit 40d531b4 authored by shinedday's avatar shinedday
Browse files

Add : scheduler mono threading

parent 18d3b6e4
No related branches found
No related tags found
No related merge requests found
......@@ -5,168 +5,92 @@ from typing import List
import sys
import pathlib
import pickle
from threading import Semaphore, Thread
from time import sleep
from threading import Thread
sys.path.insert(0, str(pathlib.Path(__file__).parent))
from pyAmakCore.classes.amas import Amas
from pyAmakCore.classes.scheduler_tool.schedulable_thread import SchedulableThread
from pyAmakCore.classes.scheduler_tool.amas_thread import AmasThread
from pyAmakCore.classes.thread_tool.schedulable_thread import SchedulableThread
from pyAmakCore.classes.thread_tool.amas_thread import AmasThread
from pyAmakCore.classes.tools.schedulable import Schedulable
from pyAmakCore.classes.scheduler_tool.scheduler_core import SchedulerCore
class Scheduler:
class Scheduler(SchedulerCore):
"""
Scheduler class, to make sure that environment and amas are always sync together
"""
def __init__(self, amas: Amas) -> None:
self.amas: Amas = amas
self.exit_bool: bool = False
self.semaphore_start_stop: Semaphore = Semaphore(0)
SchedulerCore.__init__(self, amas)
self.schedulables: List[SchedulableThread] = []
self.schedulables_threads: List[Thread] = []
self.__schedulables: List[SchedulableThread] = []
self.__schedulables_threads: List[Thread] = []
self.add_schedulables(amas, AmasThread)
self.add_schedulables(amas.get_environment(), SchedulableThread)
self.__add_schedulables(amas, AmasThread)
self.__add_schedulables(amas.get_environment(), SchedulableThread)
self.sleep_time: float = 0
def get_amas(self) -> Amas:
"""
return amas pointer
"""
return self.amas
def add_schedulables(self, schedulable: Schedulable, cls) -> None:
def __add_schedulables(self, schedulable: Schedulable, cls) -> None:
"""
add a schedulable in scheduler
"""
schedulable_thread = cls(schedulable)
self.schedulables.append(schedulable_thread)
self.__schedulables.append(schedulable_thread)
current_thread = Thread(target=schedulable_thread.run)
self.schedulables_threads.append(current_thread)
self.__schedulables_threads.append(current_thread)
current_thread.start()
def wait_schedulables(self) -> None:
def __wait_schedulables(self) -> None:
"""
wait for all schedulable to release a token
"""
for schedulable in self.schedulables:
for schedulable in self.__schedulables:
schedulable.action_done.acquire()
def start_schedulables(self) -> None:
def __start_schedulables(self) -> None:
"""
wait for all schedulable to release a token
"""
for schedulable in self.schedulables:
for schedulable in self.__schedulables:
schedulable.is_waiting.release()
def first_part(self) -> None:
"""
first part of a cycle
"""
self.start_schedulables()
self.__start_schedulables()
# on cycle begin
self.wait_schedulables()
self.__wait_schedulables()
def main_part(self) -> None:
"""
main part of a cycle
"""
self.start_schedulables()
self.__start_schedulables()
# agent cycle
self.wait_schedulables()
self.__wait_schedulables()
def last_part(self) -> None:
"""
last part of a cycle
"""
self.start_schedulables()
self.__start_schedulables()
# on cycle end
self.wait_schedulables()
self.__wait_schedulables()
def run(self) -> None:
"""
main part of amak core
override super run to close child thread before stopping
"""
while not self.exit_bool:
print("Cycle : ", self.amas.get_cycle())
self.semaphore_start_stop.acquire()
if self.exit_bool:
break
self.semaphore_start_stop.release()
self.first_part()
self.main_part()
self.last_part()
super().run()
self.__close_child()
sleep(self.sleep_time)
self.close_child()
def close_child(self) -> None:
def __close_child(self) -> None:
"""
tell all child to shut down
"""
for schedulable in self.schedulables:
for schedulable in self.__schedulables:
schedulable.exit_bool = True
schedulable.is_waiting.release()
for thread in self.schedulables_threads:
for thread in self.__schedulables_threads:
thread.join(0)
"""
program interface
"""
def exit_program(self) -> None:
"""
Exit the system as soon as possible
"""
self.exit_bool = True
self.semaphore_start_stop.release()
def start(self) -> None:
"""
Unlock the scheduler
"""
self.semaphore_start_stop.release()
def stop(self) -> None:
"""
Lock the scheduler
"""
self.semaphore_start_stop.acquire()
def set_sleep(self, sleep_time: int) -> None:
"""
Set sleep value between 2 cycles
"""
self.sleep_time = sleep_time
"""
load & save program
"""
def save(self) -> None:
"""
Save the current state of the system
"""
with open('filename.pickle', 'wb') as handle:
pickle.dump(self.amas, handle, protocol=pickle.HIGHEST_PROTOCOL)
@classmethod
def load(cls) -> 'Scheduler':
"""
Load the last save of the system
"""
with open('filename.pickle', 'rb') as handle:
amas_object = pickle.load(handle)
return cls(amas_object)
"""
SchedulerMono class
"""
from random import shuffle
from typing import List
import sys
import pathlib
sys.path.insert(0, str(pathlib.Path(__file__).parent))
from pyAmakCore.classes.scheduler_tool.scheduler_core import SchedulerCore
from pyAmakCore.classes.amas import Amas
from pyAmakCore.classes.agent import Agent
from pyAmakCore.classes.tools.schedulable import Schedulable
from pyAmakCore.classes.communicating_agent import CommunicatingAgent
from pyAmakCore.enumeration.executionPolicy import ExecutionPolicy
class SchedulerMono(SchedulerCore):
"""
Scheduler class, without threading
"""
def __init__(self, amas: Amas) -> None:
SchedulerCore.__init__(self, amas)
self.schedulables: List[Schedulable] = []
self.schedulables.append(self.amas)
self.amas.add_pending_agent()
self.schedulables.append(self.amas.get_environment())
def first_part(self) -> None:
"""
first part of a cycle
"""
self.amas.add_pending_agent()
for schedulable in self.schedulables:
schedulable.on_cycle_begin()
def main_part(self) -> None:
"""
main part of a cycle
"""
def phase1(current_agent: Agent) -> None:
"""
this is the first phase of a cycle
"""
current_agent.next_phase()
current_agent.on_cycle_begin()
if isinstance(current_agent, CommunicatingAgent):
current_agent.read_mails()
current_agent.on_perceive()
current_agent.set_criticality(current_agent.compute_criticality())
current_agent.next_phase()
def phase2(current_agent: Agent) -> None:
"""
this is the second phase of a cycle
"""
current_agent.next_phase()
current_agent.on_decide()
current_agent.on_act()
current_agent.set_criticality(current_agent.compute_criticality())
current_agent.next_phase()
current_agent.on_cycle_end()
agents: List[Agent] = self.amas.get_agents()
if self.amas.get_execution_policy() == ExecutionPolicy.ONE_PHASE:
shuffle(agents)
for agent in agents:
phase1(agent)
phase2(agent)
else:
shuffle(agents)
for agent in agents:
phase1(agent)
shuffle(agents)
for agent in agents:
phase2(agent)
def last_part(self) -> None:
"""
last part of a cycle
"""
for schedulable in self.schedulables:
schedulable.on_cycle_end()
self.amas.remove_pending_agent()
self.amas.to_csv(self.amas.get_cycle(), self.amas.get_agents())
for schedulable in self.schedulables:
schedulable.cycle()
"""
class Callable
"""
from threading import Semaphore
class Callable:
"""
Class that implement useful method to interact with the program
"""
def __init__(self) -> None:
self.exit_bool: bool = False
self.sleep_time: float = 0
self.semaphore_start_stop: Semaphore = Semaphore(0)
def exit_program(self) -> None:
"""
Exit the system as soon as possible
"""
self.exit_bool = True
self.semaphore_start_stop.release()
def start(self) -> None:
"""
Unlock the scheduler
"""
self.semaphore_start_stop.release()
def stop(self) -> None:
"""
Lock the scheduler
"""
self.semaphore_start_stop.acquire()
def set_sleep(self, sleep_time: int) -> None:
"""
Set sleep value between 2 cycles
"""
self.sleep_time = sleep_time
"""
Savable Class
"""
import pickle
import sys
import pathlib
sys.path.insert(0, str(pathlib.Path(__file__).parent))
from pyAmakCore.classes.amas import Amas
class Savable:
"""
Class that implement convenient method to save and load an amas
"""
def __init__(self, amas: Amas) -> None:
self.amas = amas
def get_amas(self):
"""
return amas
"""
return self.amas
def save(self) -> None:
"""
Save the current state of the system
"""
with open('filename.pickle', 'wb') as handle:
pickle.dump(self.amas, handle, protocol=pickle.HIGHEST_PROTOCOL)
@classmethod
def load(cls) -> 'Savable':
"""
Load the last save of the system
"""
with open('filename.pickle', 'rb') as handle:
amas_object = pickle.load(handle)
return cls(amas_object)
\ No newline at end of file
"""
Scheduler class
"""
from time import sleep
import sys
import pathlib
sys.path.insert(0, str(pathlib.Path(__file__).parent))
from pyAmakCore.classes.scheduler_tool.callable import Callable
from pyAmakCore.classes.scheduler_tool.savable import Savable
from pyAmakCore.classes.amas import Amas
class SchedulerCore(Callable, Savable):
"""
Core part of Scheduler
"""
def __init__(self, amas: Amas) -> None:
Callable.__init__(self)
Savable.__init__(self, amas)
def first_part(self) -> None:
"""
first part of a cycle
"""
def main_part(self) -> None:
"""
main part of a cycle
"""
def last_part(self) -> None:
"""
last part of a cycle
"""
def run(self) -> None:
"""
main part of amak core
"""
while not self.exit_bool:
print("Cycle : ", self.amas.get_cycle())
self.semaphore_start_stop.acquire()
if self.exit_bool:
break
self.semaphore_start_stop.release()
self.first_part()
self.main_part()
self.last_part()
sleep(self.sleep_time)
......@@ -11,10 +11,10 @@ import pathlib
sys.path.insert(0, str(pathlib.Path(__file__).parent.parent))
from pyAmakCore.enumeration.executionPolicy import ExecutionPolicy
from pyAmakCore.classes.scheduler_tool.agent_thread import AgentThread
from pyAmakCore.classes.thread_tool.agent_thread import AgentThread
from pyAmakCore.classes.amas import Amas
from pyAmakCore.classes.agent import Agent
from pyAmakCore.classes.scheduler_tool.schedulable_thread import SchedulableThread
from pyAmakCore.classes.thread_tool.schedulable_thread import SchedulableThread
class AmasThread(SchedulableThread):
......
"""
Scheduler class that need to be used for pyAmakIhm
"""
import pathlib
import sys
sys.path.insert(0, str(pathlib.Path(__file__).parent.parent))
from pyAmakCore.classes.amas import Amas
from pyAmakCore.classes.scheduler_mono_threading import SchedulerMono
class SchedulerMonoIHM(SchedulerMono):
"""
Convenient class to override while using pyAmakIHM
"""
def __init__(self, amas: Amas):
self.__observer = None
super().__init__(amas)
def last_part(self) -> None:
super().last_part()
self.__observer.updateCycle()
def attach(self, observer: 'Controleur') -> None:
"""
set observer pointer to observer
"""
self.__observer = observer
from pyAmakCore.classes.scheduler_mono_threading import SchedulerMono
from pyAmakCore.exception.override import ToOverrideWarning
from pyAmakCore.classes.agent import Agent
from pyAmakCore.classes.amas import Amas
......@@ -11,7 +13,8 @@ class SimpleAgent(Agent):
class SimpleAmas(Amas):
def on_initialization(self) -> None:
self.set_do_log(True)
# self.set_do_log(True)
pass
def on_initial_agents_creation(self) -> None:
for i in range(10):
......@@ -27,7 +30,8 @@ ToOverrideWarning.enable_warning(False)
env = SimpleEnv()
amas = SimpleAmas(env)
scheduler = Scheduler(amas)
#scheduler = Scheduler(amas)
scheduler = SchedulerMono(amas)
scheduler.start()
scheduler.run()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment