11use std:: fmt;
22use std:: os:: raw:: { c_int, c_void} ;
33
4+ use super :: XRc ;
45use crate :: state:: { RawLua , WeakLua } ;
56
67/// A reference to a Lua (complex) value stored in the Lua auxiliary thread.
8+ #[ derive( Clone ) ]
79pub struct ValueRef {
810 pub ( crate ) lua : WeakLua ,
11+ // Keep index separate to avoid additional indirection when accessing it.
912 pub ( crate ) index : c_int ,
10- pub ( crate ) drop : bool ,
13+ // If `index_count` is `None`, the value does not need to be destroyed.
14+ pub ( crate ) index_count : Option < ValueRefIndex > ,
15+ }
16+
17+ /// A reference to a Lua value index in the auxiliary thread.
18+ /// It's cheap to clone and can be used to track the number of references to a value.
19+ #[ derive( Clone ) ]
20+ pub ( crate ) struct ValueRefIndex ( pub ( crate ) XRc < c_int > ) ;
21+
22+ impl From < c_int > for ValueRefIndex {
23+ #[ inline]
24+ fn from ( index : c_int ) -> Self {
25+ ValueRefIndex ( XRc :: new ( index) )
26+ }
1127}
1228
1329impl ValueRef {
1430 #[ inline]
15- pub ( crate ) fn new ( lua : & RawLua , index : c_int ) -> Self {
31+ pub ( crate ) fn new ( lua : & RawLua , index : impl Into < ValueRefIndex > ) -> Self {
32+ let index = index. into ( ) ;
1633 ValueRef {
1734 lua : lua. weak ( ) . clone ( ) ,
18- index,
19- drop : true ,
35+ index : * index . 0 ,
36+ index_count : Some ( index ) ,
2037 }
2138 }
2239
@@ -25,16 +42,6 @@ impl ValueRef {
2542 let lua = self . lua . lock ( ) ;
2643 unsafe { ffi:: lua_topointer ( lua. ref_thread ( ) , self . index ) }
2744 }
28-
29- /// Returns a copy of the value, which is valid as long as the original value is held.
30- #[ inline]
31- pub ( crate ) fn copy ( & self ) -> Self {
32- ValueRef {
33- lua : self . lua . clone ( ) ,
34- index : self . index ,
35- drop : false ,
36- }
37- }
3845}
3946
4047impl fmt:: Debug for ValueRef {
@@ -43,17 +50,15 @@ impl fmt::Debug for ValueRef {
4350 }
4451}
4552
46- impl Clone for ValueRef {
47- fn clone ( & self ) -> Self {
48- unsafe { self . lua . lock ( ) . clone_ref ( self ) }
49- }
50- }
51-
5253impl Drop for ValueRef {
5354 fn drop ( & mut self ) {
54- if self . drop {
55- if let Some ( lua) = self . lua . try_lock ( ) {
56- unsafe { lua. drop_ref ( self ) } ;
55+ if let Some ( ValueRefIndex ( index) ) = self . index_count . take ( ) {
56+ // It's guaranteed that the inner value returns exactly once.
57+ // This means in particular that the value is not dropped.
58+ if XRc :: into_inner ( index) . is_some ( ) {
59+ if let Some ( lua) = self . lua . try_lock ( ) {
60+ unsafe { lua. drop_ref ( self ) } ;
61+ }
5762 }
5863 }
5964 }
0 commit comments