aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/tourist/foundation/include/foundation/buffer.h
blob: ab004248c67377e45d724f86900745a50de084ed (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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#pragma once

#include "types.h"

//------------------------------------------------------------------------------
class BufferStream;
class BufferRef;
class Slab;

//------------------------------------------------------------------------------
class Buffer
{
public:
                    Buffer() = default;
                    ~Buffer();
                    Buffer(Buffer&& rhs);
    void            operator = (Buffer&& rhs);
    const uint8*    get_pointer() const;
    uint32          get_size() const;
    BufferStream    create_stream() const;
    BufferRef       create_ref() const;
    Buffer          create_sub_buffer(uint32 left, uint32 right=~0u) const;
    Buffer          create_sub_buffer(const uint8* ptr, uint32 size) const;

protected:
    friend          class Allocator;
    friend          class BufferStream;
    void            inc_ref();
    void            dec_ref();
    void            move(Buffer&& rhs);
    Buffer          clone() const;
    Slab*           _slab = nullptr;
    uint32          _offset = 0;
    uint32          _size;

private:
                    Buffer(const Buffer&) = delete;
                    Buffer& operator = (const Buffer&) = delete;
};



//------------------------------------------------------------------------------
class MutableBuffer
    : public Buffer
{
public:
            MutableBuffer() = default;
    uint8*  get_pointer();

private:
    friend  class Allocator;
            MutableBuffer(Slab* slab, uint32 size, uint32 offset);
};



//------------------------------------------------------------------------------
class Pointer
{
public:
                    Pointer() = default;
                    ~Pointer();
                    Pointer(Pointer&& rhs);
    void            operator = (Pointer&& rhs);
    bool            is_valid() const;
    void            pin();
    const uint8*    get() const;

protected:
    friend          class BufferStream;
                    Pointer(Slab* slab, const uint8* ptr);

private:
    friend          class Allocator;
    Slab*           get_slab() const;

    union {
        struct {
            uintptr _ptr : 47;
            uintptr _pinned : 1;
            uintptr _slab_offset : 16;
        };
        uintptr     _value = 0;
    };
};



//------------------------------------------------------------------------------
class BufferRef
    : public Pointer
{
private:
    friend  class Buffer;
            BufferRef(Slab* slab, const uint8* ptr);
};



//------------------------------------------------------------------------------
class Allocator
    : public NoCopy
    , public NoMove
{
public:
                        ~Allocator();
    MutableBuffer       create_buffer(uint32 size);
    static Allocator&   get_from(Buffer& buffer);
    static Allocator&   get_from(BufferRef& ref);
    static Allocator&   get_from(BufferStream& stream);
    static Allocator&   get_from(Pointer& pointer);

private:
    friend              Slab;
    void                free_slab(Slab* slab);
    static Allocator&   get_from(const Slab* slab);
    Mutex               _lock;
    Slab*               _slab = nullptr;
    uint32              _slab_free = 0;
};



//------------------------------------------------------------------------------
class BufferStream
{
public:
                            BufferStream() = default;
    bool                    has_data() const;
    uint32                  get_consumed() const;
    uint32                  get_remaining() const;
    const uint8*            read(uint32 size);
    Buffer                  read_buf(uint32 size);
    Pointer                 read_ptr(uint32 size);
    template <typename T> T read();

private:
    friend                  class Allocator;
    friend                  class Buffer;
                            BufferStream(Slab* slab, const uint8* ptr, uint32 size);
    Slab*                   get_slab() const;
    const uint8*            _ptr;
    uint32                  _slab_offset = 0;
    uint32                  _end = 0;
    uint32                  _cursor = 0;
    uint32                  _unused;
};