summaryrefslogtreecommitdiffstats
path: root/src/core/file_sys/fssystem/fssystem_pooled_buffer.h
blob: 1df3153a1cd586abdfd7306bbd7c091bf39274d1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/literals.h"
#include "core/hle/result.h"

namespace FileSys {

using namespace Common::Literals;

constexpr inline size_t BufferPoolAlignment = 4_KiB;
constexpr inline size_t BufferPoolWorkSize = 320;

class PooledBuffer {
    YUZU_NON_COPYABLE(PooledBuffer);

private:
    char* m_buffer;
    size_t m_size;

private:
    static size_t GetAllocatableSizeMaxCore(bool large);

public:
    static size_t GetAllocatableSizeMax() {
        return GetAllocatableSizeMaxCore(false);
    }
    static size_t GetAllocatableParticularlyLargeSizeMax() {
        return GetAllocatableSizeMaxCore(true);
    }

private:
    void Swap(PooledBuffer& rhs) {
        std::swap(m_buffer, rhs.m_buffer);
        std::swap(m_size, rhs.m_size);
    }

public:
    // Constructor/Destructor.
    constexpr PooledBuffer() : m_buffer(), m_size() {}

    PooledBuffer(size_t ideal_size, size_t required_size) : m_buffer(), m_size() {
        this->Allocate(ideal_size, required_size);
    }

    ~PooledBuffer() {
        this->Deallocate();
    }

    // Move and assignment.
    explicit PooledBuffer(PooledBuffer&& rhs) : m_buffer(rhs.m_buffer), m_size(rhs.m_size) {
        rhs.m_buffer = nullptr;
        rhs.m_size = 0;
    }

    PooledBuffer& operator=(PooledBuffer&& rhs) {
        PooledBuffer(std::move(rhs)).Swap(*this);
        return *this;
    }

    // Allocation API.
    void Allocate(size_t ideal_size, size_t required_size) {
        return this->AllocateCore(ideal_size, required_size, false);
    }

    void AllocateParticularlyLarge(size_t ideal_size, size_t required_size) {
        return this->AllocateCore(ideal_size, required_size, true);
    }

    void Shrink(size_t ideal_size);

    void Deallocate() {
        // Shrink the buffer to empty.
        this->Shrink(0);
        ASSERT(m_buffer == nullptr);
    }

    char* GetBuffer() const {
        ASSERT(m_buffer != nullptr);
        return m_buffer;
    }

    size_t GetSize() const {
        ASSERT(m_buffer != nullptr);
        return m_size;
    }

private:
    void AllocateCore(size_t ideal_size, size_t required_size, bool large);
};

} // namespace FileSys