Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Use normal strings instead of f-strings (Sonar).
[simgrid.git] / examples / python / synchro-mutex / synchro-mutex.py
index 4e4a886..1a202ba 100644 (file)
@@ -1,3 +1,8 @@
+# Copyright (c) 2010-2023. The SimGrid Team. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the license (GNU LGPL) which comes with this package.
+
 from argparse import ArgumentParser
 from dataclasses import dataclass
 import sys
@@ -14,10 +19,10 @@ def create_parser() -> ArgumentParser:
         help='path to the platform description'
     )
     parser.add_argument(
-        '--workers',
+        '--actors',
         type=int,
         default=6,
-        help='number of workers to start'
+        help='how many pairs of actors should be started'
     )
     return parser
 
@@ -28,64 +33,41 @@ class ResultHolder:
 
 
 def worker_context_manager(mutex: Mutex, result: ResultHolder):
-    """ Worker that uses a context manager to acquire/release the shared mutex
-    :param mutex: Shared mutex that guards read/write access to the shared result
-    :param result: Shared result which will be updated by the worker
-    """
-    this_actor.info(f"I just started")
+    # When using a context manager, the lock and the unlock are automatic. This is the easiest approach
     with mutex:
-        this_actor.info(f"acquired the mutex with context manager")
+        this_actor.info("Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager")
         result.value += 1
-        this_actor.info(f"updated shared result, which is now {result.value}")
-    this_actor.info(f"released the mutex after leaving the context manager")
-    this_actor.info("Bye now!")
+    this_actor.info("I'm done, good bye")
 
 
 def worker(mutex: Mutex, result: ResultHolder):
-    """ Worker that manually acquires/releases the shared mutex
-    :param mutex: Shared mutex that guards read/write access to the shared result
-    :param result: Shared result which will be updated by the worker
-    """
-    this_actor.info(f"I just started")
+    # If you lock your mutex manually, you also have to unlock it.
+    # Beware of exceptions preventing your unlock() from being executed!
     mutex.lock()
-    this_actor.info(f"acquired the mutex manually")
+    this_actor.info("Hello simgrid, I'm ready to compute after a regular lock")
     result.value += 1
-    this_actor.info(f"updated shared result, which is now {result.value}")
     mutex.unlock()
-    this_actor.info(f"released the mutex manually")
-    this_actor.info("Bye now!")
-
-
-def master(settings):
-    """ Spawns `--workers` workers and wait until they have all updated the shared result, then displays it before
-        leaving. Alternatively spawns `worker_context_manager()` and `worker()` workers.
-    :param settings: Simulation settings
-    """
-    result = ResultHolder(value=0)
-    mutex = Mutex()
-    actors = []
-    for i in range(settings.workers):
-        use_worker_context_manager = i % 2 == 0
-        actors.append(
-            Actor.create(
-                f"worker-{i}(mgr)" if use_worker_context_manager else f"worker-{i}",
-                Host.by_name("Jupiter" if use_worker_context_manager else "Tremblay"),
-                worker_context_manager if use_worker_context_manager else worker,
-                mutex,
-                result
-            )
-        )
-    this_actor.sleep_for(10)
-    this_actor.info(f"The final result is: {result.value}")
+    this_actor.info("I'm done, good bye")
+
 
 
 def main():
     settings = create_parser().parse_known_args()[0]
     e = Engine(sys.argv)
     e.load_platform(settings.platform)
-    Actor.create("master", Host.by_name("Tremblay"), master, settings)
+
+    # Create the requested amount of actors pairs. Each pair has a specific mutex and cell in `result`
+    results = [ResultHolder(value=0) for _ in range(settings.actors)]
+    for i in range(settings.actors):
+        mutex = Mutex()
+        Actor.create(f"worker-{i}(mgr)", Host.by_name("Jupiter"), worker_context_manager, mutex, results[i])
+        Actor.create(f"worker-{i}", Host.by_name("Tremblay"), worker, mutex, results[i])
+
     e.run()
 
+    for i in range(settings.actors):
+        this_actor.info(f"Result[{i}] -> {results[i].value}")
+
 
 if __name__ == "__main__":
     main()