From 88c2baa20b4cf39162fa824bef7a50cbef7c7958 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 3 Dec 2012 15:42:15 +0000 Subject: [PATCH] Merged revision(s) 81684-81685 from trunk: For fixed size arrays upon constructor exception thrown destroy correctly. ........ Minor cosmetic change in detail array_deleter ........ [SVN r81695] --- .../boost/smart_ptr/detail/array_deleter.hpp | 156 ++++++++++++------ test/allocate_shared_array_throws_test.cpp | 16 ++ test/make_shared_array_throws_test.cpp | 16 ++ 3 files changed, 135 insertions(+), 53 deletions(-) diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 5d89dd8..b07b00a 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012 Glen Joseph Fernandes * glenfe at live dot com * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt * or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP @@ -19,58 +19,83 @@ namespace boost { template class array_deleter { public: - array_deleter(std::size_t size) + array_deleter(std::size_t size) : size(size), object(0) { } ~array_deleter() { - destroy(); + destroy(size); } void construct(T* memory) { - object = memory; - for (std::size_t i = 0; i < size; i++) { - void* p1 = object + i; - ::new(p1) T(); + std::size_t i = 0; + try { + for (object = memory; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(); + } + } catch (...) { + destroy(i); + throw; } } #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) template void construct(T* memory, Args&&... args) { - object = memory; - for (std::size_t i = 0; i < size; i++) { - void* p1 = object + i; - ::new(p1) T(args...); + std::size_t i = 0; + try { + for (object = memory; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(args...); + } + } catch (...) { + destroy(i); + throw; } } #endif void construct_list(T* memory, const T* list) { - object = memory; - for (std::size_t i = 0; i < size; i++) { - void* p1 = object + i; - ::new(p1) T(list[i]); + std::size_t i = 0; + try { + for (object = memory; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i]); + } + } catch (...) { + destroy(i); + throw; } } void construct_list(T* memory, const T* list, std::size_t n) { - object = memory; - for (std::size_t i = 0; i < size; i++) { - void* p1 = object + i; - ::new(p1) T(list[i % n]); + std::size_t i = 0; + try { + for (object = memory; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % n]); + } + } catch (...) { + destroy(i); + throw; } } void construct_noinit(T* memory) { - object = memory; - for (std::size_t i = 0; i < size; i++) { - void* p1 = object + i; - ::new(p1) T; + std::size_t i = 0; + try { + for (object = memory; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T; + } + } catch (...) { + destroy(i); + throw; } } void operator()(const void*) { - destroy(); + destroy(size); } private: - void destroy() { + void destroy(std::size_t n) { if (object) { - for (std::size_t i = size; i > 0; ) { + for (std::size_t i = n; i > 0; ) { object[--i].~T(); } object = 0; @@ -82,57 +107,82 @@ namespace boost { template class array_deleter { public: - array_deleter() + array_deleter() : object(0) { } ~array_deleter() { - destroy(); + destroy(N); } void construct(T* memory) { - object = memory; - for (std::size_t i = 0; i < N; i++) { - void* p1 = object + i; - ::new(p1) T(); + std::size_t i = 0; + try { + for (object = memory; i < N; i++) { + void* p1 = memory + i; + ::new(p1) T(); + } + } catch (...) { + destroy(i); + throw; } } #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) template void construct(T* memory, Args&&... args) { - object = memory; - for (std::size_t i = 0; i < N; i++) { - void* p1 = object + i; - ::new(p1) T(args...); + std::size_t i = 0; + try { + for (object = memory; i < N; i++) { + void* p1 = memory + i; + ::new(p1) T(args...); + } + } catch (...) { + destroy(i); + throw; } } #endif void construct_list(T* memory, const T* list) { - object = memory; - for (std::size_t i = 0; i < N; i++) { - void* p1 = object + i; - ::new(p1) T(list[i]); + std::size_t i = 0; + try { + for (object = memory; i < N; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i]); + } + } catch (...) { + destroy(i); + throw; } } void construct_list(T* memory, const T* list, std::size_t n) { - object = memory; - for (std::size_t i = 0; i < N; i++) { - void* p1 = object + i; - ::new(p1) T(list[i % n]); + std::size_t i = 0; + try { + for (object = memory; i < N; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % n]); + } + } catch (...) { + destroy(i); + throw; } } void construct_noinit(T* memory) { - object = memory; - for (std::size_t i = 0; i < N; i++) { - void* p1 = object + i; - ::new(p1) T; + std::size_t i = 0; + try { + for (object = memory; i < N; i++) { + void* p1 = memory + i; + ::new(p1) T; + } + } catch (...) { + destroy(i); + throw; } } void operator()(const void*) { - destroy(); + destroy(N); } private: - void destroy() { + void destroy(std::size_t n) { if (object) { - for (std::size_t i = N; i > 0; ) { + for (std::size_t i = n; i > 0; ) { object[--i].~T(); } object = 0; diff --git a/test/allocate_shared_array_throws_test.cpp b/test/allocate_shared_array_throws_test.cpp index d52104c..65a7985 100644 --- a/test/allocate_shared_array_throws_test.cpp +++ b/test/allocate_shared_array_throws_test.cpp @@ -43,5 +43,21 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + try { + boost::allocate_shared(std::allocator()); + BOOST_ERROR("allocate_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + try { + boost::allocate_shared(std::allocator()); + BOOST_ERROR("allocate_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } +#endif return boost::report_errors(); } diff --git a/test/make_shared_array_throws_test.cpp b/test/make_shared_array_throws_test.cpp index 7e06d41..4faf193 100644 --- a/test/make_shared_array_throws_test.cpp +++ b/test/make_shared_array_throws_test.cpp @@ -43,6 +43,22 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + try { + boost::make_shared(); + BOOST_ERROR("make_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + try { + boost::make_shared(); + BOOST_ERROR("make_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } +#endif BOOST_TEST(type::instances == 0); try { boost::make_shared_noinit(6);