Skip to content

Commit 78780e9

Browse files
author
devsh
committed
pepper the typecasting code with std::launder and hope I understood the spec :P
1 parent 4b7b34a commit 78780e9

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

include/nbl/asset/material_compiler3/CNodePool.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,19 @@ class CNodePool : public core::IReferenceCounted
6464
inline CDebugInfo(const void* data, const uint32_t size) : m_size(size)
6565
{
6666
if (data)
67-
memcpy(this+1,data,m_size);
67+
memcpy(std::launder(this+1),data,m_size);
6868
}
6969
inline CDebugInfo(const std::string_view& view) : CDebugInfo(nullptr,view.length()+1)
7070
{
71-
auto* out = reinterpret_cast<char*>(this+1);
71+
auto* out = std::launder(reinterpret_cast<char*>(this+1));
7272
if (m_size>1)
7373
memcpy(out,view.data(),m_size);
7474
out[m_size-1] = 0;
7575
}
7676

7777
inline const std::span<const uint8_t> data() const
7878
{
79-
return {reinterpret_cast<const uint8_t*>(this+1),m_size};
79+
return {std::launder(reinterpret_cast<const uint8_t*>(this+1)),m_size};
8080
}
8181

8282
protected:
@@ -174,6 +174,7 @@ class CNodePool : public core::IReferenceCounted
174174
const uint32_t size = ptr->getSize();
175175
static_cast<INode*>(ptr)->~INode(); // can't use `std::destroy_at<T>(ptr);` because of destructor being non-public
176176
// wipe v-table to mark as dead (so `~CNodePool` doesn't run destructor twice)
177+
// NOTE: This won't work if we start reusing memory, even zeroing out the whole node won't work! Then need an accurate record of live nodes!
177178
const void* nullVTable = nullptr;
178179
assert(memcmp(ptr,&nullVTable,sizeof(nullVTable))!=0); // double free
179180
memset(static_cast<INode*>(ptr),0,sizeof(nullVTable));
@@ -196,6 +197,7 @@ class CNodePool : public core::IReferenceCounted
196197
for (auto handleOff=chunk.getAllocator().get_total_size(); handleOff<chunkSize; handleOff+=sizeof(Handle))
197198
{
198199
const auto pHandle = reinterpret_cast<const Handle*>(chunk.m_data+handleOff);
200+
// NOTE: This won't work if we start reusing memory, even zeroing out the whole node won't work! Then need an accurate record of live nodes!
199201
if (auto* node=deref<INode>(*pHandle); node)
200202
node->~INode(); // can't use `std::destroy_at<T>(ptr);` because of destructor being non-public
201203
}
@@ -207,7 +209,7 @@ class CNodePool : public core::IReferenceCounted
207209
struct Chunk
208210
{
209211
// for now using KISS, we can use geeneralpupose allocator later
210-
// Generalpurpose woudl require us to store the allocated handle list in a different way, so that handles can be quickly removed from it.
212+
// Generalpurpose would require us to store the allocated handle list in a different way, so that handles can be quickly removed from it.
211213
// Maybe a doubly linked list around the original allocation?
212214
using allocator_t = core::LinearAddressAllocatorST<Handle::value_t>;
213215

@@ -232,8 +234,9 @@ class CNodePool : public core::IReferenceCounted
232234
return invalid_address;
233235
}
234236
// clear vtable to mark as not initialized yet
237+
// TODO: this won't work with reusable memory / not bump allocator
235238
memset(m_data+retval,0,sizeof(INode));
236-
*reinterpret_cast<Handle::value_t*>(m_data+newSize) = retval;
239+
*std::launder(reinterpret_cast<Handle::value_t*>(m_data+newSize)) = retval;
237240
// shrink allocator
238241
getAllocator() = allocator_t(newSize, std::move(getAllocator()), nullptr);
239242
}
@@ -264,9 +267,9 @@ class CNodePool : public core::IReferenceCounted
264267
return ptr;
265268
else
266269
{
267-
if (*reinterpret_cast<const void* const*>(ptr)) // vtable not wiped
270+
if (*std::launder(reinterpret_cast<const void* const*>(ptr))) // vtable not wiped
268271
{
269-
auto* base = reinterpret_cast<INode*>(ptr);
272+
auto* base = std::launder(reinterpret_cast<INode*>(ptr));
270273
return dynamic_cast<T*>(base);
271274
}
272275
}

0 commit comments

Comments
 (0)