Improve HandleAllocator API
We now have: allocate<> which just allocates the handle's memory construct<> which constructs the handle allocated with allocate<> allocateAndConstruct<> which allocates AND constructs the handle destroyAndConstruct<> which destroys and constructs a handle in place Normally you'd use allocate/construct but with synchronous calls, it might be necessary to have an initialized handle immediately.
This commit is contained in:
committed by
Mathias Agopian
parent
94a25452e8
commit
2bd8faaef5
@@ -51,11 +51,11 @@ public:
|
||||
* struct ConcreteTexture : public HwTexture {
|
||||
* ConcreteTexture(int w, int h);
|
||||
* };
|
||||
* Handle<ConcreteTexture> h = allocate(w, h);
|
||||
* Handle<ConcreteTexture> h = allocateAndConstruct(w, h);
|
||||
*
|
||||
*/
|
||||
template<typename D, typename ... ARGS>
|
||||
Handle<D> allocate(ARGS&& ... args) noexcept {
|
||||
Handle<D> allocateAndConstruct(ARGS&& ... args) noexcept {
|
||||
Handle<D> h{ allocateHandle(sizeof(D)) };
|
||||
D* addr = handle_cast<D*>(h);
|
||||
new(addr) D(std::forward<ARGS>(args)...);
|
||||
@@ -67,9 +67,59 @@ public:
|
||||
return h;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocates (without constructing) a D object and returns a Handle<D>
|
||||
*
|
||||
* e.g.:
|
||||
* struct ConcreteTexture : public HwTexture {
|
||||
* ConcreteTexture(int w, int h);
|
||||
* };
|
||||
* Handle<ConcreteTexture> h = allocate();
|
||||
*
|
||||
*/
|
||||
template<typename D>
|
||||
Handle<D> allocate() noexcept {
|
||||
Handle<D> h{ allocateHandle(sizeof(D)) };
|
||||
#if HANDLE_TYPE_SAFETY
|
||||
D* addr = handle_cast<D*>(h);
|
||||
mLock.lock();
|
||||
mHandleTypeId[addr] = typeid(D).name();
|
||||
mLock.unlock();
|
||||
#endif
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Destroys the object D at Handle<B> and construct a new D in its place
|
||||
* e.g.:
|
||||
* Handle<ConcreteTexture> h = allocateAndConstruct(w, h);
|
||||
* ConcreteTexture* p = reconstruct(h, w, h);
|
||||
*/
|
||||
template<typename D, typename B, typename ... ARGS>
|
||||
typename std::enable_if_t<std::is_base_of_v<B, D>, D>*
|
||||
destroyAndConstruct(Handle<B> const& handle, ARGS&& ... args) noexcept {
|
||||
assert_invariant(handle);
|
||||
D* addr = handle_cast<D*>(const_cast<Handle<B>&>(handle));
|
||||
assert_invariant(addr);
|
||||
|
||||
// currently we implement construct<> with dtor+ctor, we could use operator= also
|
||||
// but all our dtors are trivial, ~D() is actually a noop.
|
||||
addr->~D();
|
||||
new(addr) D(std::forward<ARGS>(args)...);
|
||||
|
||||
#if HANDLE_TYPE_SAFETY
|
||||
mLock.lock();
|
||||
mHandleTypeId[addr] = typeid(D).name();
|
||||
mLock.unlock();
|
||||
#endif
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a new D at Handle<B>
|
||||
* e.g.:
|
||||
* Handle<ConcreteTexture> h = allocate();
|
||||
* ConcreteTexture* p = construct(h, w, h);
|
||||
*/
|
||||
template<typename D, typename B, typename ... ARGS>
|
||||
@@ -78,10 +128,6 @@ public:
|
||||
assert_invariant(handle);
|
||||
D* addr = handle_cast<D*>(const_cast<Handle<B>&>(handle));
|
||||
assert_invariant(addr);
|
||||
|
||||
// currently we implement construct<> with dtor+ctor, we could use operator= also
|
||||
// but all our dtors are trivial, ~D() is actually a noop.
|
||||
addr->~D();
|
||||
new(addr) D(std::forward<ARGS>(args)...);
|
||||
|
||||
#if HANDLE_TYPE_SAFETY
|
||||
|
||||
@@ -1471,7 +1471,7 @@ FenceStatus OpenGLDriver::wait(Handle<HwFence> fh, uint64_t timeout) {
|
||||
// we can end-up here if:
|
||||
// - the platform doesn't support h/w fences
|
||||
// - wait() was called before the fence was asynchronously created.
|
||||
// This case is not handled in OpenGLDriver but is handle by FFence.
|
||||
// This case is not handled in OpenGLDriver but is handled by FFence.
|
||||
// TODO: move FFence logic into the backend.
|
||||
return FenceStatus::ERROR;
|
||||
}
|
||||
|
||||
@@ -253,13 +253,13 @@ private:
|
||||
|
||||
template<typename D, typename ... ARGS>
|
||||
backend::Handle<D> initHandle(ARGS&& ... args) noexcept {
|
||||
return mHandleAllocator.allocate<D>(std::forward<ARGS>(args) ...);
|
||||
return mHandleAllocator.allocateAndConstruct<D>(std::forward<ARGS>(args) ...);
|
||||
}
|
||||
|
||||
template<typename D, typename B, typename ... ARGS>
|
||||
typename std::enable_if<std::is_base_of<B, D>::value, D>::type*
|
||||
construct(backend::Handle<B> const& handle, ARGS&& ... args) noexcept {
|
||||
return mHandleAllocator.construct<D, B>(handle, std::forward<ARGS>(args) ...);
|
||||
return mHandleAllocator.destroyAndConstruct<D, B>(handle, std::forward<ARGS>(args) ...);
|
||||
}
|
||||
|
||||
template<typename B, typename D,
|
||||
|
||||
Reference in New Issue
Block a user