Skip to content

Commit 0e89c36

Browse files
committedSep 4, 2024·
unique, shared support virtual base class
1 parent f721cc6 commit 0e89c36

File tree

1 file changed

+35
-21
lines changed

1 file changed

+35
-21
lines changed
 

‎include/co/mem.h

+35-21
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class unique {
171171
if (_p) {
172172
static_cast<void>(sizeof(T));
173173
_p->~T();
174-
co::free(_s, _s->n);
174+
co::free((char*)_p - _s[-2], _s[-1]);
175175
_p = 0;
176176
}
177177
}
@@ -187,20 +187,23 @@ class unique {
187187
}
188188

189189
private:
190-
struct S { T o; size_t n; };
191-
union { S* _s; T* _p; };
190+
union { T* _p; uint32* _s; };
192191
};
193192

194193
template<typename T, typename... Args>
195194
inline unique<T> make_unique(Args&&... args) {
196-
struct S { T o; size_t n; };
197-
S* const s = (S*) co::alloc(sizeof(S));
195+
struct S { uint32 o; uint32 n; T t; };
196+
static_assert(alignof(S) <= 1024, "");
197+
const size_t off = (size_t) &((S*)0)->t;
198+
S* const s = (S*) co::alloc(sizeof(S), alignof(S));
199+
T* const t = &s->t;
198200
if (s) {
199-
new(s) T(std::forward<Args>(args)...);
200-
s->n = sizeof(S);
201+
new(t) T(std::forward<Args>(args)...);
202+
((uint32*)t)[-1] = sizeof(S);
203+
((uint32*)t)[-2] = (uint32)off;
201204
}
202205
unique<T> x;
203-
*(void**)&x = s;
206+
*(void**)&x = t;
204207
return x;
205208
}
206209

@@ -217,7 +220,7 @@ class shared {
217220

218221
shared(const shared& x) noexcept {
219222
_s = x._s;
220-
if (_s) atomic_inc(&_s->refn, mo_relaxed);
223+
if (_s) this->_ref();
221224
}
222225

223226
shared(shared&& x) noexcept {
@@ -242,7 +245,7 @@ class shared {
242245
> = 0>
243246
shared(const shared<X>& x) noexcept {
244247
_p = x.get();
245-
if (_s) atomic_inc(&_s->refn, mo_relaxed);
248+
if (_s) this->_ref();
246249
}
247250

248251
template<typename X, god::if_t<
@@ -279,17 +282,17 @@ class shared {
279282

280283
void reset() {
281284
if (_s) {
282-
if (atomic_dec(&_s->refn, mo_acq_rel) == 0) {
285+
if (this->_unref() == 0) {
283286
static_cast<void>(sizeof(T));
284287
_p->~T();
285-
co::free(_s, _s->size);
288+
co::free((char*)_p - _s[-2], _s[-1]);
286289
}
287290
_p = 0;
288291
}
289292
}
290293

291294
size_t ref_count() const noexcept {
292-
return _s ? atomic_load(&_s->refn, mo_relaxed) : 0;
295+
return _s ? atomic_load(&_s[-3], mo_relaxed) : 0;
293296
}
294297

295298
size_t use_count() const noexcept {
@@ -307,21 +310,32 @@ class shared {
307310
}
308311

309312
private:
310-
struct S { T o; uint32 refn; uint32 size; };
311-
union { S* _s; T* _p; };
313+
union { T* _p; uint32* _s; };
314+
315+
void _ref() {
316+
atomic_inc(&_s[-3], mo_relaxed);
317+
}
318+
319+
uint32 _unref() {
320+
return atomic_dec(&_s[-3], mo_acq_rel);
321+
}
312322
};
313323

314324
template<typename T, typename... Args>
315325
inline shared<T> make_shared(Args&&... args) {
316-
struct S { T o; uint32 refn; uint32 size; };
317-
S* const s = (S*) co::alloc(sizeof(S));
326+
struct S { uint32 r; uint32 o; uint32 n; T t; };
327+
static_assert(alignof(S) <= 1024, "");
328+
const size_t off = (size_t) &((S*)0)->t;
329+
S* const s = (S*) co::alloc(sizeof(S), alignof(S));
330+
T* const t = &s->t;
318331
if (s) {
319-
new(s) T(std::forward<Args>(args)...);
320-
s->refn = 1;
321-
s->size = sizeof(S);
332+
new(t) T(std::forward<Args>(args)...);
333+
((uint32*)t)[-1] = sizeof(S);
334+
((uint32*)t)[-2] = (uint32)off;
335+
((uint32*)t)[-3] = 1;
322336
}
323337
shared<T> x;
324-
*(void**)&x = s;
338+
*(void**)&x = t;
325339
return x;
326340
}
327341

0 commit comments

Comments
 (0)
Please sign in to comment.