From 71aca551f2c3847b67c324a8cab3d0548b83fa08 Mon Sep 17 00:00:00 2001 From: halx99 Date: Sat, 8 Oct 2022 22:42:53 +0800 Subject: [PATCH 1/7] Improve AutoPolygon::generateTriangles a. Avoid new many small p2t::Point b. Add pod_vector for performance purpose --- core/2d/CCAutoPolygon.cpp | 50 ++++++------ core/base/pod_vector.h | 164 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+), 27 deletions(-) create mode 100644 core/base/pod_vector.h diff --git a/core/2d/CCAutoPolygon.cpp b/core/2d/CCAutoPolygon.cpp index b37c0386d09b..cb95889c635b 100644 --- a/core/2d/CCAutoPolygon.cpp +++ b/core/2d/CCAutoPolygon.cpp @@ -34,6 +34,7 @@ THE SOFTWARE. #include "clipper2/clipper.h" #include #include +#include "base/pod_vector.h" USING_NS_AX; @@ -579,20 +580,28 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po log("AUTOPOLYGON: cannot triangulate %s with less than 3 points", _filename.c_str()); return TrianglesCommand::Triangles(); } + + + std::vector p2pointsStorage; + p2pointsStorage.reserve(points.size()); std::vector p2points; - for (const auto& pt : points) + p2points.reserve(points.size()); + for (size_t i = 0; i < points.size(); ++i) { - p2t::Point* p = new p2t::Point(pt.x, pt.y); - p2points.emplace_back(p); + auto& pt = points[i]; + p2points.emplace_back(&p2pointsStorage.emplace_back((double)pt.x, (double)pt.y)); } + p2t::CDT cdt(p2points); cdt.Triangulate(); std::vector tris = cdt.GetTriangles(); // we won't know the size of verts and indices until we process all of the triangles! - std::vector verts; - std::vector indices; - + size_t indicesCount = tris.size() * 3; + ax::pod_vector vertsBuf; + vertsBuf.reserve(indicesCount / 2); + unsigned short* indicesBuf = new unsigned short[indicesCount]; + unsigned short idx = 0; unsigned short vdx = 0; @@ -607,7 +616,7 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po auto length = vdx; for (j = 0; j < length; j++) { - if (verts[j].vertices == v3) + if (vertsBuf[j].vertices == v3) { found = true; break; @@ -616,38 +625,25 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po if (found) { // if we found the same vertex, don't add to verts, but use the same vertex with indices - indices.emplace_back(j); - idx++; + indicesBuf[idx++] = j; } else { // vert does not exist yet, so we need to create a new one, auto c4b = Color4B::WHITE; auto t2f = Tex2F(0, 0); // don't worry about tex coords now, we calculate that later - V3F_C4B_T2F vert = {v3, c4b, t2f}; - verts.emplace_back(vert); - indices.emplace_back(vdx); - idx++; - vdx++; + + indicesBuf[idx++] = vdx++; + + vertsBuf.emplace(v3, c4b, t2f); } } } - for (auto&& j : p2points) - { - delete j; - }; - - // now that we know the size of verts and indices we can create the buffers - V3F_C4B_T2F* vertsBuf = new V3F_C4B_T2F[verts.size()]; - memcpy(vertsBuf, verts.data(), verts.size() * sizeof(V3F_C4B_T2F)); - - unsigned short* indicesBuf = new unsigned short[indices.size()]; - memcpy(indicesBuf, indices.data(), indices.size() * sizeof(short)); // Triangles should really use std::vector and not arrays for verts and indices. // Then the above memcpy would not be necessary - TrianglesCommand::Triangles triangles = {vertsBuf, indicesBuf, (unsigned int)verts.size(), - (unsigned int)indices.size()}; + TrianglesCommand::Triangles triangles = {vertsBuf.release_pointer(), indicesBuf, (unsigned int)vdx, + (unsigned int)idx}; return triangles; } diff --git a/core/base/pod_vector.h b/core/base/pod_vector.h new file mode 100644 index 000000000000..a4476f8e7efb --- /dev/null +++ b/core/base/pod_vector.h @@ -0,0 +1,164 @@ +/**************************************************************************** + Copyright (c) 2022 Bytedance Inc. + + https://axmolengine.github.io/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + The pod_vector concepts: + a. only accept pod type + b. support release memory ownership with `release_pointer` + c. support pod_allocater with C(realloc) or C++(new/delete) + b. resize operation no fill +*/ +#pragma once +#include +#include +#include +#include + +namespace ax +{ + +template +struct pod_allocator +{ + static void* reallocate(void* old_block, size_t old_count, size_t new_count) + { + if (old_count != new_count) + { + void* new_block = nullptr; + if (new_count) + { + new_block = ::operator new(new_count * sizeof(_Ty)); + if (old_block) + memcpy(new_block, old_block, (std::min)(old_count, new_count) * sizeof(_Ty)); + } + + ::operator delete(old_block); + return new_block; + } + return old_block; + } +}; + +template +struct pod_allocator<_Ty, true> +{ + static void* reallocate(void* old_block, size_t /*old_count*/, size_t new_count) + { + return ::realloc(old_block, new_count * sizeof(_Ty)); + } +}; + +template , + std::enable_if_t, int> = 0> +class pod_vector +{ +public: + using pointer = _Ty*; + using value_type = _Ty; + pod_vector() = default; + pod_vector(pod_vector const&) = delete; + pod_vector& operator=(pod_vector const&) = delete; + + pod_vector(pod_vector&& o) noexcept + { + std::swap(_Myfirst, o._Myfirst); + std::swap(_Mylast, o._Mylast); + std::swap(_Myend, o._Myend); + } + pod_vector& operator=(pod_vector&& o) noexcept + { + std::swap(_Myfirst, o._Myfirst); + std::swap(_Mylast, o._Mylast); + std::swap(_Myend, o._Myend); + return *this; + } + + ~pod_vector() { shrink_to_fit(0); } + + template + _Ty& emplace(_Args&&... args) noexcept + { + return *new (resize(this->size() + 1)) _Ty(std::forward<_Args>(args)...); + } + + void reserve(size_t new_cap) + { + if (this->capacity() < new_cap) + { + auto cur_size = this->size(); + _Reallocate_exactly(new_cap); + _Mylast = _Myfirst + cur_size; + } + } + + // return address of new last element + pointer resize(size_t new_size) + { + auto old_cap = this->capacity(); + if (old_cap < new_size) + _Reallocate_exactly((std::max)(old_cap + old_cap / 2, new_size)); + _Mylast = _Myfirst + new_size; + return _Mylast - 1; + } + + _Ty& operator[](size_t idx) { return _Myfirst[idx]; } + const _Ty& operator[](size_t idx) const { return _Myfirst[idx]; } + + size_t capacity() const noexcept { return _Myend - _Myfirst; } + size_t size() const noexcept { return _Mylast - _Myfirst; } + void clear() noexcept { _Mylast = _Myfirst; } + + void shrink_to_fit() { shrink_to_fit(this->size()); } + void shrink_to_fit(size_t new_size) + { + if (this->capacity() != new_size) + _Reallocate_exactly(new_size); + _Mylast = _Myfirst + new_size; + } + + // release memmory ownership + pointer release_pointer() noexcept + { + auto ptr = _Myfirst; + memset(this, 0, sizeof(*this)); + return ptr; + } + +private: + void _Reallocate_exactly(size_t new_cap) + { + auto new_block = (pointer)_Alty::reallocate(_Myfirst, _Myend - _Myfirst, new_cap); + if (new_block || 0 == new_cap) + { + _Myfirst = new_block; + _Myend = _Myfirst + new_cap; + } + else + throw std::bad_alloc{}; + } + + pointer _Myfirst = nullptr; + pointer _Mylast = nullptr; + pointer _Myend = nullptr; +}; +} // namespace ax From 4eda9c5b71af26c9950bd97d5238ee4daffaaa29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=80=E7=BA=BF=E7=81=B5=7CDeal?= Date: Sat, 8 Oct 2022 23:00:15 +0800 Subject: [PATCH 2/7] Fix ci --- core/2d/CCAutoPolygon.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/2d/CCAutoPolygon.cpp b/core/2d/CCAutoPolygon.cpp index cb95889c635b..2cb94a253097 100644 --- a/core/2d/CCAutoPolygon.cpp +++ b/core/2d/CCAutoPolygon.cpp @@ -5,6 +5,7 @@ Copyright (c) 2011 Zynga Inc. Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2022 @aismann; Peter Eismann, Germany; dreifrankensoft +Copyright (c) 2022 Bytedance Inc. https://axmolengine.github.io/ @@ -635,7 +636,7 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po indicesBuf[idx++] = vdx++; - vertsBuf.emplace(v3, c4b, t2f); + vertsBuf.emplace({v3, c4b, t2f}); } } } From 97b566a3158733b4574a7bba1d5884f237ab6a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=80=E7=BA=BF=E7=81=B5=7CDeal?= Date: Sat, 8 Oct 2022 23:11:06 +0800 Subject: [PATCH 3/7] Fix ci --- core/2d/CCAutoPolygon.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/2d/CCAutoPolygon.cpp b/core/2d/CCAutoPolygon.cpp index 2cb94a253097..182fba742945 100644 --- a/core/2d/CCAutoPolygon.cpp +++ b/core/2d/CCAutoPolygon.cpp @@ -597,7 +597,6 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po cdt.Triangulate(); std::vector tris = cdt.GetTriangles(); - // we won't know the size of verts and indices until we process all of the triangles! size_t indicesCount = tris.size() * 3; ax::pod_vector vertsBuf; vertsBuf.reserve(indicesCount / 2); @@ -636,13 +635,12 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po indicesBuf[idx++] = vdx++; - vertsBuf.emplace({v3, c4b, t2f}); + vertsBuf.emplace(V3F_C4B_T2F{v3, c4b, t2f}); } } } - // Triangles should really use std::vector and not arrays for verts and indices. - // Then the above memcpy would not be necessary + // Good concept: the pod_vector support release internal buffer ownership TrianglesCommand::Triangles triangles = {vertsBuf.release_pointer(), indicesBuf, (unsigned int)vdx, (unsigned int)idx}; return triangles; From 0943478bddce5b64fe1496d0a885858c2be99364 Mon Sep 17 00:00:00 2001 From: halx99 Date: Sun, 9 Oct 2022 17:07:40 +0800 Subject: [PATCH 4/7] Revert pod_vector use --- core/2d/CCAutoPolygon.cpp | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/core/2d/CCAutoPolygon.cpp b/core/2d/CCAutoPolygon.cpp index 182fba742945..36d9fcc2471a 100644 --- a/core/2d/CCAutoPolygon.cpp +++ b/core/2d/CCAutoPolygon.cpp @@ -597,11 +597,10 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po cdt.Triangulate(); std::vector tris = cdt.GetTriangles(); - size_t indicesCount = tris.size() * 3; - ax::pod_vector vertsBuf; - vertsBuf.reserve(indicesCount / 2); - unsigned short* indicesBuf = new unsigned short[indicesCount]; - + // we won't know the size of verts and indices until we process all of the triangles! + std::vector verts; + std::vector indices; + unsigned short idx = 0; unsigned short vdx = 0; @@ -616,7 +615,7 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po auto length = vdx; for (j = 0; j < length; j++) { - if (vertsBuf[j].vertices == v3) + if (verts[j].vertices == v3) { found = true; break; @@ -625,24 +624,34 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po if (found) { // if we found the same vertex, don't add to verts, but use the same vertex with indices - indicesBuf[idx++] = j; + indices.emplace_back(j); + idx++; } else { // vert does not exist yet, so we need to create a new one, auto c4b = Color4B::WHITE; auto t2f = Tex2F(0, 0); // don't worry about tex coords now, we calculate that later - - indicesBuf[idx++] = vdx++; - - vertsBuf.emplace(V3F_C4B_T2F{v3, c4b, t2f}); + V3F_C4B_T2F vert = {v3, c4b, t2f}; + verts.emplace_back(vert); + indices.emplace_back(vdx); + idx++; + vdx++; } } } - // Good concept: the pod_vector support release internal buffer ownership - TrianglesCommand::Triangles triangles = {vertsBuf.release_pointer(), indicesBuf, (unsigned int)vdx, - (unsigned int)idx}; + // now that we know the size of verts and indices we can create the buffers + V3F_C4B_T2F* vertsBuf = new V3F_C4B_T2F[verts.size()]; + memcpy(vertsBuf, verts.data(), verts.size() * sizeof(V3F_C4B_T2F)); + + unsigned short* indicesBuf = new unsigned short[indices.size()]; + memcpy(indicesBuf, indices.data(), indices.size() * sizeof(short)); + + // Triangles should really use std::vector and not arrays for verts and indices. + // Then the above memcpy would not be necessary + TrianglesCommand::Triangles triangles = {vertsBuf, indicesBuf, (unsigned int)verts.size(), + (unsigned int)indices.size()}; return triangles; } From cf1d5de68c4400626ffe163c6ee3f4357a38dea3 Mon Sep 17 00:00:00 2001 From: halx99 Date: Sun, 9 Oct 2022 17:12:50 +0800 Subject: [PATCH 5/7] pod_vector emplace_back implementation is copy from ms stl, not use currently needs unittests --- core/base/pod_vector.h | 257 ++++++++++++++++++++++++----------------- 1 file changed, 153 insertions(+), 104 deletions(-) diff --git a/core/base/pod_vector.h b/core/base/pod_vector.h index a4476f8e7efb..cf0eeb7d7204 100644 --- a/core/base/pod_vector.h +++ b/core/base/pod_vector.h @@ -1,8 +1,12 @@ /**************************************************************************** + Copyright (c) Microsoft Corporation. + + SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + Copyright (c) 2022 Bytedance Inc. https://axmolengine.github.io/ - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights @@ -25,140 +29,185 @@ a. only accept pod type b. support release memory ownership with `release_pointer` c. support pod_allocater with C(realloc) or C++(new/delete) - b. resize operation no fill + +Copy of https://github.com/microsoft/STL/blob/main/stl/inc/vector but for pod types and only provide 'emplace_back' + */ #pragma once #include #include #include #include +#include namespace ax { - template -struct pod_allocator -{ - static void* reallocate(void* old_block, size_t old_count, size_t new_count) - { - if (old_count != new_count) - { - void* new_block = nullptr; - if (new_count) - { - new_block = ::operator new(new_count * sizeof(_Ty)); - if (old_block) - memcpy(new_block, old_block, (std::min)(old_count, new_count) * sizeof(_Ty)); - } - - ::operator delete(old_block); - return new_block; - } - return old_block; - } +struct pod_allocator { + static _Ty* allocate(size_t count) { return (_Ty*)new uint8_t[count * sizeof(_Ty)]; } + static void deallocate(_Ty* pBlock) { delete[] (uint8_t*)pBlock; } }; template struct pod_allocator<_Ty, true> { - static void* reallocate(void* old_block, size_t /*old_count*/, size_t new_count) - { - return ::realloc(old_block, new_count * sizeof(_Ty)); - } -}; + static _Ty* allocate(size_t count) { return malloc(count * sizeof(_Ty)); } + static void deallocate(_Ty* pBlock) { free(pBlock); } + }; -template , +template , std::enable_if_t, int> = 0> -class pod_vector -{ +class pod_vector { public: - using pointer = _Ty*; - using value_type = _Ty; - pod_vector() = default; - pod_vector(pod_vector const&) = delete; - pod_vector& operator=(pod_vector const&) = delete; - pod_vector(pod_vector&& o) noexcept - { - std::swap(_Myfirst, o._Myfirst); - std::swap(_Mylast, o._Mylast); - std::swap(_Myend, o._Myend); - } - pod_vector& operator=(pod_vector&& o) noexcept - { - std::swap(_Myfirst, o._Myfirst); - std::swap(_Mylast, o._Mylast); - std::swap(_Myend, o._Myend); - return *this; + using pointer = _Ty*; + using value_type = _Ty; + using size_type = size_t; + pod_vector() = default; + pod_vector(pod_vector const&) = delete; + pod_vector& operator=(pod_vector const&) = delete; + + pod_vector(pod_vector&& o) noexcept + { + std::swap(_Myfirst, o._Myfirst); + std::swap(_Mylast, o._Mylast); + std::swap(_Myend, o._Myend); + } + pod_vector& operator=(pod_vector&& o) noexcept + { + std::swap(_Myfirst, o._Myfirst); + std::swap(_Mylast, o._Mylast); + std::swap(_Myend, o._Myend); + return *this; + } + + ~pod_vector() { _Tidy(); } + + template + _Ty& emplace_back(_Valty&&... _Val) noexcept + { + if (_Mylast != _Myend) + return *new (_Mylast++) _Ty(std::forward<_Valty>(_Val)...); + + return *_Emplace_back_reallocate(std::forward<_Valty>(_Val)...); + } + + void reserve(size_t new_cap) + { + if (new_cap > this->capacity()) + _Reallocate_exactly(new_cap); + } + + _Ty& operator[](size_t idx) { return _Myfirst[idx]; } + const _Ty& operator[](size_t idx) const { return _Myfirst[idx]; } + + size_t capacity() const noexcept { return _Myend - _Myfirst; } + size_t size() const noexcept { return _Mylast - _Myfirst; } + size_type max_size() const noexcept { return (std::numeric_limits::max)(); } + void clear() noexcept { _Mylast = _Myfirst; } + + void shrink_to_fit() + { // reduce capacity to size, provide strong guarantee + const pointer _Oldlast = _Mylast; + if (_Oldlast != _Myend) + { // something to do + const pointer _Oldfirst = _Myfirst; + if (_Oldfirst == _Oldlast) + _Tidy(); + else + _Reallocate_exactly(static_cast(_Oldlast - _Oldfirst)); } + } - ~pod_vector() { shrink_to_fit(0); } + // release memmory ownership + pointer release_pointer() noexcept + { + auto ptr = _Myfirst; + memset(this, 0, sizeof(*this)); + return ptr; + } - template - _Ty& emplace(_Args&&... args) noexcept - { - return *new (resize(this->size() + 1)) _Ty(std::forward<_Args>(args)...); - } +private: + template + pointer _Emplace_back_reallocate(_Valty&&... _Val) + { + const auto _Oldsize = static_cast(_Mylast - _Myfirst); - void reserve(size_t new_cap) + if (_Oldsize == max_size()) { - if (this->capacity() < new_cap) - { - auto cur_size = this->size(); - _Reallocate_exactly(new_cap); - _Mylast = _Myfirst + cur_size; - } + throw std::length_error("pod_vector too long"); } - // return address of new last element - pointer resize(size_t new_size) - { - auto old_cap = this->capacity(); - if (old_cap < new_size) - _Reallocate_exactly((std::max)(old_cap + old_cap / 2, new_size)); - _Mylast = _Myfirst + new_size; - return _Mylast - 1; - } + const size_type _Newsize = _Oldsize + 1; + const size_type _Newcapacity = _Calculate_growth(_Newsize); - _Ty& operator[](size_t idx) { return _Myfirst[idx]; } - const _Ty& operator[](size_t idx) const { return _Myfirst[idx]; } + const pointer _Newvec = _Alty::allocate(_Newcapacity); + const pointer _Constructed_last = _Newvec + _Oldsize + 1; + pointer _Constructed_first = _Constructed_last; - size_t capacity() const noexcept { return _Myend - _Myfirst; } - size_t size() const noexcept { return _Mylast - _Myfirst; } - void clear() noexcept { _Mylast = _Myfirst; } + new ((void*)(_Newvec + _Oldsize)) _Ty(std::forward<_Valty>(_Val)...); + _Constructed_first = _Newvec + _Oldsize; - void shrink_to_fit() { shrink_to_fit(this->size()); } - void shrink_to_fit(size_t new_size) - { - if (this->capacity() != new_size) - _Reallocate_exactly(new_size); - _Mylast = _Myfirst + new_size; - } + // at back, provide strong guarantee + std::move(_Myfirst, _Mylast, _Newvec); - // release memmory ownership - pointer release_pointer() noexcept - { - auto ptr = _Myfirst; - memset(this, 0, sizeof(*this)); - return ptr; - } + _Change_array(_Newvec, _Newsize, _Newcapacity); + return _Newvec + _Oldsize; + } -private: - void _Reallocate_exactly(size_t new_cap) - { - auto new_block = (pointer)_Alty::reallocate(_Myfirst, _Myend - _Myfirst, new_cap); - if (new_block || 0 == new_cap) - { - _Myfirst = new_block; - _Myend = _Myfirst + new_cap; - } - else - throw std::bad_alloc{}; + void _Reallocate_exactly(size_t _Newcapacity) + { + const auto _Size = static_cast(_Mylast - _Myfirst); + + const pointer _Newvec = _Alty::allocate(_Newcapacity); + + std::copy(_Myfirst, _Mylast, _Newvec); + + _Change_array(_Newvec, _Size, _Newcapacity); + } + + void _Change_array(const pointer _Newvec, const size_type _Newsize, const size_type _Newcapacity) + { + if (_Myfirst) + _Alty::deallocate(_Myfirst /*, static_cast(_Myend - _Myfirst)*/); + + _Myfirst = _Newvec; + _Mylast = _Newvec + _Newsize; + _Myend = _Newvec + _Newcapacity; + } + + size_type _Calculate_growth(const size_type _Newsize) const + { + // given _Oldcapacity and _Newsize, calculate geometric growth + const size_type _Oldcapacity = capacity(); + const auto _Max = max_size(); + + if (_Oldcapacity > _Max - _Oldcapacity / 2) + return _Max; // geometric growth would overflow + + const size_type _Geometric = _Oldcapacity + (_Oldcapacity >> 1); + + if (_Geometric < _Newsize) + return _Newsize; // geometric growth would be insufficient + + return _Geometric; // geometric growth is sufficient + } + + + void _Tidy() noexcept + { // free all storage + if (_Myfirst) + { // destroy and deallocate old array + _Alty::deallocate(_Myfirst/*, static_cast(_Myend - _Myfirst)*/); + + _Myfirst = nullptr; + _Mylast = nullptr; + _Myend = nullptr; } + } - pointer _Myfirst = nullptr; - pointer _Mylast = nullptr; - pointer _Myend = nullptr; + pointer _Myfirst = nullptr; + pointer _Mylast = nullptr; + pointer _Myend = nullptr; }; -} // namespace ax +} // namespace ax From bb20c91c6a244afa18e52fd31e32b463245846f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=80=E7=BA=BF=E7=81=B5=7CDeal?= Date: Sun, 9 Oct 2022 17:21:18 +0800 Subject: [PATCH 6/7] Delete pod_vector.h --- core/base/pod_vector.h | 213 ----------------------------------------- 1 file changed, 213 deletions(-) delete mode 100644 core/base/pod_vector.h diff --git a/core/base/pod_vector.h b/core/base/pod_vector.h deleted file mode 100644 index cf0eeb7d7204..000000000000 --- a/core/base/pod_vector.h +++ /dev/null @@ -1,213 +0,0 @@ -/**************************************************************************** - Copyright (c) Microsoft Corporation. - - SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - - Copyright (c) 2022 Bytedance Inc. - - https://axmolengine.github.io/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - The pod_vector concepts: - a. only accept pod type - b. support release memory ownership with `release_pointer` - c. support pod_allocater with C(realloc) or C++(new/delete) - -Copy of https://github.com/microsoft/STL/blob/main/stl/inc/vector but for pod types and only provide 'emplace_back' - -*/ -#pragma once -#include -#include -#include -#include -#include - -namespace ax -{ -template -struct pod_allocator { - static _Ty* allocate(size_t count) { return (_Ty*)new uint8_t[count * sizeof(_Ty)]; } - static void deallocate(_Ty* pBlock) { delete[] (uint8_t*)pBlock; } -}; - -template -struct pod_allocator<_Ty, true> -{ - static _Ty* allocate(size_t count) { return malloc(count * sizeof(_Ty)); } - static void deallocate(_Ty* pBlock) { free(pBlock); } - }; - -template , - std::enable_if_t, int> = 0> -class pod_vector { -public: - - using pointer = _Ty*; - using value_type = _Ty; - using size_type = size_t; - pod_vector() = default; - pod_vector(pod_vector const&) = delete; - pod_vector& operator=(pod_vector const&) = delete; - - pod_vector(pod_vector&& o) noexcept - { - std::swap(_Myfirst, o._Myfirst); - std::swap(_Mylast, o._Mylast); - std::swap(_Myend, o._Myend); - } - pod_vector& operator=(pod_vector&& o) noexcept - { - std::swap(_Myfirst, o._Myfirst); - std::swap(_Mylast, o._Mylast); - std::swap(_Myend, o._Myend); - return *this; - } - - ~pod_vector() { _Tidy(); } - - template - _Ty& emplace_back(_Valty&&... _Val) noexcept - { - if (_Mylast != _Myend) - return *new (_Mylast++) _Ty(std::forward<_Valty>(_Val)...); - - return *_Emplace_back_reallocate(std::forward<_Valty>(_Val)...); - } - - void reserve(size_t new_cap) - { - if (new_cap > this->capacity()) - _Reallocate_exactly(new_cap); - } - - _Ty& operator[](size_t idx) { return _Myfirst[idx]; } - const _Ty& operator[](size_t idx) const { return _Myfirst[idx]; } - - size_t capacity() const noexcept { return _Myend - _Myfirst; } - size_t size() const noexcept { return _Mylast - _Myfirst; } - size_type max_size() const noexcept { return (std::numeric_limits::max)(); } - void clear() noexcept { _Mylast = _Myfirst; } - - void shrink_to_fit() - { // reduce capacity to size, provide strong guarantee - const pointer _Oldlast = _Mylast; - if (_Oldlast != _Myend) - { // something to do - const pointer _Oldfirst = _Myfirst; - if (_Oldfirst == _Oldlast) - _Tidy(); - else - _Reallocate_exactly(static_cast(_Oldlast - _Oldfirst)); - } - } - - // release memmory ownership - pointer release_pointer() noexcept - { - auto ptr = _Myfirst; - memset(this, 0, sizeof(*this)); - return ptr; - } - -private: - template - pointer _Emplace_back_reallocate(_Valty&&... _Val) - { - const auto _Oldsize = static_cast(_Mylast - _Myfirst); - - if (_Oldsize == max_size()) - { - throw std::length_error("pod_vector too long"); - } - - const size_type _Newsize = _Oldsize + 1; - const size_type _Newcapacity = _Calculate_growth(_Newsize); - - const pointer _Newvec = _Alty::allocate(_Newcapacity); - const pointer _Constructed_last = _Newvec + _Oldsize + 1; - pointer _Constructed_first = _Constructed_last; - - new ((void*)(_Newvec + _Oldsize)) _Ty(std::forward<_Valty>(_Val)...); - _Constructed_first = _Newvec + _Oldsize; - - // at back, provide strong guarantee - std::move(_Myfirst, _Mylast, _Newvec); - - _Change_array(_Newvec, _Newsize, _Newcapacity); - return _Newvec + _Oldsize; - } - - void _Reallocate_exactly(size_t _Newcapacity) - { - const auto _Size = static_cast(_Mylast - _Myfirst); - - const pointer _Newvec = _Alty::allocate(_Newcapacity); - - std::copy(_Myfirst, _Mylast, _Newvec); - - _Change_array(_Newvec, _Size, _Newcapacity); - } - - void _Change_array(const pointer _Newvec, const size_type _Newsize, const size_type _Newcapacity) - { - if (_Myfirst) - _Alty::deallocate(_Myfirst /*, static_cast(_Myend - _Myfirst)*/); - - _Myfirst = _Newvec; - _Mylast = _Newvec + _Newsize; - _Myend = _Newvec + _Newcapacity; - } - - size_type _Calculate_growth(const size_type _Newsize) const - { - // given _Oldcapacity and _Newsize, calculate geometric growth - const size_type _Oldcapacity = capacity(); - const auto _Max = max_size(); - - if (_Oldcapacity > _Max - _Oldcapacity / 2) - return _Max; // geometric growth would overflow - - const size_type _Geometric = _Oldcapacity + (_Oldcapacity >> 1); - - if (_Geometric < _Newsize) - return _Newsize; // geometric growth would be insufficient - - return _Geometric; // geometric growth is sufficient - } - - - void _Tidy() noexcept - { // free all storage - if (_Myfirst) - { // destroy and deallocate old array - _Alty::deallocate(_Myfirst/*, static_cast(_Myend - _Myfirst)*/); - - _Myfirst = nullptr; - _Mylast = nullptr; - _Myend = nullptr; - } - } - - pointer _Myfirst = nullptr; - pointer _Mylast = nullptr; - pointer _Myend = nullptr; -}; -} // namespace ax From 8d6cb5af6525cda3fb28da9bfc8e00ab6b895409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=80=E7=BA=BF=E7=81=B5=7CDeal?= Date: Sun, 9 Oct 2022 17:22:22 +0800 Subject: [PATCH 7/7] Update CCAutoPolygon.cpp --- core/2d/CCAutoPolygon.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/core/2d/CCAutoPolygon.cpp b/core/2d/CCAutoPolygon.cpp index 36d9fcc2471a..694e354f9667 100644 --- a/core/2d/CCAutoPolygon.cpp +++ b/core/2d/CCAutoPolygon.cpp @@ -35,7 +35,6 @@ THE SOFTWARE. #include "clipper2/clipper.h" #include #include -#include "base/pod_vector.h" USING_NS_AX;