| 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 |