@@ -54,34 +54,20 @@ inline void set_option(SEXP name, SEXP value) {
5454 SETCAR (opt, value);
5555}
5656
57- inline Rboolean* setup_should_unwind_protect () {
57+ inline Rboolean& get_should_unwind_protect () {
5858 SEXP should_unwind_protect_sym = Rf_install (" cpp11_should_unwind_protect" );
5959 SEXP should_unwind_protect_sexp = Rf_GetOption1 (should_unwind_protect_sym);
60-
6160 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.
6461 should_unwind_protect_sexp = PROTECT (Rf_allocVector (LGLSXP, 1 ));
65- SET_LOGICAL_ELT (should_unwind_protect_sexp, 0 , TRUE );
6662 detail::set_option (should_unwind_protect_sym, should_unwind_protect_sexp);
6763 UNPROTECT (1 );
6864 }
6965
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 ;
8269
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 ];
8571}
8672
8773} // namespace detail
@@ -94,11 +80,12 @@ inline void set_should_unwind_protect(Rboolean should_unwind_protect) {
9480template <typename Fun, typename = typename std::enable_if<std::is_same<
9581 decltype (std::declval<Fun&&>()()), SEXP>::value>::type>
9682SEXP 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 ) {
9885 return std::forward<Fun>(code)();
9986 }
10087
101- detail::set_should_unwind_protect ( FALSE ) ;
88+ should_unwind_protect = FALSE ;
10289
10390 static SEXP token = [] {
10491 SEXP res = R_MakeUnwindCont ();
@@ -108,7 +95,7 @@ SEXP unwind_protect(Fun&& code) {
10895
10996 std::jmp_buf jmpbuf;
11097 if (setjmp (jmpbuf)) {
111- detail::set_should_unwind_protect ( TRUE ) ;
98+ should_unwind_protect = TRUE ;
11299 throw unwind_exception (token);
113100 }
114101
@@ -133,7 +120,7 @@ SEXP unwind_protect(Fun&& code) {
133120 // unset it here before returning the value ourselves.
134121 SETCAR (token, R_NilValue);
135122
136- detail::set_should_unwind_protect ( TRUE ) ;
123+ should_unwind_protect = TRUE ;
137124
138125 return res;
139126}
0 commit comments