@@ -54,34 +54,20 @@ inline void set_option(SEXP name, SEXP value) {
54
54
SETCAR (opt, value);
55
55
}
56
56
57
- inline Rboolean* setup_should_unwind_protect () {
57
+ inline Rboolean& get_should_unwind_protect () {
58
58
SEXP should_unwind_protect_sym = Rf_install (" cpp11_should_unwind_protect" );
59
59
SEXP should_unwind_protect_sexp = Rf_GetOption1 (should_unwind_protect_sym);
60
-
61
60
if (should_unwind_protect_sexp == R_NilValue) {
62
- // Allocate and initialize once, then let R manage it.
63
- // That makes this a shared global across all compilation units.
64
61
should_unwind_protect_sexp = PROTECT (Rf_allocVector (LGLSXP, 1 ));
65
- SET_LOGICAL_ELT (should_unwind_protect_sexp, 0 , TRUE );
66
62
detail::set_option (should_unwind_protect_sym, should_unwind_protect_sexp);
67
63
UNPROTECT (1 );
68
64
}
69
65
70
- return reinterpret_cast <Rboolean*>(LOGICAL (should_unwind_protect_sexp));
71
- }
72
-
73
- inline Rboolean* access_should_unwind_protect () {
74
- // Setup is run once per compilation unit, but all compilation units
75
- // share the same global option, so each compilation unit's static pointer
76
- // will point to the same object.
77
- static Rboolean* p_should_unwind_protect = setup_should_unwind_protect ();
78
- return p_should_unwind_protect;
79
- }
80
-
81
- inline Rboolean get_should_unwind_protect () { return *access_should_unwind_protect (); }
66
+ Rboolean* should_unwind_protect =
67
+ reinterpret_cast <Rboolean*>(LOGICAL (should_unwind_protect_sexp));
68
+ should_unwind_protect[0 ] = TRUE ;
82
69
83
- inline void set_should_unwind_protect (Rboolean should_unwind_protect) {
84
- *access_should_unwind_protect () = should_unwind_protect;
70
+ return should_unwind_protect[0 ];
85
71
}
86
72
87
73
} // namespace detail
@@ -94,11 +80,12 @@ inline void set_should_unwind_protect(Rboolean should_unwind_protect) {
94
80
template <typename Fun, typename = typename std::enable_if<std::is_same<
95
81
decltype (std::declval<Fun&&>()()), SEXP>::value>::type>
96
82
SEXP unwind_protect(Fun&& code) {
97
- if (detail::get_should_unwind_protect () == FALSE ) {
83
+ static auto should_unwind_protect = detail::get_should_unwind_protect ();
84
+ if (should_unwind_protect == FALSE ) {
98
85
return std::forward<Fun>(code)();
99
86
}
100
87
101
- detail::set_should_unwind_protect ( FALSE ) ;
88
+ should_unwind_protect = FALSE ;
102
89
103
90
static SEXP token = [] {
104
91
SEXP res = R_MakeUnwindCont ();
@@ -108,7 +95,7 @@ SEXP unwind_protect(Fun&& code) {
108
95
109
96
std::jmp_buf jmpbuf;
110
97
if (setjmp (jmpbuf)) {
111
- detail::set_should_unwind_protect ( TRUE ) ;
98
+ should_unwind_protect = TRUE ;
112
99
throw unwind_exception (token);
113
100
}
114
101
@@ -133,7 +120,7 @@ SEXP unwind_protect(Fun&& code) {
133
120
// unset it here before returning the value ourselves.
134
121
SETCAR (token, R_NilValue);
135
122
136
- detail::set_should_unwind_protect ( TRUE ) ;
123
+ should_unwind_protect = TRUE ;
137
124
138
125
return res;
139
126
}
0 commit comments