-
Notifications
You must be signed in to change notification settings - Fork 4
/
Box.cpp
151 lines (129 loc) · 3.5 KB
/
Box.cpp
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
149
150
151
#include "Box.h"
#include "ext/mx/mx_platform.h"
#include "ext/mx/mx_sync.h"
#include "sf/Reflection.h"
namespace sf {
static constexpr const size_t BoxHeaderSize = 16;
#if SF_DEBUG
static constexpr const size_t BoxMagicSize = 16;
const char boxMagic[] = "\x0b\x1b\x2b\x3b\x4b\x5b\x6b\x7b\x8b\x9b\xab\xbb\xcb\xdb\xeb\xfb";
const char boxDeletedMagic[] = "\x0d\x1d\x2d\x3d\x4d\x5d\x6d\x7d\x8d\x9d\xad\xbd\xcd\xdd\xed\xfd";
static_assert(sizeof(boxMagic) == BoxMagicSize + 1, "boxMagic size");
static_assert(sizeof(boxDeletedMagic) == BoxMagicSize + 1, "boxDeletedMagic size");
sf_inline void boxInitMagic(BoxHeader *header) {
char *magic = (char*)header + BoxHeaderSize + header->size;
memcpy(magic, boxMagic, BoxMagicSize);
}
sf_inline void boxDeleteMagic(BoxHeader *header) {
char *magic = (char*)header + BoxHeaderSize + header->size;
memcpy(magic, boxDeletedMagic, BoxMagicSize);
}
sf_inline void boxCheckMagic(const BoxHeader *header) {
const char *magic = (const char*)header + BoxHeaderSize + header->size;
sf_assert(!memcmp(magic, boxMagic, BoxMagicSize));
}
#else
static constexpr const size_t BoxMagicSize = 0;
sf_inline void boxInitMagic(BoxHeader *header) { }
sf_inline void boxDeleteMagic(BoxHeader *header) { }
sf_inline void boxCheckMagic(const BoxHeader *header) { }
#endif
struct WeakBoxData
{
mx_mutex mutex;
void *ptr;
uint64_t id;
};
void *boxAlloc(size_t size)
{
return memAlloc(size);
}
void boxFree(void *ptr, size_t size)
{
memFree(ptr);
}
static_assert(sizeof(BoxHeader) <= BoxHeaderSize, "BoxHeader is too large");
BoxHeader *getHeader(void *ptr)
{
sf_assert(ptr);
return (BoxHeader*)((char*)ptr - BoxHeaderSize);
}
void *impBoxAllocate(size_t size, DestructRangeFn dtor)
{
void *data = boxAlloc(size + (BoxHeaderSize + BoxMagicSize));
BoxHeader *header = (BoxHeader*)data;
header->refCount = 1;
header->size = (uint32_t)size;
header->dtor = dtor;
boxInitMagic(header);
return (char*)data + BoxHeaderSize;
}
void impBoxIncRef(void *ptr)
{
BoxHeader *header = getHeader(ptr);
boxCheckMagic(header);
uint32_t refs = mxa_inc32(&header->refCount);
sf_assert(refs > 0);
}
void impBoxDecRef(void *ptr)
{
BoxHeader *header = getHeader(ptr);
boxCheckMagic(header);
uint32_t left = mxa_dec32(&header->refCount) - 1;
if (left == 0) {
header->dtor(ptr, 1);
boxFree(header, header->size + (BoxHeaderSize + BoxMagicSize));
}
}
struct BoxType final : Type
{
BoxType(const TypeInfo &info, Type *elemType)
: Type("sf::Box", info, HasPointer | IsBox)
{
elementType = elemType;
}
virtual void init()
{
if (elementType->flags & PolymorphBase) {
flags |= Polymorph;
}
}
virtual void getName(sf::StringBuf &buf)
{
buf.append("sf::Box<");
elementType->getName(buf);
buf.append(">");
}
virtual PolymorphInstance instGetPolymorph(void *inst)
{
void *ptr = *(void**)inst;
if (ptr) {
return elementType->instGetPolymorph(ptr);
} else {
return { };
}
}
virtual void *instSetPolymorph(void *inst, Type *type)
{
void *ptr = *(void**)inst;
if (ptr) impBoxDecRef(ptr);
ptr = impBoxAllocate(type->info.size, type->info.destructRange);
*(void**)inst = ptr;
type->info.constructRange(ptr, 1);
return ptr;
}
virtual void *instSetPointer(void *inst)
{
void *ptr = *(void**)inst;
if (ptr) impBoxDecRef(ptr);
ptr = impBoxAllocate(elementType->info.size, elementType->info.destructRange);
*(void**)inst = ptr;
elementType->info.constructRange(ptr, 1);
return ptr;
}
};
void initBoxType(Type *t, const TypeInfo &info, Type *elemType)
{
new (t) BoxType(info, elemType);
}
}