From 41f2971b7c2ab118131d34cee3e83834418f70f5 Mon Sep 17 00:00:00 2001 From: Sandu Liviu Catalin Date: Thu, 17 Nov 2016 11:46:36 +0200 Subject: [PATCH] Implement an allocator for types that cannot be constructed by script and must not be destructed by script. For cases where the actual instance is static and might outlive the VM itself. --- include/sqrat/sqratAllocator.h | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/include/sqrat/sqratAllocator.h b/include/sqrat/sqratAllocator.h index d28966da..93098460 100644 --- a/include/sqrat/sqratAllocator.h +++ b/include/sqrat/sqratAllocator.h @@ -463,6 +463,89 @@ public: } }; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// NoDestructor is the allocator to use for Class that can NOT be constructed, copied or destructed +/// +/// \tparam C Type of class +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +class NoDestructor { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted) + /// + /// \param vm VM that has an instance object of the correct type at idx + /// \param idx Index of the stack that the instance object is at + /// \param ptr Should be the return value from a call to the new operator + /// + /// \remarks + /// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr) + { + ClassData* cd = ClassType::getClassData(vm); + sq_setinstanceup(vm, idx, new std::pair::type> >(ptr, cd->instance)); + sq_setreleasehook(vm, idx, &Delete); + sq_getstackobj(vm, idx, &((*cd->instances)[ptr])); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to set up an instance on the stack for the template class (not allowed in this allocator) + /// + /// \param vm VM that has an instance object of the correct type at position 1 in its stack + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger New(HSQUIRRELVM vm) { +#if !defined (SCRAT_NO_ERROR_CHECKING) + return sq_throwerror(vm, (ClassType::ClassName() + string(_SC(" constructing is not allowed"))).c_str()); +#else + SQUNUSED(vm); + return 0; +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type (not used in this allocator) + /// + /// \param vm VM that has an instance object of the correct type at idx + /// \param idx Index of the stack that the instance object is at + /// \param value A pointer to data of the same type as the instance object + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) { + SQUNUSED(vm); + SQUNUSED(idx); + SQUNUSED(value); + return sq_throwerror(vm, (ClassType::ClassName() + string(_SC(" cloning is not allowed"))).c_str()); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to delete an instance's data + /// + /// \param ptr Pointer to the data contained by the instance + /// \param size Size of the data contained by the instance + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger Delete(SQUserPointer ptr, SQInteger size) { + SQUNUSED(size); + std::pair::type> >* instance = reinterpret_cast::type> >*>(ptr); + instance->second->erase(instance->first); + // Only delete our pair instance and leave the actual instance untouched + //delete instance->first; + delete instance; + return 0; + } +}; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// CopyOnly is the allocator to use for Class that can be copied but not constructed ///