Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/skia/skia/include/private/base/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 2 kB image not shown  

Quelle  SkSemaphore.h   Sprache: C

 
/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#ifndef SkSemaphore_DEFINED
#define SkSemaphore_DEFINED

#include "include/private/base/SkAPI.h"
#include "include/private/base/SkOnce.h"
#include "include/private/base/SkThreadAnnotations.h"

#include <algorithm>
#include <atomic>

class SkSemaphore {
public:
    constexpr SkSemaphore(int count = 0) : fCount(count), fOSSemaphore(nullptr) {}

    // Cleanup the underlying OS semaphore.
    SK_SPI ~SkSemaphore();

    // Increment the counter n times.
    // Generally it's better to call signal(n) instead of signal() n times.
    void signal(int n = 1);

    // Decrement the counter by 1,
    // then if the counter is < 0, sleep this thread until the counter is >= 0.
    void wait();

    // If the counter is positive, decrement it by 1 and return true, otherwise return false.
    SK_SPI bool try_wait();

private:
    // This implementation follows the general strategy of
    //     'A Lightweight Semaphore with Partial Spinning'
    // found here
    //     http://preshing.com/20150316/semaphores-are-surprisingly-versatile/
    // That article (and entire blog) are very much worth reading.
    //
    // We wrap an OS-provided semaphore with a user-space atomic counter that
    // lets us avoid interacting with the OS semaphore unless strictly required:
    // moving the count from >=0 to <0 or vice-versa, i.e. sleeping or waking threads.
    struct OSSemaphore;

    SK_SPI void osSignal(int n);
    SK_SPI void osWait();

    std::atomic<int> fCount;
    SkOnce           fOSSemaphoreOnce;
    OSSemaphore*     fOSSemaphore;
};

inline void SkSemaphore::signal(int n) {
    int prev = fCount.fetch_add(n, std::memory_order_release);

    // We only want to call the OS semaphore when our logical count crosses
    // from <0 to >=0 (when we need to wake sleeping threads).
    //
    // This is easiest to think about with specific examples of prev and n.
    // If n == 5 and prev == -3, there are 3 threads sleeping and we signal
    // std::min(-(-3), 5) == 3 times on the OS semaphore, leaving the count at 2.
    //
    // If prev >= 0, no threads are waiting, std::min(-prev, n) is always <= 0,
    // so we don't call the OS semaphore, leaving the count at (prev + n).
    int toSignal = std::min(-prev, n);
    if (toSignal > 0) {
        this->osSignal(toSignal);
    }
}

inline void SkSemaphore::wait() {
    // Since this fetches the value before the subtract, zero and below means that there are no
    // resources left, so the thread needs to wait.
    if (fCount.fetch_sub(1, std::memory_order_acquire) <= 0) {
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
        this->osWait();
        SK_POTENTIALLY_BLOCKING_REGION_END;
    }
}

#endif//SkSemaphore_DEFINED

Messung V0.5
C=93 H=95 G=93

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.