1
+ // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2
+ // file at the top-level directory of this distribution and at
3
+ // http://rust-lang.org/COPYRIGHT.
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6
+ // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7
+ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8
+ // option. This file may not be copied, modified, or distributed
9
+ // except according to those terms.
10
+
11
+ use option:: { Option , Some , None } ;
12
+ use rt:: sched:: Scheduler ;
13
+ use rt:: task:: Task ;
14
+ use rt:: local_ptr;
15
+ use rt:: rtio:: { EventLoop , IoFactoryObject } ;
16
+
17
+ pub trait Local {
18
+ fn put ( value : ~Self ) ;
19
+ fn take ( ) -> ~Self ;
20
+ fn exists ( ) -> bool ;
21
+ fn borrow ( f : & fn ( & mut Self ) ) ;
22
+ unsafe fn unsafe_borrow ( ) -> * mut Self ;
23
+ unsafe fn try_unsafe_borrow ( ) -> Option < * mut Self > ;
24
+ }
25
+
26
+ impl Local for Scheduler {
27
+ fn put ( value : ~Scheduler ) { unsafe { local_ptr:: put ( value) } }
28
+ fn take ( ) -> ~Scheduler { unsafe { local_ptr:: take ( ) } }
29
+ fn exists ( ) -> bool { local_ptr:: exists ( ) }
30
+ fn borrow ( f : & fn ( & mut Scheduler ) ) { unsafe { local_ptr:: borrow ( f) } }
31
+ unsafe fn unsafe_borrow ( ) -> * mut Scheduler { local_ptr:: unsafe_borrow ( ) }
32
+ unsafe fn try_unsafe_borrow ( ) -> Option < * mut Scheduler > { abort ! ( "unimpl" ) }
33
+ }
34
+
35
+ impl Local for Task {
36
+ fn put ( value : ~Task ) { abort ! ( "unimpl" ) }
37
+ fn take ( ) -> ~Task { abort ! ( "unimpl" ) }
38
+ fn exists ( ) -> bool { abort ! ( "unimpl" ) }
39
+ fn borrow ( f : & fn ( & mut Task ) ) {
40
+ do Local :: borrow :: < Scheduler > |sched| {
41
+ match sched. current_task {
42
+ Some ( ~ref mut task) => {
43
+ f ( & mut * task. task )
44
+ }
45
+ None => {
46
+ abort ! ( "no scheduler" )
47
+ }
48
+ }
49
+ }
50
+ }
51
+ unsafe fn unsafe_borrow ( ) -> * mut Task {
52
+ match ( * Local :: unsafe_borrow :: < Scheduler > ( ) ) . current_task {
53
+ Some ( ~ref mut task) => {
54
+ let s: * mut Task = & mut * task. task ;
55
+ return s;
56
+ }
57
+ None => {
58
+ // Don't fail. Infinite recursion
59
+ abort ! ( "no scheduler" )
60
+ }
61
+ }
62
+ }
63
+ unsafe fn try_unsafe_borrow ( ) -> Option < * mut Task > {
64
+ if Local :: exists :: < Scheduler > ( ) {
65
+ Some ( Local :: unsafe_borrow ( ) )
66
+ } else {
67
+ None
68
+ }
69
+ }
70
+ }
71
+
72
+ // XXX: This formulation won't work once ~IoFactoryObject is a real trait pointer
73
+ impl Local for IoFactoryObject {
74
+ fn put ( value : ~IoFactoryObject ) { abort ! ( "unimpl" ) }
75
+ fn take ( ) -> ~IoFactoryObject { abort ! ( "unimpl" ) }
76
+ fn exists ( ) -> bool { abort ! ( "unimpl" ) }
77
+ fn borrow ( f : & fn ( & mut IoFactoryObject ) ) { abort ! ( "unimpl" ) }
78
+ unsafe fn unsafe_borrow ( ) -> * mut IoFactoryObject {
79
+ let sched = Local :: unsafe_borrow :: < Scheduler > ( ) ;
80
+ let io: * mut IoFactoryObject = ( * sched) . event_loop . io ( ) . unwrap ( ) ;
81
+ return io;
82
+ }
83
+ unsafe fn try_unsafe_borrow ( ) -> Option < * mut IoFactoryObject > { abort ! ( "unimpl" ) }
84
+ }
85
+
86
+ #[ cfg( test) ]
87
+ mod test {
88
+ use rt:: sched:: Scheduler ;
89
+ use rt:: uv:: uvio:: UvEventLoop ;
90
+ use super :: * ;
91
+
92
+ #[ test]
93
+ fn thread_local_scheduler_smoke_test ( ) {
94
+ let scheduler = ~UvEventLoop :: new_scheduler ( ) ;
95
+ Local :: put ( scheduler) ;
96
+ let _scheduler: ~Scheduler = Local :: take ( ) ;
97
+ }
98
+
99
+ #[ test]
100
+ fn thread_local_scheduler_two_instances ( ) {
101
+ let scheduler = ~UvEventLoop :: new_scheduler ( ) ;
102
+ Local :: put ( scheduler) ;
103
+ let _scheduler: ~Scheduler = Local :: take ( ) ;
104
+ let scheduler = ~UvEventLoop :: new_scheduler ( ) ;
105
+ Local :: put ( scheduler) ;
106
+ let _scheduler: ~Scheduler = Local :: take ( ) ;
107
+ }
108
+
109
+ #[ test]
110
+ fn borrow_smoke_test ( ) {
111
+ let scheduler = ~UvEventLoop :: new_scheduler ( ) ;
112
+ Local :: put ( scheduler) ;
113
+ unsafe {
114
+ let _scheduler: * mut Scheduler = Local :: unsafe_borrow ( ) ;
115
+ }
116
+ let _scheduler: ~Scheduler = Local :: take ( ) ;
117
+ }
118
+ }
0 commit comments