Commit 1299eec8 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Let FBVector.h support -fno-exceptions

Summary: [Folly] Let `folly/FBVector.h` support `-fno-exceptions`. Same mechanism as with `folly/small_vector.h`.

Reviewed By: Orvid

Differential Revision: D15158754

fbshipit-source-id: fe67d608a5b38258d05718efae502b7277e1f4ee
parent be621139
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <folly/FormatTraits.h> #include <folly/FormatTraits.h>
#include <folly/Likely.h> #include <folly/Likely.h>
#include <folly/ScopeGuard.h>
#include <folly/Traits.h> #include <folly/Traits.h>
#include <folly/lang/Exception.h> #include <folly/lang/Exception.h>
#include <folly/memory/Malloc.h> #include <folly/memory/Malloc.h>
...@@ -174,12 +175,9 @@ class fbvector { ...@@ -174,12 +175,9 @@ class fbvector {
void reset(size_type newCap) { void reset(size_type newCap) {
destroy(); destroy();
try { auto rollback = makeGuard([&] { init(0); });
init(newCap); init(newCap);
} catch (...) { rollback.dismiss();
init(0);
throw;
}
} }
void reset() { // same as reset(0) void reset() { // same as reset(0)
destroy(); destroy();
...@@ -429,15 +427,12 @@ class fbvector { ...@@ -429,15 +427,12 @@ class fbvector {
Args&&... args) { Args&&... args) {
auto b = dest; auto b = dest;
auto e = dest + sz; auto e = dest + sz;
try { auto rollback = makeGuard([&] { S_destroy_range_a(a, dest, b); });
for (; b != e; ++b) { for (; b != e; ++b) {
std::allocator_traits<Allocator>::construct( std::allocator_traits<Allocator>::construct(
a, b, std::forward<Args>(args)...); a, b, std::forward<Args>(args)...);
}
} catch (...) {
S_destroy_range_a(a, dest, b);
throw;
} }
rollback.dismiss();
} }
// optimized // optimized
...@@ -449,31 +444,27 @@ class fbvector { ...@@ -449,31 +444,27 @@ class fbvector {
} else { } else {
auto b = dest; auto b = dest;
auto e = dest + n; auto e = dest + n;
try { auto rollback = makeGuard([&] {
for (; b != e; ++b) {
S_construct(b);
}
} catch (...) {
--b; --b;
for (; b >= dest; --b) { for (; b >= dest; --b) {
b->~T(); b->~T();
} }
throw; });
for (; b != e; ++b) {
S_construct(b);
} }
rollback.dismiss();
} }
} }
static void S_uninitialized_fill_n(T* dest, size_type n, const T& value) { static void S_uninitialized_fill_n(T* dest, size_type n, const T& value) {
auto b = dest; auto b = dest;
auto e = dest + n; auto e = dest + n;
try { auto rollback = makeGuard([&] { S_destroy_range(dest, b); });
for (; b != e; ++b) { for (; b != e; ++b) {
S_construct(b, value); S_construct(b, value);
}
} catch (...) {
S_destroy_range(dest, b);
throw;
} }
rollback.dismiss();
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
...@@ -519,28 +510,22 @@ class fbvector { ...@@ -519,28 +510,22 @@ class fbvector {
template <typename It> template <typename It>
static void S_uninitialized_copy_a(Allocator& a, T* dest, It first, It last) { static void S_uninitialized_copy_a(Allocator& a, T* dest, It first, It last) {
auto b = dest; auto b = dest;
try { auto rollback = makeGuard([&] { S_destroy_range_a(a, dest, b); });
for (; first != last; ++first, ++b) { for (; first != last; ++first, ++b) {
std::allocator_traits<Allocator>::construct(a, b, *first); std::allocator_traits<Allocator>::construct(a, b, *first);
}
} catch (...) {
S_destroy_range_a(a, dest, b);
throw;
} }
rollback.dismiss();
} }
// optimized // optimized
template <typename It> template <typename It>
static void S_uninitialized_copy(T* dest, It first, It last) { static void S_uninitialized_copy(T* dest, It first, It last) {
auto b = dest; auto b = dest;
try { auto rollback = makeGuard([&] { S_destroy_range(dest, b); });
for (; first != last; ++first, ++b) { for (; first != last; ++first, ++b) {
S_construct(b, *first); S_construct(b, *first);
}
} catch (...) {
S_destroy_range(dest, b);
throw;
} }
rollback.dismiss();
} }
static void static void
...@@ -1002,11 +987,10 @@ class fbvector { ...@@ -1002,11 +987,10 @@ class fbvector {
auto newCap = folly::goodMallocSize(n * sizeof(T)) / sizeof(T); auto newCap = folly::goodMallocSize(n * sizeof(T)) / sizeof(T);
auto newB = M_allocate(newCap); auto newB = M_allocate(newCap);
try { {
auto rollback = makeGuard([&] { M_deallocate(newB, newCap); });
M_relocate(newB); M_relocate(newB);
} catch (...) { rollback.dismiss();
M_deallocate(newB, newCap);
throw;
} }
if (impl_.b_) { if (impl_.b_) {
M_deallocate(impl_.b_, size_type(impl_.z_ - impl_.b_)); M_deallocate(impl_.b_, size_type(impl_.z_ - impl_.b_));
...@@ -1039,15 +1023,25 @@ class fbvector { ...@@ -1039,15 +1023,25 @@ class fbvector {
impl_.z_ += newCap - oldCap; impl_.z_ += newCap - oldCap;
} else { } else {
T* newB; // intentionally uninitialized T* newB; // intentionally uninitialized
try { if (!catch_exception(
newB = M_allocate(newCap); [&] {
try { newB = M_allocate(newCap);
M_relocate(newB); return true;
} catch (...) { },
M_deallocate(newB, newCap); [&] { //
return; // swallow the error return false;
} })) {
} catch (...) { return;
}
if (!catch_exception(
[&] {
M_relocate(newB);
return true;
},
[&] {
M_deallocate(newB, newCap);
return false;
})) {
return; return;
} }
if (impl_.b_) { if (impl_.b_) {
...@@ -1251,7 +1245,8 @@ class fbvector { ...@@ -1251,7 +1245,8 @@ class fbvector {
size_type sz = byte_sz / sizeof(T); size_type sz = byte_sz / sizeof(T);
auto newB = M_allocate(sz); auto newB = M_allocate(sz);
auto newE = newB + size(); auto newE = newB + size();
try { {
auto rollback1 = makeGuard([&] { M_deallocate(newB, sz); });
if (folly::IsRelocatable<T>::value && usingStdAllocator) { if (folly::IsRelocatable<T>::value && usingStdAllocator) {
// For linear memory access, relocate before construction. // For linear memory access, relocate before construction.
// By the test condition, relocate is noexcept. // By the test condition, relocate is noexcept.
...@@ -1264,16 +1259,11 @@ class fbvector { ...@@ -1264,16 +1259,11 @@ class fbvector {
} else { } else {
M_construct(newE, std::forward<Args>(args)...); M_construct(newE, std::forward<Args>(args)...);
++newE; ++newE;
try { auto rollback2 = makeGuard([&] { M_destroy(newE - 1); });
M_relocate(newB); M_relocate(newB);
} catch (...) { rollback2.dismiss();
M_destroy(newE - 1);
throw;
}
} }
} catch (...) { rollback1.dismiss();
M_deallocate(newB, sz);
throw;
} }
if (impl_.b_) { if (impl_.b_) {
M_deallocate(impl_.b_, size()); M_deallocate(impl_.b_, size());
...@@ -1403,15 +1393,16 @@ class fbvector { ...@@ -1403,15 +1393,16 @@ class fbvector {
impl_.e_ += n; impl_.e_ += n;
} else { } else {
D_uninitialized_move_a(impl_.e_, impl_.e_ - n, impl_.e_); D_uninitialized_move_a(impl_.e_, impl_.e_ - n, impl_.e_);
try { {
auto rollback = makeGuard([&] {
D_destroy_range_a(impl_.e_ - n, impl_.e_ + n);
impl_.e_ -= n;
});
std::copy_backward( std::copy_backward(
std::make_move_iterator(position), std::make_move_iterator(position),
std::make_move_iterator(impl_.e_ - n), std::make_move_iterator(impl_.e_ - n),
impl_.e_); impl_.e_);
} catch (...) { rollback.dismiss();
D_destroy_range_a(impl_.e_ - n, impl_.e_ + n);
impl_.e_ -= n;
throw;
} }
impl_.e_ += n; impl_.e_ += n;
D_destroy_range_a(position, position + n); D_destroy_range_a(position, position + n);
...@@ -1432,11 +1423,12 @@ class fbvector { ...@@ -1432,11 +1423,12 @@ class fbvector {
assert(n != 0); assert(n != 0);
relocate_move(ledge, impl_.b_, impl_.b_ + idx); relocate_move(ledge, impl_.b_, impl_.b_ + idx);
try { {
auto rollback = makeGuard([&] { //
relocate_undo(ledge, impl_.b_, impl_.b_ + idx);
});
relocate_move(ledge + idx + n, impl_.b_ + idx, impl_.e_); relocate_move(ledge + idx + n, impl_.b_ + idx, impl_.e_);
} catch (...) { rollback.dismiss();
relocate_undo(ledge, impl_.b_, impl_.b_ + idx);
throw;
} }
relocate_done(ledge, impl_.b_, impl_.b_ + idx); relocate_done(ledge, impl_.b_, impl_.b_ + idx);
relocate_done(ledge + idx + n, impl_.b_ + idx, impl_.e_); relocate_done(ledge + idx + n, impl_.b_ + idx, impl_.e_);
...@@ -1508,30 +1500,32 @@ class fbvector { ...@@ -1508,30 +1500,32 @@ class fbvector {
} }
T* start = b + idx; T* start = b + idx;
try { {
// construct the inserted elements auto rollback = makeGuard([&] {
constructFunc(start); if (fresh) {
} catch (...) { M_deallocate(b, newCap);
if (fresh) {
M_deallocate(b, newCap);
} else {
if (!at_end) {
undo_window(position, n);
} else { } else {
impl_.e_ -= n; if (!at_end) {
undo_window(position, n);
} else {
impl_.e_ -= n;
}
} }
} });
throw; // construct the inserted elements
constructFunc(start);
rollback.dismiss();
} }
if (fresh) { if (fresh) {
try { {
auto rollback = makeGuard([&] {
// delete the inserted elements (exception has been thrown)
destroyFunc(start);
M_deallocate(b, newCap);
});
wrap_frame(b, idx, n); wrap_frame(b, idx, n);
} catch (...) { rollback.dismiss();
// delete the inserted elements (exception has been thrown)
destroyFunc(start);
M_deallocate(b, newCap);
throw;
} }
if (impl_.b_) { if (impl_.b_) {
M_deallocate(impl_.b_, capacity()); M_deallocate(impl_.b_, capacity());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment