@@ -5,12 +5,13 @@ use super::object::neon_array::NeonArray;
55use super :: object:: neon_function:: NeonFunction ;
66use super :: object:: neon_struct:: NeonStruct ;
77use super :: object:: NeonObject ;
8- use crate :: wrappers:: context:: NativeContext ;
8+ use crate :: wrappers:: context:: { NativeContext , NativeContextHolder } ;
99use crate :: wrappers:: object:: NativeObject ;
1010use crate :: wrappers:: object_handle:: NativeObjectHandle ;
1111use cubesql:: CubeError ;
1212use neon:: prelude:: * ;
13- use std:: cell:: RefCell ;
13+ use std:: cell:: { RefCell , RefMut } ;
14+ use std:: marker:: PhantomData ;
1415use std:: panic:: { catch_unwind, resume_unwind, AssertUnwindSafe } ;
1516use std:: rc:: { Rc , Weak } ;
1617
@@ -47,18 +48,42 @@ impl<C: Context<'static>> ContextWrapper<C> {
4748 }
4849}
4950
51+ pub struct NeonContextGuard < ' cx , C : Context < ' cx > + NoenContextLifetimeExpand < ' cx > > {
52+ context : Rc < RefCell < ContextWrapper < C :: ExpandedResult > > > ,
53+ lifetime : PhantomData < & ' cx ( ) > ,
54+ }
55+
56+ impl < ' cx , C : Context < ' cx > + NoenContextLifetimeExpand < ' cx > + ' cx > NeonContextGuard < ' cx , C > {
57+ fn new ( cx : C ) -> Self {
58+ Self {
59+ context : ContextWrapper :: new ( cx. expand_lifetime ( ) ) ,
60+ lifetime : PhantomData :: default ( ) ,
61+ }
62+ }
63+
64+ fn context_holder ( & self ) -> ContextHolder < C :: ExpandedResult > {
65+ ContextHolder :: new ( Rc :: downgrade ( & self . context ) )
66+ }
67+
68+ fn unwrap ( self ) {
69+ if Rc :: strong_count ( & self . context ) > 0 {
70+ match Rc :: try_unwrap ( self . context ) {
71+ Ok ( _) => { }
72+ Err ( _) => panic ! ( "Guarded context have more then one reference" ) ,
73+ }
74+ }
75+ }
76+ }
77+
5078pub fn neon_run_with_guarded_lifetime < ' cx , C , T , F > ( cx : C , func : F ) -> T
5179where
52- C : Context < ' cx > + NoenContextLifetimeExpand < ' cx > ,
80+ C : Context < ' cx > + NoenContextLifetimeExpand < ' cx > + ' cx ,
5381 F : FnOnce ( ContextHolder < C :: ExpandedResult > ) -> T ,
5482{
55- let context = ContextWrapper :: new ( cx. expand_lifetime ( ) ) ;
56- let context_holder = ContextHolder :: new ( Rc :: downgrade ( & context ) ) ;
83+ let guard = NeonContextGuard :: new ( cx) ;
84+ let context_holder = guard . context_holder ( ) ;
5785 let res = catch_unwind ( AssertUnwindSafe ( || func ( context_holder) ) ) ;
58- match Rc :: try_unwrap ( context) {
59- Ok ( _) => { }
60- Err ( _) => panic ! ( "Guarded context have more then one reference" ) ,
61- } ;
86+ guard. unwrap ( ) ;
6287
6388 match res {
6489 Ok ( res) => res,
0 commit comments