OLD | NEW |
| (Empty) |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package system | |
6 | |
7 import ( | |
8 "log" | |
9 "runtime" | |
10 ) | |
11 | |
12 // Handle is a generic handle for mojo objects. | |
13 type Handle interface { | |
14 // Close closes the given handle. | |
15 Close() MojoResult | |
16 | |
17 // IsValid returns whether the handle is valid. A handle is valid until
it | |
18 // has been explicitly closed or sent through a message pipe. | |
19 IsValid() bool | |
20 | |
21 // NativeHandle returns the native handle backed by this handle. | |
22 // | |
23 // Note: try to avoid using this method as you lose ownership tracking. | |
24 NativeHandle() MojoHandle | |
25 | |
26 // ReleaseNativeHandle releases the native handle backed by this handle. | |
27 // The caller owns the handle and must close it. | |
28 ReleaseNativeHandle() MojoHandle | |
29 | |
30 // ToUntypedHandle converts this handle into an UntypedHandle, invalidat
ing | |
31 // this handle. | |
32 ToUntypedHandle() UntypedHandle | |
33 | |
34 // Wait waits on the handle until a signal indicated by signals is satis
fied | |
35 // or it becomes known that no signal indicated by signals will ever be | |
36 // satisified or until deadline has passed. | |
37 Wait(signals MojoHandleSignals, deadline MojoDeadline) (MojoResult, Mojo
HandleSignalsState) | |
38 } | |
39 | |
40 // UntypedHandle is a a mojo handle of unknown type. This handle can be typed by | |
41 // using one of its methods, which will return a handle of the requested type | |
42 // and invalidate this object. No validation is made when the conversion | |
43 // operation is called. | |
44 type UntypedHandle interface { | |
45 Handle | |
46 | |
47 // ToConsumerHandle returns the underlying handle as a ConsumerHandle | |
48 // and invalidates this UntypedHandle representation. | |
49 ToConsumerHandle() ConsumerHandle | |
50 | |
51 // ToProducerHandle returns the underlying handle as a ProducerHandle | |
52 // and invalidates this UntypedHandle representation. | |
53 ToProducerHandle() ProducerHandle | |
54 | |
55 // ToMessagePipeHandle returns the underlying handle as a MessagePipeHan
dle | |
56 // and invalidates this UntypedHandle representation. | |
57 ToMessagePipeHandle() MessagePipeHandle | |
58 | |
59 // ToSharedBufferHandle returns the underlying handle as a | |
60 // SharedBufferHandle and invalidates this UntypedHandle representation. | |
61 ToSharedBufferHandle() SharedBufferHandle | |
62 } | |
63 | |
64 // finalizeHandle closes handles that becomes unreachable in runtime. | |
65 // We want to make sure that every mojo handle is closed, so we set this | |
66 // finalizer function on every handle object we create. If a handle object | |
67 // becomes invalidated (because the handle was closed or the underlying mojo | |
68 // handle has been passed to another handle object), we remove the finalizer. | |
69 // | |
70 // The finalizing mechanism works tricky: runtime.SetFinalizer can be called on | |
71 // an object allocated by calling new or by taking the address of a composite | |
72 // literal, so we can't set a finalizer on an embedded struct if the embedded | |
73 // struct has a non-zero offset related to the outmost struct. | |
74 // | |
75 // Type structure of handles is the following: there is a struct baseHandle, | |
76 // which serves as a "base class" for all the typed handles (i.e. sharedBuffer, | |
77 // untypedHandleImpl, dataPipeProducer, dataPipeConsumer and messagePipe). We | |
78 // express it by struct embedding. When we operate with handles, we create typed | |
79 // handles and set finalizers on them, while to invalidate a handle and remove | |
80 // finalizer we call methods on the embedded baseHandle struct. So in order for | |
81 // finalizers to work correct we need to make sure that baseHandle is the first | |
82 // component of typed handles. | |
83 func finalizeHandle(h Handle) { | |
84 log.Println("Handle was not closed.") | |
85 h.Close() | |
86 } | |
87 | |
88 type baseHandle struct { | |
89 core *coreImpl | |
90 mojoHandle MojoHandle | |
91 } | |
92 | |
93 func (h *baseHandle) invalidate() { | |
94 h.mojoHandle = MOJO_HANDLE_INVALID | |
95 runtime.SetFinalizer(h, nil) | |
96 } | |
97 | |
98 func (h *baseHandle) Close() MojoResult { | |
99 mojoHandle := h.mojoHandle | |
100 h.invalidate() | |
101 h.core.mu.Lock() | |
102 r := sysImpl.Close(uint32(mojoHandle)) | |
103 h.core.mu.Unlock() | |
104 return MojoResult(r) | |
105 } | |
106 | |
107 func (h *baseHandle) IsValid() bool { | |
108 return h.mojoHandle != MOJO_HANDLE_INVALID | |
109 } | |
110 | |
111 func (h *baseHandle) NativeHandle() MojoHandle { | |
112 return h.mojoHandle | |
113 } | |
114 | |
115 func (h *baseHandle) ReleaseNativeHandle() MojoHandle { | |
116 mojoHandle := h.mojoHandle | |
117 h.invalidate() | |
118 return mojoHandle | |
119 } | |
120 | |
121 func (h *baseHandle) ToUntypedHandle() UntypedHandle { | |
122 handle := &untypedHandleImpl{*h} | |
123 runtime.SetFinalizer(handle, finalizeHandle) | |
124 h.invalidate() | |
125 return handle | |
126 } | |
127 | |
128 func (h *baseHandle) Wait(signals MojoHandleSignals, deadline MojoDeadline) (Moj
oResult, MojoHandleSignalsState) { | |
129 r, satisfiedSignals, satisfiableSignals := sysImpl.Wait(uint32(h.mojoHan
dle), uint32(signals), uint64(deadline)) | |
130 state := MojoHandleSignalsState{ | |
131 SatisfiedSignals: MojoHandleSignals(satisfiedSignals), | |
132 SatisfiableSignals: MojoHandleSignals(satisfiableSignals), | |
133 } | |
134 return MojoResult(r), state | |
135 } | |
136 | |
137 type untypedHandleImpl struct { | |
138 // baseHandle should always be the first component of this struct, | |
139 // see |finalizeHandle()| for more details. | |
140 baseHandle | |
141 } | |
142 | |
143 func (h *untypedHandleImpl) ToConsumerHandle() ConsumerHandle { | |
144 handle := &dataPipeConsumer{h.baseHandle} | |
145 runtime.SetFinalizer(handle, finalizeHandle) | |
146 h.invalidate() | |
147 return handle | |
148 } | |
149 | |
150 func (h *untypedHandleImpl) ToProducerHandle() ProducerHandle { | |
151 handle := &dataPipeProducer{h.baseHandle} | |
152 runtime.SetFinalizer(handle, finalizeHandle) | |
153 h.invalidate() | |
154 return handle | |
155 } | |
156 | |
157 func (h *untypedHandleImpl) ToMessagePipeHandle() MessagePipeHandle { | |
158 handle := &messagePipe{h.baseHandle} | |
159 runtime.SetFinalizer(handle, finalizeHandle) | |
160 h.invalidate() | |
161 return handle | |
162 } | |
163 | |
164 func (h *untypedHandleImpl) ToSharedBufferHandle() SharedBufferHandle { | |
165 handle := &sharedBuffer{h.baseHandle} | |
166 runtime.SetFinalizer(handle, finalizeHandle) | |
167 h.invalidate() | |
168 return handle | |
169 } | |
OLD | NEW |