1- use std:: sync:: Arc ;
1+ use std:: {
2+ panic,
3+ sync:: {
4+ Arc ,
5+ atomic:: { AtomicUsize , Ordering } ,
6+ } ,
7+ thread,
8+ } ;
29
310use ctor:: ctor;
411use scope_local:: { ActiveScope , Scope , scope_local} ;
512
613#[ ctor]
7- fn init ( ) {
14+ fn init_percpu ( ) {
815 percpu:: init ( ) ;
916
1017 unsafe { percpu:: write_percpu_reg ( percpu:: percpu_area_base ( 0 ) ) } ;
@@ -14,18 +21,22 @@ fn init() {
1421 println ! ( "per-CPU area size = {}" , percpu:: percpu_area_size( ) ) ;
1522}
1623
17- scope_local ! {
18- static DATA : usize = 0 ;
19- }
20-
2124#[ test]
22- fn global ( ) {
23- assert_eq ! ( * DATA , 0 ) ;
25+ fn scope_init ( ) {
26+ scope_local ! {
27+ static DATA : usize = 42 ;
28+ }
29+ assert_eq ! ( * DATA , 42 ) ;
2430}
2531
2632#[ test]
2733fn scope ( ) {
34+ scope_local ! {
35+ static DATA : usize = 0 ;
36+ }
37+
2838 let mut scope = Scope :: new ( ) ;
39+ assert_eq ! ( * DATA , 0 ) ;
2940 assert_eq ! ( * DATA . scope( & scope) , 0 ) ;
3041
3142 * DATA . scope_mut ( & mut scope) = 42 ;
@@ -35,14 +46,16 @@ fn scope() {
3546 assert_eq ! ( * DATA , 42 ) ;
3647
3748 ActiveScope :: set_global ( ) ;
38- }
39-
40- scope_local ! {
41- static SHARED : Arc <String > = Arc :: new( "qwq" . to_string( ) ) ;
49+ assert_eq ! ( * DATA , 0 ) ;
50+ assert_eq ! ( * DATA . scope( & scope) , 42 ) ;
4251}
4352
4453#[ test]
45- fn shared ( ) {
54+ fn scope_drop ( ) {
55+ scope_local ! {
56+ static SHARED : Arc <( ) > = Arc :: new( ( ) ) ;
57+ }
58+
4659 assert_eq ! ( Arc :: strong_count( & SHARED ) , 1 ) ;
4760
4861 {
@@ -55,3 +68,110 @@ fn shared() {
5568
5669 assert_eq ! ( Arc :: strong_count( & SHARED ) , 1 ) ;
5770}
71+
72+ #[ test]
73+ fn scope_panic_unwind_drop ( ) {
74+ scope_local ! {
75+ static SHARED : Arc <( ) > = Arc :: new( ( ) ) ;
76+ }
77+
78+ let panic = panic:: catch_unwind ( || {
79+ let mut scope = Scope :: new ( ) ;
80+ * SHARED . scope_mut ( & mut scope) = SHARED . clone ( ) ;
81+ assert_eq ! ( Arc :: strong_count( & SHARED ) , 2 ) ;
82+ panic ! ( "panic" ) ;
83+ } ) ;
84+ assert ! ( panic. is_err( ) ) ;
85+
86+ assert_eq ! ( Arc :: strong_count( & SHARED ) , 1 ) ;
87+ }
88+
89+ #[ test]
90+ fn thread_share_item ( ) {
91+ scope_local ! {
92+ static SHARED : Arc <( ) > = Arc :: new( ( ) ) ;
93+ }
94+
95+ let handles: Vec < _ > = ( 0 ..10 )
96+ . map ( |_| {
97+ thread:: spawn ( move || {
98+ let global = & * SHARED ;
99+
100+ let mut scope = Scope :: new ( ) ;
101+ * SHARED . scope_mut ( & mut scope) = global. clone ( ) ;
102+
103+ unsafe { ActiveScope :: set ( & scope) } ;
104+
105+ assert ! ( Arc :: strong_count( & SHARED ) >= 2 ) ;
106+ assert ! ( Arc :: ptr_eq( & SHARED , global) ) ;
107+
108+ ActiveScope :: set_global ( ) ;
109+ } )
110+ } )
111+ . collect ( ) ;
112+
113+ for h in handles {
114+ h. join ( ) . unwrap ( ) ;
115+ }
116+
117+ assert_eq ! ( Arc :: strong_count( & SHARED ) , 1 ) ;
118+ }
119+
120+ #[ test]
121+ fn thread_share_scope ( ) {
122+ scope_local ! {
123+ static SHARED : Arc <( ) > = Arc :: new( ( ) ) ;
124+ }
125+
126+ let scope = Arc :: new ( Scope :: new ( ) ) ;
127+
128+ let handles: Vec < _ > = ( 0 ..10 )
129+ . map ( |_| {
130+ let scope = scope. clone ( ) ;
131+ thread:: spawn ( move || {
132+ unsafe { ActiveScope :: set ( & scope) } ;
133+ assert_eq ! ( Arc :: strong_count( & SHARED ) , 1 ) ;
134+ assert ! ( Arc :: ptr_eq( & SHARED , & SHARED . scope( & scope) ) ) ;
135+ ActiveScope :: set_global ( ) ;
136+ } )
137+ } )
138+ . collect ( ) ;
139+
140+ for h in handles {
141+ h. join ( ) . unwrap ( ) ;
142+ }
143+
144+ assert_eq ! ( Arc :: strong_count( & SHARED ) , 1 ) ;
145+ assert_eq ! ( Arc :: strong_count( & SHARED . scope( & scope) ) , 1 ) ;
146+ }
147+
148+ #[ test]
149+ fn thread_isolation ( ) {
150+ scope_local ! {
151+ static DATA : usize = 42 ;
152+ static DATA2 : AtomicUsize = AtomicUsize :: new( 42 ) ;
153+ }
154+
155+ let handles: Vec < _ > = ( 0 ..10 )
156+ . map ( |i| {
157+ thread:: spawn ( move || {
158+ let mut scope = Scope :: new ( ) ;
159+ * DATA . scope_mut ( & mut scope) = i;
160+
161+ unsafe { ActiveScope :: set ( & scope) } ;
162+ assert_eq ! ( * DATA , i) ;
163+
164+ DATA2 . store ( i, Ordering :: Relaxed ) ;
165+
166+ ActiveScope :: set_global ( ) ;
167+ } )
168+ } )
169+ . collect ( ) ;
170+
171+ for h in handles {
172+ h. join ( ) . unwrap ( ) ;
173+ }
174+
175+ assert_eq ! ( * DATA , 42 ) ;
176+ assert_eq ! ( DATA2 . load( Ordering :: Relaxed ) , 42 ) ;
177+ }
0 commit comments