Skip to content

Commit bb0e22a

Browse files
committed
[libc++] Introduce a standalone __scope_guard and use it in <string>
1 parent 7c69491 commit bb0e22a

File tree

4 files changed

+60
-13
lines changed

4 files changed

+60
-13
lines changed

libcxx/include/__flat_map/flat_map.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
#include <__type_traits/is_nothrow_constructible.h>
5151
#include <__type_traits/is_same.h>
5252
#include <__type_traits/maybe_const.h>
53-
#include <__utility/exception_guard.h>
53+
#include <__utility/scope_guard.h>
5454
#include <__utility/pair.h>
5555
#include <initializer_list>
5656
#include <stdexcept>

libcxx/include/__utility/exception_guard.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __exception_guard<_Rollback> __make_exce
137137
return __exception_guard<_Rollback>(std::move(__rollback));
138138
}
139139

140-
template <class _Rollback>
141-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __exception_guard_exceptions<_Rollback>
142-
__make_scope_guard(_Rollback __rollback) {
143-
return __exception_guard_exceptions<_Rollback>(std::move(__rollback));
144-
}
145-
146140
_LIBCPP_END_NAMESPACE_STD
147141

148142
_LIBCPP_POP_MACROS
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP___UTILITY_SCOPE_GUARD_H
11+
#define _LIBCPP___UTILITY_SCOPE_GUARD_H
12+
13+
#include <__config>
14+
#include <__utility/move.h>
15+
16+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
17+
# pragma GCC system_header
18+
#endif
19+
20+
_LIBCPP_PUSH_MACROS
21+
#include <__undef_macros>
22+
23+
_LIBCPP_BEGIN_NAMESPACE_STD
24+
25+
template <class _Func>
26+
class __scope_guard {
27+
_Func __func_;
28+
29+
public:
30+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __scope_guard(_Func __func) : __func_(std::move(__func)) {}
31+
_LIBCPP_HIDE_FROM_ABI ~__scope_guard() { __func_(); }
32+
33+
__scope_guard(const __scope_guard&) = delete;
34+
__scope_guard& operator=(const __scope_guard&) = delete;
35+
};
36+
37+
template <class _Func>
38+
__scope_guard<_Func> __make_scope_guard(_Func __func) {
39+
return __scope_guard<_Func>(std::move(__func));
40+
}
41+
42+
_LIBCPP_END_NAMESPACE_STD
43+
44+
_LIBCPP_POP_MACROS
45+
46+
#endif // _LIBCPP___UTILITY_SCOPE_GUARD_H

libcxx/include/string

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,7 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
638638
#include <__utility/forward.h>
639639
#include <__utility/is_pointer_in_range.h>
640640
#include <__utility/move.h>
641+
#include <__utility/scope_guard.h>
641642
#include <__utility/swap.h>
642643
#include <__utility/unreachable.h>
643644
#include <climits>
@@ -929,6 +930,13 @@ private:
929930

930931
_LIBCPP_COMPRESSED_PAIR(__rep, __rep_, allocator_type, __alloc_);
931932

933+
// annotate the string with its size() at scope exit. The string has to be in a valid state at that point.
934+
struct __annotate_new_size {
935+
basic_string& __str_;
936+
937+
void operator()() { __str_.__annotate_new(__str_.size()); }
938+
};
939+
932940
// Construct a string with the given allocator and enough storage to hold `__size` characters, but
933941
// don't initialize the characters. The contents of the string, including the null terminator, must be
934942
// initialized separately.
@@ -2169,6 +2177,7 @@ private:
21692177
__alloc_ = __str.__alloc_;
21702178
} else {
21712179
__annotate_delete();
2180+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
21722181
allocator_type __a = __str.__alloc_;
21732182
auto __allocation = std::__allocate_at_least(__a, __str.__get_long_cap());
21742183
__begin_lifetime(__allocation.ptr, __allocation.count);
@@ -2178,7 +2187,6 @@ private:
21782187
__set_long_pointer(__allocation.ptr);
21792188
__set_long_cap(__allocation.count);
21802189
__set_long_size(__str.size());
2181-
__annotate_new(__get_long_size());
21822190
}
21832191
}
21842192
}
@@ -2506,6 +2514,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
25062514
size_type __cap =
25072515
__old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1;
25082516
__annotate_delete();
2517+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
25092518
auto __allocation = std::__allocate_at_least(__alloc_, __cap + 1);
25102519
pointer __p = __allocation.ptr;
25112520
__begin_lifetime(__p, __allocation.count);
@@ -2524,7 +2533,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
25242533
__old_sz = __n_copy + __n_add + __sec_cp_sz;
25252534
__set_long_size(__old_sz);
25262535
traits_type::assign(__p[__old_sz], value_type());
2527-
__annotate_new(__old_sz);
25282536
}
25292537

25302538
// __grow_by is deprecated because it does not set the size. It may not update the size when the size is changed, and it
@@ -2548,7 +2556,6 @@ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Trait
25482556
pointer __old_p = __get_pointer();
25492557
size_type __cap =
25502558
__old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1;
2551-
__annotate_delete();
25522559
auto __allocation = std::__allocate_at_least(__alloc_, __cap + 1);
25532560
pointer __p = __allocation.ptr;
25542561
__begin_lifetime(__p, __allocation.count);
@@ -2573,11 +2580,12 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_without_replace(
25732580
size_type __n_copy,
25742581
size_type __n_del,
25752582
size_type __n_add) {
2583+
__annotate_delete();
2584+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
25762585
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
25772586
__grow_by(__old_cap, __delta_cap, __old_sz, __n_copy, __n_del, __n_add);
25782587
_LIBCPP_SUPPRESS_DEPRECATED_POP
25792588
__set_long_size(__old_sz - __n_del + __n_add);
2580-
__annotate_new(__old_sz - __n_del + __n_add);
25812589
}
25822590

25832591
// assign
@@ -3367,6 +3375,7 @@ template <class _CharT, class _Traits, class _Allocator>
33673375
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void
33683376
basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target_capacity) {
33693377
__annotate_delete();
3378+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
33703379
size_type __cap = capacity();
33713380
size_type __sz = size();
33723381

@@ -3398,7 +3407,6 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
33983407
// due to swapping the elements.
33993408
if (__allocation.count - 1 > __target_capacity) {
34003409
__alloc_traits::deallocate(__alloc_, __allocation.ptr, __allocation.count);
3401-
__annotate_new(__sz); // Undoes the __annotate_delete()
34023410
return;
34033411
}
34043412
__new_data = __allocation.ptr;
@@ -3423,7 +3431,6 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
34233431
__set_long_pointer(__new_data);
34243432
} else
34253433
__set_short_size(__sz);
3426-
__annotate_new(__sz);
34273434
}
34283435

34293436
template <class _CharT, class _Traits, class _Allocator>

0 commit comments

Comments
 (0)