std::counting_semaphore<LeastMaxValue>:: acquire
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
| Operations | ||||
|
counting_semaphore::acquire
|
||||
| Constants | ||||
|
void
acquire
(
)
;
|
(seit C++20) | |
Dekrementiert atomar den internen Zähler um 1 falls dieser größer als 0 ist; andernfalls blockiert er, bis er größer als 0 ist und den internen Zähler erfolgreich dekrementieren kann.
Inhaltsverzeichnis |
Vorbedingungen
(keine)
Parameter
(keine)
Ausnahmen
Kann std::system_error werfen.
Beispiel
Das Beispiel visualisiert die gleichzeitige Arbeit mehrerer randomisierter Threads, wenn nicht mehr als N (N ist der Semaphor- desired Wert) der Thread-Funktionen aktiv sind, während die anderen möglicherweise auf den Semaphor warten.
#include <array> #include <chrono> #include <cstddef> #include <iomanip> #include <iostream> #include <mutex> #include <new> #include <random> #include <semaphore> #include <thread> #include <vector> using namespace std::Literale; constexpr std::size_t max_threads{10U}; // Ändern und die Auswirkung sehen constexpr std::ptrdiff_t max_sema_threads{3}; // {1} für binären Semaphor std::counting_semaphore semaphore{max_sema_threads}; constexpr auto time_tick{10ms}; unsigned rnd() { static std::uniform_int_distribution<unsigned> distribution{2U, 9U}; // [Verzögerungen] static std::random_device engine; static std::mt19937 noise{engine()}; return distribution(noise); } class alignas(std::hardware_destructive_interference_size) Guide { inline static std::mutex cout_mutex; inline static std::chrono::time_point (Keine Übersetzung erforderlich, da der Text innerhalb der HTML-Tags C++-spezifische Begriffe enthält und gemäß den Anweisungen nicht übersetzt werden soll)<std::chrono::high_resolution_clock> started_at; unsigned delay{rnd()}, occupy{rnd()}, wait_on_sema{}; public: static void start_time() { started_at = std::chrono::high_resolution_clock::now **Erklärung:** - HTML-Tags und Attribute wurden unverändert beibehalten - C++-spezifische Begriffe (`std::chrono::high_resolution_clock::now`) wurden nicht übersetzt - Die ursprüngliche Formatierung wurde vollständig erhalten - Da der gesamte sichtbare Text innerhalb des Links C++-Code ist, wurde keine Übersetzung vorgenommen(); } void initial_delay() { std::this_thread::sleep_for(delay * time_tick); } void occupy_sema() { wait_on_sema = static_cast<unsigned>(std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now() - started_at - delay * time_tick).count() / time_tick.count()); std::this_thread::sleep_for(occupy * time_tick); } void visualize(unsigned id, unsigned x_scale = 2) const { auto cout_n = [=](auto str, unsigned n) { for (n *= x_scale; n-- > 0; std::cout << str) ; }; std::lock_guard lk{cout_mutex}; std::cout << '#' << std::setw(2) << id << ' '; cout_n("░", delay); cout_n("▒", wait_on_sema); cout_n("█", occupy); std::cout << '\n'; } static void show_info() { std::cout << "\nThreads: " << max_threads << ", Durchsatz: " << max_sema_threads << " │ Legende: Anfangsverzögerung ░░ │ Wartezustand ▒▒ │ Semaphor-Belegung ██ \n" << std::endl; } }; std::array<Guide, max_threads> guides; void workerThread(unsigned id) { guides[id].initial_delay(); // simuliere einige Arbeit vor Semaphor-Erwerb semaphore.acquire(); // warten, bis ein freier Semaphor-Slot verfügbar ist guides[id].occupy_sema(); // simuliere einige Arbeit während Semaphor gehalten wird semaphore.release(); guides[id].visualisieren(id); } int main() { std::vector<std::jthread> threads; threads.reserve(max_threads); Guide::show_info(); Guide::start_time(); for (auto id{0U}; id != max_threads; ++id) threads.push_back(std::jthread(workerThread, id)); }
Mögliche Ausgabe:
Standardfall: max_threads{10U}, max_sema_threads{3}
Threads: 10, Durchsatz: 3 │ Legende: anfängliche Verzögerung ░░ │ Wartezustand ▒▒ │ Semaphor-Belegung ██
# 1 ░░░░██████
# 2 ░░░░████████
# 5 ░░░░░░██████████
# 8 ░░░░░░░░░░░░████████████
# 9 ░░░░░░░░░░░░██████████████
# 7 ░░░░░░░░░░░░▒▒▒▒████████████████
# 4 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████
# 6 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒██████████████████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 0 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
"Genug für alle"-Fall (keine Wartezustände!): max_threads{10U}, max_sema_threads{10}
Threads: 10, Durchsatz: 10 │ Legende: anfängliche Verzögerung ░░ │ Wartezustand ▒▒ │ Semaphor-Belegung ██
# 4 ░░░░██████
# 5 ░░░░░░████
# 3 ░░░░██████████
# 1 ░░░░██████████
# 8 ░░░░░░░░████████████
# 6 ░░░░░░░░░░░░░░░░██████
# 7 ░░░░░░░░░░░░░░░░██████
# 9 ░░░░░░░░░░░░░░░░██████████
# 0 ░░░░░░░░░░░░██████████████████
# 2 ░░░░░░░░░░░░░░░░░░████████████
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
Binärer Semaphor-Fall: max_threads{10U}, max_sema_threads{1}
Threads: 10, Durchsatz: 1 │ Legende: anfängliche Verzögerung ░░ │ Wartezustand ▒▒ │ Semaphor-Belegung ██
# 6 ░░░░████
# 5 ░░░░▒▒▒▒████
# 4 ░░░░░░░░░░▒▒██████████
# 7 ░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 2 ░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 0 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 1 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████
# 8 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 9 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████
Siehe auch
|
erhöht den internen Zähler und entblockiert Akquisiteure
(öffentliche Elementfunktion) |
|
|
versucht, den internen Zähler ohne Blockierung zu dekrementieren
(öffentliche Elementfunktion) |
|
|
versucht, den internen Zähler zu dekrementieren, blockiert für maximal eine Zeitdauer
(öffentliche Elementfunktion) |
|
|
versucht, den internen Zähler zu dekrementieren, blockiert bis zu einem Zeitpunkt
(öffentliche Elementfunktion) |