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

Quelle  SkDiscardableMemoryPool.cpp   Sprache: C

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


#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkMutex.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/chromium/SkDiscardableMemory.h"
#include "src/base/SkTInternalLList.h"
#include "src/lazy/SkDiscardableMemoryPool.h"

using namespace skia_private;

// Note:
// A PoolDiscardableMemory is memory that is counted in a pool.
// A DiscardableMemoryPool is a pool of PoolDiscardableMemorys.

namespace {

class PoolDiscardableMemory;

/**
 *  This non-global pool can be used for unit tests to verify that the
 *  pool works.
 */

class DiscardableMemoryPool : public SkDiscardableMemoryPool {
public:
    DiscardableMemoryPool(size_t budget);
    ~DiscardableMemoryPool() override;

    std::unique_ptr<SkDiscardableMemory> make(size_t bytes);
    SkDiscardableMemory* create(size_t bytes) override {
        return this->make(bytes).release();  // TODO: change API
    }

    size_t getRAMUsed() override;
    void setRAMBudget(size_t budget) override;
    size_t getRAMBudget() override { return fBudget; }

    /** purges all unlocked DMs */
    void dumpPool() override;

    #if SK_LAZY_CACHE_STATS  // Defined in SkDiscardableMemoryPool.h
    int getCacheHits() override { return fCacheHits; }
    int getCacheMisses() override { return fCacheMisses; }
    void resetCacheHitsAndMisses() override {
        fCacheHits = fCacheMisses = 0;
    }
    int          fCacheHits;
    int          fCacheMisses;
    #endif  // SK_LAZY_CACHE_STATS

private:
    SkMutex      fMutex;
    size_t       fBudget;
    size_t       fUsed;
    SkTInternalLList<PoolDiscardableMemory> fList;

    /** Function called to free memory if needed */
    void dumpDownTo(size_t budget);
    /** called by DiscardableMemoryPool upon destruction */
    void removeFromPool(PoolDiscardableMemory* dm);
    /** called by DiscardableMemoryPool::lock() */
    bool lock(PoolDiscardableMemory* dm);
    /** called by DiscardableMemoryPool::unlock() */
    void unlock(PoolDiscardableMemory* dm);

    friend class PoolDiscardableMemory;

    using INHERITED = SkDiscardableMemory::Factory;
};

/**
 *  A PoolDiscardableMemory is a SkDiscardableMemory that relies on
 *  a DiscardableMemoryPool object to manage the memory.
 */

class PoolDiscardableMemory : public SkDiscardableMemory {
public:
    PoolDiscardableMemory(sk_sp<DiscardableMemoryPool> pool, UniqueVoidPtr pointer, size_t bytes);
    ~PoolDiscardableMemory() override;
    bool lock() override;
    void* data() override;
    void unlock() override;
    friend class DiscardableMemoryPool;
private:
    SK_DECLARE_INTERNAL_LLIST_INTERFACE(PoolDiscardableMemory);
    sk_sp<DiscardableMemoryPool> fPool;
    bool                         fLocked;
    UniqueVoidPtr                   fPointer;
    const size_t                 fBytes;
};

PoolDiscardableMemory::PoolDiscardableMemory(sk_sp<DiscardableMemoryPool> pool,
                                             UniqueVoidPtr pointer,
                                             size_t bytes)
        : fPool(std::move(pool)), fLocked(true), fPointer(std::move(pointer)), fBytes(bytes) {
    SkASSERT(fPool != nullptr);
    SkASSERT(fPointer != nullptr);
    SkASSERT(fBytes > 0);
}

PoolDiscardableMemory::~PoolDiscardableMemory() {
    SkASSERT(!fLocked); // contract for SkDiscardableMemory
    fPool->removeFromPool(this);
}

bool PoolDiscardableMemory::lock() {
    SkASSERT(!fLocked); // contract for SkDiscardableMemory
    return fPool->lock(this);
}

void* PoolDiscardableMemory::data() {
    SkASSERT(fLocked); // contract for SkDiscardableMemory
    return fPointer.get();
}

void PoolDiscardableMemory::unlock() {
    SkASSERT(fLocked); // contract for SkDiscardableMemory
    fPool->unlock(this);
}

////////////////////////////////////////////////////////////////////////////////

DiscardableMemoryPool::DiscardableMemoryPool(size_t budget)
    : fBudget(budget)
    , fUsed(0) {
    #if SK_LAZY_CACHE_STATS
    fCacheHits = 0;
    fCacheMisses = 0;
    #endif  // SK_LAZY_CACHE_STATS
}
DiscardableMemoryPool::~DiscardableMemoryPool() {
    // PoolDiscardableMemory objects that belong to this pool are
    // always deleted before deleting this pool since each one has a
    // ref to the pool.
    SkASSERT(fList.isEmpty());
}

void DiscardableMemoryPool::dumpDownTo(size_t budget) {
    fMutex.assertHeld();
    if (fUsed <= budget) {
        return;
    }
    using Iter = SkTInternalLList<PoolDiscardableMemory>::Iter;
    Iter iter;
    PoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart);
    while ((fUsed > budget) && (cur)) {
        if (!cur->fLocked) {
            PoolDiscardableMemory* dm = cur;
            SkASSERT(dm->fPointer != nullptr);
            dm->fPointer = nullptr;
            SkASSERT(fUsed >= dm->fBytes);
            fUsed -= dm->fBytes;
            cur = iter.prev();
            // Purged DMs are taken out of the list.  This saves times
            // looking them up.  Purged DMs are NOT deleted.
            fList.remove(dm);
        } else {
            cur = iter.prev();
        }
    }
}

