1 from argparse import ArgumentParser
2 from dataclasses import dataclass
5 from simgrid import Actor, Engine, Host, Mutex, this_actor
8 def create_parser() -> ArgumentParser:
9 parser = ArgumentParser()
14 help='path to the platform description'
20 help='number of workers to start'
23 '--trials-before-success',
26 help='number of attempts each workers need to make before getting the correct answer'
27 ' (i.e. number of simulated failures)'
37 class CalculationError(RuntimeError):
38 """ Fake calculation error
43 def worker_context_manager(mutex: Mutex, trials_before_success: int, result: ResultHolder):
44 """ Worker that uses a context manager to acquire/release the shared mutex
45 :param mutex: Shared mutex that guards read/write access to the shared result
46 :param trials_before_success: Number of simulated calculation failures before success
47 :param result: Shared result which will be updated by the worker
49 this_actor.info(f"I just started")
50 for trial in range(trials_before_success + 1):
53 this_actor.info(f"acquired the mutex with context manager")
54 this_actor.sleep_for(1)
55 if trial < trials_before_success:
56 raise CalculationError("did not manage to find the correct answer")
58 this_actor.info(f"updated shared result, which is now {result.value}")
59 except CalculationError as e:
60 this_actor.warning(f"ran in trouble while calculating: {e}. Will retry shortly.")
62 this_actor.info(f"released the mutex after leaving the context manager")
63 this_actor.info("Bye now!")
66 def worker(mutex: Mutex, trials_before_success: int, result: ResultHolder):
67 """ Worker that manually acquires/releases the shared mutex
68 :param mutex: Shared mutex that guards read/write access to the shared result
69 :param trials_before_success: Number of simulated calculation failures before success
70 :param result: Shared result which will be updated by the worker
72 this_actor.info(f"I just started")
73 for trial in range(trials_before_success + 1):
76 this_actor.info(f"acquired the mutex manually")
77 this_actor.sleep_for(1)
78 if trial < trials_before_success:
79 raise CalculationError("did not manage to find the correct answer")
81 this_actor.info(f"updated shared result, which is now {result.value}")
82 except CalculationError as e:
83 this_actor.warning(f"ran in trouble while calculating: {e}. Will retry shortly.")
85 this_actor.info(f"released the mutex manually")
87 this_actor.info("Bye now!")
91 """ Spawns `--workers` workers and wait until they have all updated the shared result, then displays it before
92 leaving. Alternatively spawns `worker_context_manager()` and `worker()` workers.
93 :param settings: Simulation settings
95 result = ResultHolder(value=0)
98 for i in range(settings.workers):
99 use_worker_context_manager = i % 2 == 0
102 f"worker-{i}(mgr)" if use_worker_context_manager else f"worker-{i}",
103 Host.by_name("Jupiter" if use_worker_context_manager else "Tremblay"),
104 worker_context_manager if use_worker_context_manager else worker,
106 settings.trials_before_success,
110 [actor.join() for actor in actors]
111 this_actor.info(f"The final result is: {result.value}")
115 settings = create_parser().parse_known_args()[0]
117 e.load_platform(settings.platform)
118 Actor.create("master", Host.by_name("Tremblay"), master, settings)
122 if __name__ == "__main__":