communications between same source and destination inside the ptask).
- Parameters:
- "--cfg=host/model:ptask_BMF": enable the model.
- - "--cfg=bmf/max-iterations: <N>": maximum number of iterations performed
+ - "--cfg=bmf/max-iterations: <N>": maximum number of iterations performed
by BMF solver (default: 1000).
- "--cfg=bmf/selective-update:<true/false>": enable/disable the
selective-update optimization. Only invalidates and recomputes modified
- This model requires Eigen3 library. Make sure Eigen3 is installed to use BMF.
General:
- - Modifications of the Profile mechanism, with some impact on users
+ - Modifications of the Profile mechanism, with some impact on users
- Addition of a new (S4U) method to init profiles from generic functions to improve versatility
- - Fix initial behaviour of state_profiles
+ - Fix initial behaviour of state_profiles
- Modify periodicity to behave like a period, and not like a loop delay
XBT:
- Comm.wait_all_for() [example: examples/python/comm-waitallfor/]
- Mutex [example: examples/python/synchro-mutex/]
- Barrier [example: examples/python/synchro-barrier/]
+ - Semaphore [example: examples/python/synchro-semaphore/]
Build System:
- Remove target "make uninstall" which was incomplete and no longer maintained.
include examples/python/synchro-barrier/synchro-barrier.tesh
include examples/python/synchro-mutex/synchro-mutex.py
include examples/python/synchro-mutex/synchro-mutex.tesh
+include examples/python/synchro-semaphore/synchro-semaphore.py
+include examples/python/synchro-semaphore/synchro-semaphore.tesh
include examples/smpi/NAS/DGraph.c
include examples/smpi/NAS/DGraph.h
include examples/smpi/NAS/README.install
# Access shared resource ...
pass
+ .. automethod:: simgrid.Mutex.__init__
+
.. group-tab:: C
.. code-block:: C
.. group-tab:: Python
- .. automethod:: simgrid.Mutex.lock()
- .. automethod:: simgrid.Mutex.try_lock()
- .. automethod:: simgrid.Mutex.unlock()
+ .. automethod:: simgrid.Mutex.lock
+ .. automethod:: simgrid.Mutex.try_lock
+ .. automethod:: simgrid.Mutex.unlock
.. group-tab:: C
from simgrid import Barrier
barrier = Barrier(2)
- .. automethod:: simgrid.Barrier.wait()
+ .. automethod:: simgrid.Barrier.__init__
+ .. automethod:: simgrid.Barrier.wait
.. group-tab:: C
Semaphore
==================
-.. doxygenclass:: simgrid::s4u::Semaphore
+.. tabs::
+ .. group-tab:: C++
+
+ .. doxygenclass:: simgrid::s4u::Semaphore
+
+ .. group-tab:: Python
+
+ .. autoclass:: simgrid.Semaphore
Basic management
----------------
.. doxygentypedef:: SemaphorePtr
.. doxygenfunction:: simgrid::s4u::Semaphore::create(unsigned int initial_capacity)
+ .. group-tab:: Python
+
+ .. code-block:: Python
+
+ from simgrid import Semaphore
+ semaphore = Semaphore(1)
+ # Automatically acquire the semaphore, and release it after leaving the scope.
+ with semaphore:
+ # Do something with the shared resource
+ pass
+
+ .. automethod:: simgrid.Semaphore.__init__
+
.. group-tab:: C
.. code-block:: C
.. doxygenfunction:: simgrid::s4u::Semaphore::release()
.. doxygenfunction:: simgrid::s4u::Semaphore::would_block() const
+ .. group-tab:: Python
+
+ .. automethod:: simgrid.Semaphore.acquire
+ .. automethod:: simgrid.Semaphore.acquire_timeout
+ .. autoattribute:: simgrid.Semaphore.capacity
+ .. automethod:: simgrid.Semaphore.release
+ .. autoattribute:: simgrid.Semaphore.would_block
+
.. group-tab:: C
.. doxygenfunction:: sg_sem_acquire(sg_sem_t sem)
exec-async exec-basic exec-dvfs exec-remote
platform-profile platform-failures
network-nonlinear clusters-multicpu io-degradation exec-cpu-nonlinear
- synchro-barrier synchro-mutex)
+ synchro-barrier synchro-mutex synchro-semaphore)
set(tesh_files ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/${example}/${example}.tesh)
set(examples_src ${examples_src} ${CMAKE_CURRENT_SOURCE_DIR}/${example}/${example}.py)
--- /dev/null
+# Copyright (c) 2010-2022. 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 typing import List, Optional
+from dataclasses import dataclass
+from argparse import ArgumentParser
+import sys
+
+from simgrid import Actor, Engine, Host, Semaphore, this_actor
+
+
+@dataclass
+class Shared:
+ buffer: str
+
+
+END_MARKER = ""
+
+
+shared = Shared("")
+sem_empty = Semaphore(1) # indicates whether the buffer is empty
+sem_full = Semaphore(0) # indicates whether the buffer is full
+
+
+def create_parser():
+ parser = ArgumentParser()
+ parser.add_argument(
+ '--platform',
+ type=str,
+ required=True,
+ help='path to the platform description'
+ )
+ parser.add_argument(
+ '--words',
+ type=lambda raw_words: raw_words.split(","),
+ default=["one", "two", "three"],
+ help='Comma-delimited list of words sent by the producer to the consumer'
+ )
+ return parser
+
+
+def producer(words: List[str]):
+ this_actor.info("starting consuming")
+ for word in words + [END_MARKER]:
+ sem_empty.acquire()
+ this_actor.sleep_for(1)
+ this_actor.info(f"Pushing '{word}'")
+ shared.buffer = word
+ sem_full.release()
+ this_actor.info("Bye!")
+
+
+def consumer():
+ this_actor.info("starting producing")
+ word: Optional[str] = None
+ while word != END_MARKER:
+ sem_full.acquire()
+ word = str(shared.buffer)
+ sem_empty.release()
+ this_actor.info(f"Receiving '{word}'")
+ this_actor.info("Bye!")
+
+
+def main():
+ settings = create_parser().parse_known_args()[0]
+ e = Engine(sys.argv)
+ e.load_platform(settings.platform)
+ Actor.create("producer", Host.by_name("Tremblay"), producer, settings.words)
+ Actor.create("consumer", Host.by_name("Jupiter"), consumer)
+ e.run()
+
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+#!/usr/bin/env tesh
+
+p Testing Semaphore
+
+$ ${pythoncmd:=python3} ${PYTHON_TOOL_OPTIONS:=} ${bindir:=.}/synchro-semaphore.py --platform ${platfdir}/two_hosts.xml --words hello "--log=root.fmt:[%10.6r]%e(%i:%a@%h)%e%m%n"
+>[ 0.000000] (1:producer@Tremblay) starting consuming
+>[ 0.000000] (2:consumer@Jupiter) starting producing
+>[ 1.000000] (1:producer@Tremblay) Pushing 'hello'
+>[ 1.000000] (2:consumer@Jupiter) Receiving 'hello'
+>[ 2.000000] (1:producer@Tremblay) Pushing ''
+>[ 2.000000] (1:producer@Tremblay) Bye!
+>[ 2.000000] (2:consumer@Jupiter) Receiving ''
+>[ 2.000000] (2:consumer@Jupiter) Bye!
+
+$ ${pythoncmd:=python3} ${PYTHON_TOOL_OPTIONS:=} ${bindir:=.}/synchro-semaphore.py --platform ${platfdir}/two_hosts.xml --words one,two,three "--log=root.fmt:[%10.6r]%e(%i:%a@%h)%e%m%n"
+>[ 0.000000] (1:producer@Tremblay) starting consuming
+>[ 0.000000] (2:consumer@Jupiter) starting producing
+>[ 1.000000] (1:producer@Tremblay) Pushing 'one'
+>[ 1.000000] (2:consumer@Jupiter) Receiving 'one'
+>[ 2.000000] (1:producer@Tremblay) Pushing 'two'
+>[ 2.000000] (2:consumer@Jupiter) Receiving 'two'
+>[ 3.000000] (1:producer@Tremblay) Pushing 'three'
+>[ 3.000000] (2:consumer@Jupiter) Receiving 'three'
+>[ 4.000000] (1:producer@Tremblay) Pushing ''
+>[ 4.000000] (1:producer@Tremblay) Bye!
+>[ 4.000000] (2:consumer@Jupiter) Receiving ''
+>[ 4.000000] (2:consumer@Jupiter) Bye!
#include <simgrid/s4u/Mailbox.hpp>
#include <simgrid/s4u/Mutex.hpp>
#include <simgrid/s4u/NetZone.hpp>
+#include <simgrid/s4u/Semaphore.hpp>
#include <simgrid/version.h>
#include <algorithm>
using simgrid::s4u::Mailbox;
using simgrid::s4u::Mutex;
using simgrid::s4u::MutexPtr;
+using simgrid::s4u::Semaphore;
+using simgrid::s4u::SemaphorePtr;
XBT_LOG_NEW_DEFAULT_CATEGORY(python, "python");
.def("wait", &simgrid::s4u::Exec::wait, py::call_guard<py::gil_scoped_release>(),
"Block until the completion of that execution.");
+ /* Class Semaphore */
+ py::class_<Semaphore, SemaphorePtr>(m, "Semaphore",
+ "A classical semaphore, but blocking in the simulation world. See the C++ "
+ "documentation for details.")
+ .def(py::init<>(&Semaphore::create), py::call_guard<py::gil_scoped_release>(), py::arg("capacity"),
+ "Semaphore constructor.")
+ .def("acquire", &Semaphore::acquire, py::call_guard<py::gil_scoped_release>(),
+ "Acquire on the semaphore object with no timeout. Blocks until the semaphore is acquired.")
+ .def("acquire_timeout", &Semaphore::acquire_timeout, py::call_guard<py::gil_scoped_release>(), py::arg("timeout"),
+ "Acquire on the semaphore object with no timeout. Blocks until the semaphore is acquired or return "
+ "true if it has not been acquired after the specified timeout.")
+ .def("release", &Semaphore::release, py::call_guard<py::gil_scoped_release>(),
+ "Release the semaphore.")
+ .def_property_readonly("capacity", &Semaphore::get_capacity, py::call_guard<py::gil_scoped_release>(),
+ "Get the semaphore capacity.")
+ .def_property_readonly("would_block", &Semaphore::would_block, py::call_guard<py::gil_scoped_release>(),
+ "Check whether trying to acquire the semaphore would block (in other word, checks whether "
+ "this semaphore has capacity).")
+ // Allow semaphores to be automatically acquired/released with a context manager: `with semaphore: ...`
+ .def("__enter__", [](Semaphore* self){ self->acquire(); }, py::call_guard<py::gil_scoped_release>())
+ .def("__exit__", [](Semaphore* self){ self->release(); }, py::call_guard<py::gil_scoped_release>());
+
/* Class Mutex */
py::class_<Mutex, MutexPtr>(m, "Mutex",
"A classical mutex, but blocking in the simulation world."
"See the C++ documentation for details.")
- .def(py::init<>(&Mutex::create))
+ .def(py::init<>(&Mutex::create), py::call_guard<py::gil_scoped_release>(), "Mutex constructor.")
.def("lock", &Mutex::lock, py::call_guard<py::gil_scoped_release>(), "Block until the mutex is acquired.")
.def("try_lock", &Mutex::try_lock, py::call_guard<py::gil_scoped_release>(),
"Try to acquire the mutex. Return true if the mutex was acquired, false otherwise.")
- .def("unlock", &Mutex::unlock, py::call_guard<py::gil_scoped_release>(), "Release the mutex")
+ .def("unlock", &Mutex::unlock, py::call_guard<py::gil_scoped_release>(), "Release the mutex.")
// Allow mutexes to be automatically acquired/released with a context manager: `with mutex: ...`
.def("__enter__", [](Mutex* self){ self->lock(); }, py::call_guard<py::gil_scoped_release>())
.def("__exit__", [](Mutex* self, const py::object&, const py::object&, const py::object&) { self->unlock(); },
/* Class Barrier */
py::class_<Barrier, BarrierPtr>(m, "Barrier",
"A classical barrier, but blocking in the simulation world.")
- .def(py::init<>(&Barrier::create), py::call_guard<py::gil_scoped_release>(), py::arg("expected_actors"))
+ .def(py::init<>(&Barrier::create), py::call_guard<py::gil_scoped_release>(), py::arg("expected_actors"),
+ "Barrier constructor.")
.def("wait", &Barrier::wait, py::call_guard<py::gil_scoped_release>(),
"Blocks into the barrier. Every waiting actors will be unlocked once the expected amount of actors reaches "
- "the barrier");
+ "the barrier.");
/* Class Actor */
py::class_<simgrid::s4u::Actor, ActorPtr>(m, "Actor",