std::unique_ptr<SkDiscardableMemory> DiscardableMemoryPool::make(size_t bytes) {
    UniqueVoidPtr addr(sk_malloc_canfail(bytes));
    if (nullptr == addr) {
        return nullptr;
    }
    auto dm = std::make_unique<PoolDiscardableMemory>(sk_ref_sp(this), std::move(addr), bytes);
    SkAutoMutexExclusive autoMutexAcquire(fMutex);
    fList.addToHead(dm.get());
    fUsed += bytes;
    this->dumpDownTo(fBudget);
    return dm;
}

void DiscardableMemoryPool::removeFromPool(PoolDiscardableMemory* dm) {
    SkAutoMutexExclusive autoMutexAcquire(fMutex);
    // This is called by dm's destructor.
    if (dm->fPointer != nullptr) {
        SkASSERT(fUsed >= dm->fBytes);
        fUsed -= dm->fBytes;
        fList.remove(dm);
    } else {
        SkASSERT(!fList.isInList(dm));
    }
}

bool DiscardableMemoryPool::lock(PoolDiscardableMemory* dm) {
    SkASSERT(dm != nullptr);
    SkAutoMutexExclusive autoMutexAcquire(fMutex);
    if (nullptr == dm->fPointer) {
        // May have been purged while waiting for lock.
        #if SK_LAZY_CACHE_STATS
        ++fCacheMisses;
        #endif  // SK_LAZY_CACHE_STATS
        return false;
    }
    dm->fLocked = true;
    fList.remove(dm);
    fList.addToHead(dm);
    #if SK_LAZY_CACHE_STATS
    ++fCacheHits;
    #endif  // SK_LAZY_CACHE_STATS
    return true;
}

void DiscardableMemoryPool::unlock(PoolDiscardableMemory* dm) {
    SkASSERT(dm != nullptr);
    SkAutoMutexExclusive autoMutexAcquire(fMutex);
    dm->fLocked = false;
    this->dumpDownTo(fBudget);
}

size_t DiscardableMemoryPool::getRAMUsed() {
    return fUsed;
}
void DiscardableMemoryPool::setRAMBudget(size_t budget) {
    SkAutoMutexExclusive autoMutexAcquire(fMutex);
    fBudget = budget;
    this->dumpDownTo(fBudget);
}
void DiscardableMemoryPool::dumpPool() {
    SkAutoMutexExclusive autoMutexAcquire(fMutex);
    this->dumpDownTo(0);
}

}  // namespace

sk_sp<SkDiscardableMemoryPool> SkDiscardableMemoryPool::Make(size_t size) {
    return sk_make_sp<DiscardableMemoryPool>(size);
}

SkDiscardableMemoryPool* SkGetGlobalDiscardableMemoryPool() {
    // Intentionally leak this global pool.
    static SkDiscardableMemoryPool* global =
            new DiscardableMemoryPool(SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE);
    return global;
}

Messung V0.5
C=88 H=98 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.