1*bebae9c0SAndroid Build Coastguard Worker /*
2*bebae9c0SAndroid Build Coastguard Worker * Copyright (C) 2010 The Android Open Source Project
3*bebae9c0SAndroid Build Coastguard Worker *
4*bebae9c0SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*bebae9c0SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*bebae9c0SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*bebae9c0SAndroid Build Coastguard Worker *
8*bebae9c0SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*bebae9c0SAndroid Build Coastguard Worker *
10*bebae9c0SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*bebae9c0SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*bebae9c0SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*bebae9c0SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*bebae9c0SAndroid Build Coastguard Worker * limitations under the License.
15*bebae9c0SAndroid Build Coastguard Worker */
16*bebae9c0SAndroid Build Coastguard Worker
17*bebae9c0SAndroid Build Coastguard Worker /* Object implementation */
18*bebae9c0SAndroid Build Coastguard Worker
19*bebae9c0SAndroid Build Coastguard Worker #include "sles_allinclusive.h"
20*bebae9c0SAndroid Build Coastguard Worker
21*bebae9c0SAndroid Build Coastguard Worker
22*bebae9c0SAndroid Build Coastguard Worker // Called by a worker thread to handle an asynchronous Object.Realize.
23*bebae9c0SAndroid Build Coastguard Worker // Parameter self is the Object.
24*bebae9c0SAndroid Build Coastguard Worker
HandleRealize(void * self,void * ignored,int unused)25*bebae9c0SAndroid Build Coastguard Worker static void HandleRealize(void *self, void *ignored, int unused)
26*bebae9c0SAndroid Build Coastguard Worker {
27*bebae9c0SAndroid Build Coastguard Worker
28*bebae9c0SAndroid Build Coastguard Worker // validate input parameters
29*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
30*bebae9c0SAndroid Build Coastguard Worker assert(NULL != thiz);
31*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thiz->mClass;
32*bebae9c0SAndroid Build Coastguard Worker assert(NULL != clazz);
33*bebae9c0SAndroid Build Coastguard Worker AsyncHook realize = clazz->mRealize;
34*bebae9c0SAndroid Build Coastguard Worker SLresult result;
35*bebae9c0SAndroid Build Coastguard Worker SLuint8 state;
36*bebae9c0SAndroid Build Coastguard Worker
37*bebae9c0SAndroid Build Coastguard Worker // check object state
38*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
39*bebae9c0SAndroid Build Coastguard Worker state = thiz->mState;
40*bebae9c0SAndroid Build Coastguard Worker switch (state) {
41*bebae9c0SAndroid Build Coastguard Worker
42*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_1: // normal case
43*bebae9c0SAndroid Build Coastguard Worker if (NULL != realize) {
44*bebae9c0SAndroid Build Coastguard Worker thiz->mState = SL_OBJECT_STATE_REALIZING_2;
45*bebae9c0SAndroid Build Coastguard Worker // Note that the mutex is locked on entry to and exit from the realize hook,
46*bebae9c0SAndroid Build Coastguard Worker // but the hook is permitted to temporarily unlock the mutex (e.g. for async).
47*bebae9c0SAndroid Build Coastguard Worker result = (*realize)(thiz, SL_BOOLEAN_TRUE);
48*bebae9c0SAndroid Build Coastguard Worker assert(SL_OBJECT_STATE_REALIZING_2 == thiz->mState);
49*bebae9c0SAndroid Build Coastguard Worker state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED :
50*bebae9c0SAndroid Build Coastguard Worker SL_OBJECT_STATE_UNREALIZED;
51*bebae9c0SAndroid Build Coastguard Worker } else {
52*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
53*bebae9c0SAndroid Build Coastguard Worker state = SL_OBJECT_STATE_REALIZED;
54*bebae9c0SAndroid Build Coastguard Worker }
55*bebae9c0SAndroid Build Coastguard Worker break;
56*bebae9c0SAndroid Build Coastguard Worker
57*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_1A: // operation was aborted while on work queue
58*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_OPERATION_ABORTED;
59*bebae9c0SAndroid Build Coastguard Worker state = SL_OBJECT_STATE_UNREALIZED;
60*bebae9c0SAndroid Build Coastguard Worker break;
61*bebae9c0SAndroid Build Coastguard Worker
62*bebae9c0SAndroid Build Coastguard Worker default: // impossible
63*bebae9c0SAndroid Build Coastguard Worker assert(SL_BOOLEAN_FALSE);
64*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_INTERNAL_ERROR;
65*bebae9c0SAndroid Build Coastguard Worker break;
66*bebae9c0SAndroid Build Coastguard Worker
67*bebae9c0SAndroid Build Coastguard Worker }
68*bebae9c0SAndroid Build Coastguard Worker
69*bebae9c0SAndroid Build Coastguard Worker // mutex is locked, update state
70*bebae9c0SAndroid Build Coastguard Worker thiz->mState = state;
71*bebae9c0SAndroid Build Coastguard Worker
72*bebae9c0SAndroid Build Coastguard Worker // Make a copy of these, so we can call the callback with mutex unlocked
73*bebae9c0SAndroid Build Coastguard Worker slObjectCallback callback = thiz->mCallback;
74*bebae9c0SAndroid Build Coastguard Worker void *context = thiz->mContext;
75*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
76*bebae9c0SAndroid Build Coastguard Worker
77*bebae9c0SAndroid Build Coastguard Worker // Note that the mutex is unlocked during the callback
78*bebae9c0SAndroid Build Coastguard Worker if (NULL != callback) {
79*bebae9c0SAndroid Build Coastguard Worker (*callback)(&thiz->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL);
80*bebae9c0SAndroid Build Coastguard Worker }
81*bebae9c0SAndroid Build Coastguard Worker }
82*bebae9c0SAndroid Build Coastguard Worker
83*bebae9c0SAndroid Build Coastguard Worker
IObject_Realize(SLObjectItf self,SLboolean async)84*bebae9c0SAndroid Build Coastguard Worker static SLresult IObject_Realize(SLObjectItf self, SLboolean async)
85*bebae9c0SAndroid Build Coastguard Worker {
86*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
87*bebae9c0SAndroid Build Coastguard Worker
88*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
89*bebae9c0SAndroid Build Coastguard Worker SLuint8 state;
90*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thiz->mClass;
91*bebae9c0SAndroid Build Coastguard Worker bool isSharedEngine = false;
92*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
93*bebae9c0SAndroid Build Coastguard Worker // note that SL_OBJECTID_ENGINE and XA_OBJECTID_ENGINE map to same class
94*bebae9c0SAndroid Build Coastguard Worker if (clazz == objectIDtoClass(SL_OBJECTID_ENGINE)) {
95*bebae9c0SAndroid Build Coastguard Worker // important: the lock order is engine followed by theOneTrueMutex
96*bebae9c0SAndroid Build Coastguard Worker int ok = pthread_mutex_lock(&theOneTrueMutex);
97*bebae9c0SAndroid Build Coastguard Worker assert(0 == ok);
98*bebae9c0SAndroid Build Coastguard Worker isSharedEngine = 1 < theOneTrueRefCount;
99*bebae9c0SAndroid Build Coastguard Worker ok = pthread_mutex_unlock(&theOneTrueMutex);
100*bebae9c0SAndroid Build Coastguard Worker assert(0 == ok);
101*bebae9c0SAndroid Build Coastguard Worker }
102*bebae9c0SAndroid Build Coastguard Worker state = thiz->mState;
103*bebae9c0SAndroid Build Coastguard Worker // Reject redundant calls to Realize, except on a shared engine
104*bebae9c0SAndroid Build Coastguard Worker if (SL_OBJECT_STATE_UNREALIZED != state) {
105*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
106*bebae9c0SAndroid Build Coastguard Worker // redundant realize on the shared engine is permitted
107*bebae9c0SAndroid Build Coastguard Worker if (isSharedEngine && (SL_OBJECT_STATE_REALIZED == state)) {
108*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
109*bebae9c0SAndroid Build Coastguard Worker } else {
110*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PRECONDITIONS_VIOLATED;
111*bebae9c0SAndroid Build Coastguard Worker }
112*bebae9c0SAndroid Build Coastguard Worker } else {
113*bebae9c0SAndroid Build Coastguard Worker // Asynchronous: mark operation pending and cancellable
114*bebae9c0SAndroid Build Coastguard Worker if (async && (SL_OBJECTID_ENGINE != clazz->mSLObjectID)) {
115*bebae9c0SAndroid Build Coastguard Worker state = SL_OBJECT_STATE_REALIZING_1;
116*bebae9c0SAndroid Build Coastguard Worker // Synchronous: mark operation pending and non-cancellable
117*bebae9c0SAndroid Build Coastguard Worker } else {
118*bebae9c0SAndroid Build Coastguard Worker state = SL_OBJECT_STATE_REALIZING_2;
119*bebae9c0SAndroid Build Coastguard Worker }
120*bebae9c0SAndroid Build Coastguard Worker thiz->mState = state;
121*bebae9c0SAndroid Build Coastguard Worker switch (state) {
122*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_1: // asynchronous on non-Engine
123*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
124*bebae9c0SAndroid Build Coastguard Worker assert(async);
125*bebae9c0SAndroid Build Coastguard Worker result = ThreadPool_add_ppi(&thiz->mEngine->mThreadPool, HandleRealize, thiz, NULL, 0);
126*bebae9c0SAndroid Build Coastguard Worker if (SL_RESULT_SUCCESS != result) {
127*bebae9c0SAndroid Build Coastguard Worker // Engine was destroyed during realize, or insufficient memory
128*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
129*bebae9c0SAndroid Build Coastguard Worker thiz->mState = SL_OBJECT_STATE_UNREALIZED;
130*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
131*bebae9c0SAndroid Build Coastguard Worker }
132*bebae9c0SAndroid Build Coastguard Worker break;
133*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_2: // synchronous, or asynchronous on Engine
134*bebae9c0SAndroid Build Coastguard Worker {
135*bebae9c0SAndroid Build Coastguard Worker AsyncHook realize = clazz->mRealize;
136*bebae9c0SAndroid Build Coastguard Worker // Note that the mutex is locked on entry to and exit from the realize hook,
137*bebae9c0SAndroid Build Coastguard Worker // but the hook is permitted to temporarily unlock the mutex (e.g. for async).
138*bebae9c0SAndroid Build Coastguard Worker result = (NULL != realize) ? (*realize)(thiz, async) : SL_RESULT_SUCCESS;
139*bebae9c0SAndroid Build Coastguard Worker assert(SL_OBJECT_STATE_REALIZING_2 == thiz->mState);
140*bebae9c0SAndroid Build Coastguard Worker state = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED :
141*bebae9c0SAndroid Build Coastguard Worker SL_OBJECT_STATE_UNREALIZED;
142*bebae9c0SAndroid Build Coastguard Worker thiz->mState = state;
143*bebae9c0SAndroid Build Coastguard Worker slObjectCallback callback = thiz->mCallback;
144*bebae9c0SAndroid Build Coastguard Worker void *context = thiz->mContext;
145*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
146*bebae9c0SAndroid Build Coastguard Worker // asynchronous Realize on an Engine is actually done synchronously, but still has
147*bebae9c0SAndroid Build Coastguard Worker // callback because there is no thread pool yet to do it asynchronously.
148*bebae9c0SAndroid Build Coastguard Worker if (async && (NULL != callback)) {
149*bebae9c0SAndroid Build Coastguard Worker (*callback)(&thiz->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state,
150*bebae9c0SAndroid Build Coastguard Worker NULL);
151*bebae9c0SAndroid Build Coastguard Worker }
152*bebae9c0SAndroid Build Coastguard Worker }
153*bebae9c0SAndroid Build Coastguard Worker break;
154*bebae9c0SAndroid Build Coastguard Worker default: // impossible
155*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
156*bebae9c0SAndroid Build Coastguard Worker assert(SL_BOOLEAN_FALSE);
157*bebae9c0SAndroid Build Coastguard Worker break;
158*bebae9c0SAndroid Build Coastguard Worker }
159*bebae9c0SAndroid Build Coastguard Worker }
160*bebae9c0SAndroid Build Coastguard Worker
161*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
162*bebae9c0SAndroid Build Coastguard Worker }
163*bebae9c0SAndroid Build Coastguard Worker
164*bebae9c0SAndroid Build Coastguard Worker
165*bebae9c0SAndroid Build Coastguard Worker // Called by a worker thread to handle an asynchronous Object.Resume.
166*bebae9c0SAndroid Build Coastguard Worker // Parameter self is the Object.
167*bebae9c0SAndroid Build Coastguard Worker
HandleResume(void * self,void * ignored,int unused)168*bebae9c0SAndroid Build Coastguard Worker static void HandleResume(void *self, void *ignored, int unused)
169*bebae9c0SAndroid Build Coastguard Worker {
170*bebae9c0SAndroid Build Coastguard Worker
171*bebae9c0SAndroid Build Coastguard Worker // valid input parameters
172*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
173*bebae9c0SAndroid Build Coastguard Worker assert(NULL != thiz);
174*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thiz->mClass;
175*bebae9c0SAndroid Build Coastguard Worker assert(NULL != clazz);
176*bebae9c0SAndroid Build Coastguard Worker AsyncHook resume = clazz->mResume;
177*bebae9c0SAndroid Build Coastguard Worker SLresult result;
178*bebae9c0SAndroid Build Coastguard Worker SLuint8 state;
179*bebae9c0SAndroid Build Coastguard Worker
180*bebae9c0SAndroid Build Coastguard Worker // check object state
181*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
182*bebae9c0SAndroid Build Coastguard Worker state = thiz->mState;
183*bebae9c0SAndroid Build Coastguard Worker switch (state) {
184*bebae9c0SAndroid Build Coastguard Worker
185*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_1: // normal case
186*bebae9c0SAndroid Build Coastguard Worker if (NULL != resume) {
187*bebae9c0SAndroid Build Coastguard Worker thiz->mState = SL_OBJECT_STATE_RESUMING_2;
188*bebae9c0SAndroid Build Coastguard Worker // Note that the mutex is locked on entry to and exit from the resume hook,
189*bebae9c0SAndroid Build Coastguard Worker // but the hook is permitted to temporarily unlock the mutex (e.g. for async).
190*bebae9c0SAndroid Build Coastguard Worker result = (*resume)(thiz, SL_BOOLEAN_TRUE);
191*bebae9c0SAndroid Build Coastguard Worker assert(SL_OBJECT_STATE_RESUMING_2 == thiz->mState);
192*bebae9c0SAndroid Build Coastguard Worker state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED :
193*bebae9c0SAndroid Build Coastguard Worker SL_OBJECT_STATE_SUSPENDED;
194*bebae9c0SAndroid Build Coastguard Worker } else {
195*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
196*bebae9c0SAndroid Build Coastguard Worker state = SL_OBJECT_STATE_REALIZED;
197*bebae9c0SAndroid Build Coastguard Worker }
198*bebae9c0SAndroid Build Coastguard Worker break;
199*bebae9c0SAndroid Build Coastguard Worker
200*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_1A: // operation was aborted while on work queue
201*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_OPERATION_ABORTED;
202*bebae9c0SAndroid Build Coastguard Worker state = SL_OBJECT_STATE_SUSPENDED;
203*bebae9c0SAndroid Build Coastguard Worker break;
204*bebae9c0SAndroid Build Coastguard Worker
205*bebae9c0SAndroid Build Coastguard Worker default: // impossible
206*bebae9c0SAndroid Build Coastguard Worker assert(SL_BOOLEAN_FALSE);
207*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_INTERNAL_ERROR;
208*bebae9c0SAndroid Build Coastguard Worker break;
209*bebae9c0SAndroid Build Coastguard Worker
210*bebae9c0SAndroid Build Coastguard Worker }
211*bebae9c0SAndroid Build Coastguard Worker
212*bebae9c0SAndroid Build Coastguard Worker // mutex is unlocked, update state
213*bebae9c0SAndroid Build Coastguard Worker thiz->mState = state;
214*bebae9c0SAndroid Build Coastguard Worker
215*bebae9c0SAndroid Build Coastguard Worker // Make a copy of these, so we can call the callback with mutex unlocked
216*bebae9c0SAndroid Build Coastguard Worker slObjectCallback callback = thiz->mCallback;
217*bebae9c0SAndroid Build Coastguard Worker void *context = thiz->mContext;
218*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
219*bebae9c0SAndroid Build Coastguard Worker
220*bebae9c0SAndroid Build Coastguard Worker // Note that the mutex is unlocked during the callback
221*bebae9c0SAndroid Build Coastguard Worker if (NULL != callback) {
222*bebae9c0SAndroid Build Coastguard Worker (*callback)(&thiz->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL);
223*bebae9c0SAndroid Build Coastguard Worker }
224*bebae9c0SAndroid Build Coastguard Worker }
225*bebae9c0SAndroid Build Coastguard Worker
226*bebae9c0SAndroid Build Coastguard Worker
IObject_Resume(SLObjectItf self,SLboolean async)227*bebae9c0SAndroid Build Coastguard Worker static SLresult IObject_Resume(SLObjectItf self, SLboolean async)
228*bebae9c0SAndroid Build Coastguard Worker {
229*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
230*bebae9c0SAndroid Build Coastguard Worker
231*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
232*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thiz->mClass;
233*bebae9c0SAndroid Build Coastguard Worker SLuint8 state;
234*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
235*bebae9c0SAndroid Build Coastguard Worker state = thiz->mState;
236*bebae9c0SAndroid Build Coastguard Worker // Reject redundant calls to Resume
237*bebae9c0SAndroid Build Coastguard Worker if (SL_OBJECT_STATE_SUSPENDED != state) {
238*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
239*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PRECONDITIONS_VIOLATED;
240*bebae9c0SAndroid Build Coastguard Worker } else {
241*bebae9c0SAndroid Build Coastguard Worker // Asynchronous: mark operation pending and cancellable
242*bebae9c0SAndroid Build Coastguard Worker if (async) {
243*bebae9c0SAndroid Build Coastguard Worker state = SL_OBJECT_STATE_RESUMING_1;
244*bebae9c0SAndroid Build Coastguard Worker // Synchronous: mark operatio pending and non-cancellable
245*bebae9c0SAndroid Build Coastguard Worker } else {
246*bebae9c0SAndroid Build Coastguard Worker state = SL_OBJECT_STATE_RESUMING_2;
247*bebae9c0SAndroid Build Coastguard Worker }
248*bebae9c0SAndroid Build Coastguard Worker thiz->mState = state;
249*bebae9c0SAndroid Build Coastguard Worker switch (state) {
250*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_1: // asynchronous
251*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
252*bebae9c0SAndroid Build Coastguard Worker assert(async);
253*bebae9c0SAndroid Build Coastguard Worker result = ThreadPool_add_ppi(&thiz->mEngine->mThreadPool, HandleResume, thiz, NULL, 0);
254*bebae9c0SAndroid Build Coastguard Worker if (SL_RESULT_SUCCESS != result) {
255*bebae9c0SAndroid Build Coastguard Worker // Engine was destroyed during resume, or insufficient memory
256*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
257*bebae9c0SAndroid Build Coastguard Worker thiz->mState = SL_OBJECT_STATE_SUSPENDED;
258*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
259*bebae9c0SAndroid Build Coastguard Worker }
260*bebae9c0SAndroid Build Coastguard Worker break;
261*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_2: // synchronous
262*bebae9c0SAndroid Build Coastguard Worker {
263*bebae9c0SAndroid Build Coastguard Worker AsyncHook resume = clazz->mResume;
264*bebae9c0SAndroid Build Coastguard Worker // Note that the mutex is locked on entry to and exit from the resume hook,
265*bebae9c0SAndroid Build Coastguard Worker // but the hook is permitted to temporarily unlock the mutex (e.g. for async).
266*bebae9c0SAndroid Build Coastguard Worker result = (NULL != resume) ? (*resume)(thiz, SL_BOOLEAN_FALSE) : SL_RESULT_SUCCESS;
267*bebae9c0SAndroid Build Coastguard Worker assert(SL_OBJECT_STATE_RESUMING_2 == thiz->mState);
268*bebae9c0SAndroid Build Coastguard Worker thiz->mState = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED :
269*bebae9c0SAndroid Build Coastguard Worker SL_OBJECT_STATE_SUSPENDED;
270*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
271*bebae9c0SAndroid Build Coastguard Worker }
272*bebae9c0SAndroid Build Coastguard Worker break;
273*bebae9c0SAndroid Build Coastguard Worker default: // impossible
274*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
275*bebae9c0SAndroid Build Coastguard Worker assert(SL_BOOLEAN_FALSE);
276*bebae9c0SAndroid Build Coastguard Worker break;
277*bebae9c0SAndroid Build Coastguard Worker }
278*bebae9c0SAndroid Build Coastguard Worker }
279*bebae9c0SAndroid Build Coastguard Worker
280*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
281*bebae9c0SAndroid Build Coastguard Worker }
282*bebae9c0SAndroid Build Coastguard Worker
283*bebae9c0SAndroid Build Coastguard Worker
IObject_GetState(SLObjectItf self,SLuint32 * pState)284*bebae9c0SAndroid Build Coastguard Worker static SLresult IObject_GetState(SLObjectItf self, SLuint32 *pState)
285*bebae9c0SAndroid Build Coastguard Worker {
286*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
287*bebae9c0SAndroid Build Coastguard Worker
288*bebae9c0SAndroid Build Coastguard Worker if (NULL == pState) {
289*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PARAMETER_INVALID;
290*bebae9c0SAndroid Build Coastguard Worker } else {
291*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
292*bebae9c0SAndroid Build Coastguard Worker object_lock_shared(thiz);
293*bebae9c0SAndroid Build Coastguard Worker SLuint8 state = thiz->mState;
294*bebae9c0SAndroid Build Coastguard Worker object_unlock_shared(thiz);
295*bebae9c0SAndroid Build Coastguard Worker // Re-map the realizing, resuming, and suspending states
296*bebae9c0SAndroid Build Coastguard Worker switch (state) {
297*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_1:
298*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_1A:
299*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_2:
300*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_DESTROYING: // application shouldn't call GetState after Destroy
301*bebae9c0SAndroid Build Coastguard Worker state = SL_OBJECT_STATE_UNREALIZED;
302*bebae9c0SAndroid Build Coastguard Worker break;
303*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_1:
304*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_1A:
305*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_2:
306*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_SUSPENDING:
307*bebae9c0SAndroid Build Coastguard Worker state = SL_OBJECT_STATE_SUSPENDED;
308*bebae9c0SAndroid Build Coastguard Worker break;
309*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_UNREALIZED:
310*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZED:
311*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_SUSPENDED:
312*bebae9c0SAndroid Build Coastguard Worker // These are the "official" object states, return them as is
313*bebae9c0SAndroid Build Coastguard Worker break;
314*bebae9c0SAndroid Build Coastguard Worker default:
315*bebae9c0SAndroid Build Coastguard Worker assert(SL_BOOLEAN_FALSE);
316*bebae9c0SAndroid Build Coastguard Worker break;
317*bebae9c0SAndroid Build Coastguard Worker }
318*bebae9c0SAndroid Build Coastguard Worker *pState = state;
319*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
320*bebae9c0SAndroid Build Coastguard Worker }
321*bebae9c0SAndroid Build Coastguard Worker
322*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
323*bebae9c0SAndroid Build Coastguard Worker }
324*bebae9c0SAndroid Build Coastguard Worker
IObject_GetInterface(SLObjectItf self,const SLInterfaceID iid,void * pInterface)325*bebae9c0SAndroid Build Coastguard Worker static SLresult IObject_GetInterface(SLObjectItf self, const SLInterfaceID iid, void *pInterface)
326*bebae9c0SAndroid Build Coastguard Worker {
327*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
328*bebae9c0SAndroid Build Coastguard Worker
329*bebae9c0SAndroid Build Coastguard Worker if (NULL == pInterface) {
330*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PARAMETER_INVALID;
331*bebae9c0SAndroid Build Coastguard Worker } else {
332*bebae9c0SAndroid Build Coastguard Worker void *interface = NULL;
333*bebae9c0SAndroid Build Coastguard Worker if (NULL == iid) {
334*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PARAMETER_INVALID;
335*bebae9c0SAndroid Build Coastguard Worker } else {
336*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
337*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thiz->mClass;
338*bebae9c0SAndroid Build Coastguard Worker int MPH, index;
339*bebae9c0SAndroid Build Coastguard Worker if ((0 > (MPH = IID_to_MPH(iid))) ||
340*bebae9c0SAndroid Build Coastguard Worker // no need to check for an initialization hook
341*bebae9c0SAndroid Build Coastguard Worker // (NULL == MPH_init_table[MPH].mInit) ||
342*bebae9c0SAndroid Build Coastguard Worker (0 > (index = clazz->mMPH_to_index[MPH]))) {
343*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_FEATURE_UNSUPPORTED;
344*bebae9c0SAndroid Build Coastguard Worker } else {
345*bebae9c0SAndroid Build Coastguard Worker unsigned mask = 1 << index;
346*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
347*bebae9c0SAndroid Build Coastguard Worker if ((SL_OBJECT_STATE_REALIZED != thiz->mState) &&
348*bebae9c0SAndroid Build Coastguard Worker !(INTERFACE_PREREALIZE & clazz->mInterfaces[index].mInterface)) {
349*bebae9c0SAndroid Build Coastguard Worker // Can't get interface on an unrealized object unless pre-realize is ok
350*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PRECONDITIONS_VIOLATED;
351*bebae9c0SAndroid Build Coastguard Worker } else if ((MPH_MUTESOLO == MPH) && (SL_OBJECTID_AUDIOPLAYER ==
352*bebae9c0SAndroid Build Coastguard Worker clazz->mSLObjectID) && (1 == ((CAudioPlayer *) thiz)->mNumChannels)) {
353*bebae9c0SAndroid Build Coastguard Worker // Can't get the MuteSolo interface of an audio player if the channel count is
354*bebae9c0SAndroid Build Coastguard Worker // mono, but _can_ get the MuteSolo interface if the channel count is unknown
355*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_FEATURE_UNSUPPORTED;
356*bebae9c0SAndroid Build Coastguard Worker } else {
357*bebae9c0SAndroid Build Coastguard Worker switch (thiz->mInterfaceStates[index]) {
358*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_EXPOSED:
359*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDED:
360*bebae9c0SAndroid Build Coastguard Worker interface = (char *) thiz + clazz->mInterfaces[index].mOffset;
361*bebae9c0SAndroid Build Coastguard Worker // Note that interface has been gotten,
362*bebae9c0SAndroid Build Coastguard Worker // for debugger and to detect incorrect use of interfaces
363*bebae9c0SAndroid Build Coastguard Worker if (!(thiz->mGottenMask & mask)) {
364*bebae9c0SAndroid Build Coastguard Worker thiz->mGottenMask |= mask;
365*bebae9c0SAndroid Build Coastguard Worker // This trickery validates the v-table
366*bebae9c0SAndroid Build Coastguard Worker ((size_t *) interface)[0] ^= ~0;
367*bebae9c0SAndroid Build Coastguard Worker }
368*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
369*bebae9c0SAndroid Build Coastguard Worker break;
370*bebae9c0SAndroid Build Coastguard Worker // Can't get interface if uninitialized, initialized, suspended,
371*bebae9c0SAndroid Build Coastguard Worker // suspending, resuming, adding, or removing
372*bebae9c0SAndroid Build Coastguard Worker default:
373*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_FEATURE_UNSUPPORTED;
374*bebae9c0SAndroid Build Coastguard Worker break;
375*bebae9c0SAndroid Build Coastguard Worker }
376*bebae9c0SAndroid Build Coastguard Worker }
377*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
378*bebae9c0SAndroid Build Coastguard Worker }
379*bebae9c0SAndroid Build Coastguard Worker }
380*bebae9c0SAndroid Build Coastguard Worker *(void **)pInterface = interface;
381*bebae9c0SAndroid Build Coastguard Worker }
382*bebae9c0SAndroid Build Coastguard Worker
383*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
384*bebae9c0SAndroid Build Coastguard Worker }
385*bebae9c0SAndroid Build Coastguard Worker
386*bebae9c0SAndroid Build Coastguard Worker
IObject_RegisterCallback(SLObjectItf self,slObjectCallback callback,void * pContext)387*bebae9c0SAndroid Build Coastguard Worker static SLresult IObject_RegisterCallback(SLObjectItf self,
388*bebae9c0SAndroid Build Coastguard Worker slObjectCallback callback, void *pContext)
389*bebae9c0SAndroid Build Coastguard Worker {
390*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
391*bebae9c0SAndroid Build Coastguard Worker
392*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
393*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
394*bebae9c0SAndroid Build Coastguard Worker thiz->mCallback = callback;
395*bebae9c0SAndroid Build Coastguard Worker thiz->mContext = pContext;
396*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
397*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
398*bebae9c0SAndroid Build Coastguard Worker
399*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
400*bebae9c0SAndroid Build Coastguard Worker }
401*bebae9c0SAndroid Build Coastguard Worker
402*bebae9c0SAndroid Build Coastguard Worker
403*bebae9c0SAndroid Build Coastguard Worker /** \brief This is internal common code for Abort and Destroy.
404*bebae9c0SAndroid Build Coastguard Worker * Note: called with mutex unlocked, and returns with mutex locked.
405*bebae9c0SAndroid Build Coastguard Worker */
406*bebae9c0SAndroid Build Coastguard Worker
Abort_internal(IObject * thiz)407*bebae9c0SAndroid Build Coastguard Worker static void Abort_internal(IObject *thiz)
408*bebae9c0SAndroid Build Coastguard Worker {
409*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thiz->mClass;
410*bebae9c0SAndroid Build Coastguard Worker bool anyAsync = false;
411*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
412*bebae9c0SAndroid Build Coastguard Worker
413*bebae9c0SAndroid Build Coastguard Worker // Abort asynchronous operations on the object
414*bebae9c0SAndroid Build Coastguard Worker switch (thiz->mState) {
415*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_1: // Realize
416*bebae9c0SAndroid Build Coastguard Worker thiz->mState = SL_OBJECT_STATE_REALIZING_1A;
417*bebae9c0SAndroid Build Coastguard Worker anyAsync = true;
418*bebae9c0SAndroid Build Coastguard Worker break;
419*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_1: // Resume
420*bebae9c0SAndroid Build Coastguard Worker thiz->mState = SL_OBJECT_STATE_RESUMING_1A;
421*bebae9c0SAndroid Build Coastguard Worker anyAsync = true;
422*bebae9c0SAndroid Build Coastguard Worker break;
423*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_1A: // Realize
424*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_2:
425*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_1A: // Resume
426*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_2:
427*bebae9c0SAndroid Build Coastguard Worker anyAsync = true;
428*bebae9c0SAndroid Build Coastguard Worker break;
429*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_DESTROYING:
430*bebae9c0SAndroid Build Coastguard Worker assert(false);
431*bebae9c0SAndroid Build Coastguard Worker break;
432*bebae9c0SAndroid Build Coastguard Worker default:
433*bebae9c0SAndroid Build Coastguard Worker break;
434*bebae9c0SAndroid Build Coastguard Worker }
435*bebae9c0SAndroid Build Coastguard Worker
436*bebae9c0SAndroid Build Coastguard Worker // Abort asynchronous operations on interfaces
437*bebae9c0SAndroid Build Coastguard Worker SLuint8 *interfaceStateP = thiz->mInterfaceStates;
438*bebae9c0SAndroid Build Coastguard Worker unsigned index;
439*bebae9c0SAndroid Build Coastguard Worker for (index = 0; index < clazz->mInterfaceCount; ++index, ++interfaceStateP) {
440*bebae9c0SAndroid Build Coastguard Worker switch (*interfaceStateP) {
441*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_1: // AddInterface
442*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_ADDING_1A;
443*bebae9c0SAndroid Build Coastguard Worker anyAsync = true;
444*bebae9c0SAndroid Build Coastguard Worker break;
445*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_1: // ResumeInterface
446*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_RESUMING_1A;
447*bebae9c0SAndroid Build Coastguard Worker anyAsync = true;
448*bebae9c0SAndroid Build Coastguard Worker break;
449*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_1A: // AddInterface
450*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_2:
451*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_1A: // ResumeInterface
452*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_2:
453*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_REMOVING: // not observable: RemoveInterface is synchronous & mutex locked
454*bebae9c0SAndroid Build Coastguard Worker anyAsync = true;
455*bebae9c0SAndroid Build Coastguard Worker break;
456*bebae9c0SAndroid Build Coastguard Worker default:
457*bebae9c0SAndroid Build Coastguard Worker break;
458*bebae9c0SAndroid Build Coastguard Worker }
459*bebae9c0SAndroid Build Coastguard Worker }
460*bebae9c0SAndroid Build Coastguard Worker
461*bebae9c0SAndroid Build Coastguard Worker // Wait until all asynchronous operations either complete normally or recognize the abort
462*bebae9c0SAndroid Build Coastguard Worker while (anyAsync) {
463*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
464*bebae9c0SAndroid Build Coastguard Worker // FIXME should use condition variable instead of polling
465*bebae9c0SAndroid Build Coastguard Worker usleep(20000);
466*bebae9c0SAndroid Build Coastguard Worker anyAsync = false;
467*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
468*bebae9c0SAndroid Build Coastguard Worker switch (thiz->mState) {
469*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_1: // state 1 means it cycled during the usleep window
470*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_1:
471*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_1A:
472*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_REALIZING_2:
473*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_1A:
474*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_RESUMING_2:
475*bebae9c0SAndroid Build Coastguard Worker anyAsync = true;
476*bebae9c0SAndroid Build Coastguard Worker break;
477*bebae9c0SAndroid Build Coastguard Worker case SL_OBJECT_STATE_DESTROYING:
478*bebae9c0SAndroid Build Coastguard Worker assert(false);
479*bebae9c0SAndroid Build Coastguard Worker break;
480*bebae9c0SAndroid Build Coastguard Worker default:
481*bebae9c0SAndroid Build Coastguard Worker break;
482*bebae9c0SAndroid Build Coastguard Worker }
483*bebae9c0SAndroid Build Coastguard Worker interfaceStateP = thiz->mInterfaceStates;
484*bebae9c0SAndroid Build Coastguard Worker for (index = 0; index < clazz->mInterfaceCount; ++index, ++interfaceStateP) {
485*bebae9c0SAndroid Build Coastguard Worker switch (*interfaceStateP) {
486*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_1: // state 1 means it cycled during the usleep window
487*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_1:
488*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_1A:
489*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_2:
490*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_1A:
491*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_2:
492*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_REMOVING:
493*bebae9c0SAndroid Build Coastguard Worker anyAsync = true;
494*bebae9c0SAndroid Build Coastguard Worker break;
495*bebae9c0SAndroid Build Coastguard Worker default:
496*bebae9c0SAndroid Build Coastguard Worker break;
497*bebae9c0SAndroid Build Coastguard Worker }
498*bebae9c0SAndroid Build Coastguard Worker }
499*bebae9c0SAndroid Build Coastguard Worker }
500*bebae9c0SAndroid Build Coastguard Worker
501*bebae9c0SAndroid Build Coastguard Worker // At this point there are no pending asynchronous operations
502*bebae9c0SAndroid Build Coastguard Worker }
503*bebae9c0SAndroid Build Coastguard Worker
504*bebae9c0SAndroid Build Coastguard Worker
IObject_AbortAsyncOperation(SLObjectItf self)505*bebae9c0SAndroid Build Coastguard Worker static void IObject_AbortAsyncOperation(SLObjectItf self)
506*bebae9c0SAndroid Build Coastguard Worker {
507*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE_VOID
508*bebae9c0SAndroid Build Coastguard Worker
509*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
510*bebae9c0SAndroid Build Coastguard Worker Abort_internal(thiz);
511*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
512*bebae9c0SAndroid Build Coastguard Worker
513*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE_VOID
514*bebae9c0SAndroid Build Coastguard Worker }
515*bebae9c0SAndroid Build Coastguard Worker
516*bebae9c0SAndroid Build Coastguard Worker
IObject_Destroy(SLObjectItf self)517*bebae9c0SAndroid Build Coastguard Worker void IObject_Destroy(SLObjectItf self)
518*bebae9c0SAndroid Build Coastguard Worker {
519*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE_VOID
520*bebae9c0SAndroid Build Coastguard Worker
521*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
522*bebae9c0SAndroid Build Coastguard Worker // mutex is unlocked
523*bebae9c0SAndroid Build Coastguard Worker Abort_internal(thiz);
524*bebae9c0SAndroid Build Coastguard Worker // mutex is locked
525*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thiz->mClass;
526*bebae9c0SAndroid Build Coastguard Worker PreDestroyHook preDestroy = clazz->mPreDestroy;
527*bebae9c0SAndroid Build Coastguard Worker // The pre-destroy hook is called with mutex locked, and should block until it is safe to
528*bebae9c0SAndroid Build Coastguard Worker // destroy. It is OK to unlock the mutex temporarily, as it long as it re-locks the mutex
529*bebae9c0SAndroid Build Coastguard Worker // before returning.
530*bebae9c0SAndroid Build Coastguard Worker if (NULL != preDestroy) {
531*bebae9c0SAndroid Build Coastguard Worker predestroy_t okToDestroy = (*preDestroy)(thiz);
532*bebae9c0SAndroid Build Coastguard Worker switch (okToDestroy) {
533*bebae9c0SAndroid Build Coastguard Worker case predestroy_ok:
534*bebae9c0SAndroid Build Coastguard Worker break;
535*bebae9c0SAndroid Build Coastguard Worker case predestroy_error:
536*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("Object::Destroy(%p) not allowed", thiz);
537*bebae9c0SAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
538*bebae9c0SAndroid Build Coastguard Worker case predestroy_again:
539*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
540*bebae9c0SAndroid Build Coastguard Worker // unfortunately Destroy doesn't return a result
541*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE_VOID
542*bebae9c0SAndroid Build Coastguard Worker // unreachable
543*bebae9c0SAndroid Build Coastguard Worker default:
544*bebae9c0SAndroid Build Coastguard Worker assert(false);
545*bebae9c0SAndroid Build Coastguard Worker break;
546*bebae9c0SAndroid Build Coastguard Worker }
547*bebae9c0SAndroid Build Coastguard Worker }
548*bebae9c0SAndroid Build Coastguard Worker thiz->mState = SL_OBJECT_STATE_DESTROYING;
549*bebae9c0SAndroid Build Coastguard Worker VoidHook destroy = clazz->mDestroy;
550*bebae9c0SAndroid Build Coastguard Worker // const, no lock needed
551*bebae9c0SAndroid Build Coastguard Worker IEngine *thisEngine = &thiz->mEngine->mEngine;
552*bebae9c0SAndroid Build Coastguard Worker unsigned i = thiz->mInstanceID;
553*bebae9c0SAndroid Build Coastguard Worker assert(MAX_INSTANCE >= i);
554*bebae9c0SAndroid Build Coastguard Worker // avoid a recursive lock on the engine when destroying the engine itself
555*bebae9c0SAndroid Build Coastguard Worker if (thisEngine->mThis != thiz) {
556*bebae9c0SAndroid Build Coastguard Worker interface_lock_exclusive(thisEngine);
557*bebae9c0SAndroid Build Coastguard Worker }
558*bebae9c0SAndroid Build Coastguard Worker // An unpublished object has a slot reserved, but the ID hasn't been chosen yet
559*bebae9c0SAndroid Build Coastguard Worker assert(0 < thisEngine->mInstanceCount);
560*bebae9c0SAndroid Build Coastguard Worker --thisEngine->mInstanceCount;
561*bebae9c0SAndroid Build Coastguard Worker // If object is published, then remove it from exposure to sync thread and debugger
562*bebae9c0SAndroid Build Coastguard Worker if (0 != i) {
563*bebae9c0SAndroid Build Coastguard Worker --i;
564*bebae9c0SAndroid Build Coastguard Worker unsigned mask = 1 << i;
565*bebae9c0SAndroid Build Coastguard Worker assert(thisEngine->mInstanceMask & mask);
566*bebae9c0SAndroid Build Coastguard Worker thisEngine->mInstanceMask &= ~mask;
567*bebae9c0SAndroid Build Coastguard Worker assert(thisEngine->mInstances[i] == thiz);
568*bebae9c0SAndroid Build Coastguard Worker thisEngine->mInstances[i] = NULL;
569*bebae9c0SAndroid Build Coastguard Worker }
570*bebae9c0SAndroid Build Coastguard Worker // avoid a recursive unlock on the engine when destroying the engine itself
571*bebae9c0SAndroid Build Coastguard Worker if (thisEngine->mThis != thiz) {
572*bebae9c0SAndroid Build Coastguard Worker interface_unlock_exclusive(thisEngine);
573*bebae9c0SAndroid Build Coastguard Worker }
574*bebae9c0SAndroid Build Coastguard Worker // The destroy hook is called with mutex locked
575*bebae9c0SAndroid Build Coastguard Worker if (NULL != destroy) {
576*bebae9c0SAndroid Build Coastguard Worker (*destroy)(thiz);
577*bebae9c0SAndroid Build Coastguard Worker }
578*bebae9c0SAndroid Build Coastguard Worker // Call the deinitializer for each currently initialized interface,
579*bebae9c0SAndroid Build Coastguard Worker // whether it is implicit, explicit, optional, or dynamically added.
580*bebae9c0SAndroid Build Coastguard Worker // The deinitializers are called in the reverse order that the
581*bebae9c0SAndroid Build Coastguard Worker // initializers were called, so that IObject_deinit is called last.
582*bebae9c0SAndroid Build Coastguard Worker unsigned index = clazz->mInterfaceCount;
583*bebae9c0SAndroid Build Coastguard Worker const struct iid_vtable *x = &clazz->mInterfaces[index];
584*bebae9c0SAndroid Build Coastguard Worker SLuint8 *interfaceStateP = &thiz->mInterfaceStates[index];
585*bebae9c0SAndroid Build Coastguard Worker for ( ; index > 0; --index) {
586*bebae9c0SAndroid Build Coastguard Worker --x;
587*bebae9c0SAndroid Build Coastguard Worker size_t offset = x->mOffset;
588*bebae9c0SAndroid Build Coastguard Worker void *thisItf = (char *) thiz + offset;
589*bebae9c0SAndroid Build Coastguard Worker SLuint32 state = *--interfaceStateP;
590*bebae9c0SAndroid Build Coastguard Worker switch (state) {
591*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_UNINITIALIZED:
592*bebae9c0SAndroid Build Coastguard Worker break;
593*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_EXPOSED: // quiescent states
594*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDED:
595*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_SUSPENDED:
596*bebae9c0SAndroid Build Coastguard Worker // The remove hook is called with mutex locked
597*bebae9c0SAndroid Build Coastguard Worker {
598*bebae9c0SAndroid Build Coastguard Worker VoidHook remove = MPH_init_table[x->mMPH].mRemove;
599*bebae9c0SAndroid Build Coastguard Worker if (NULL != remove) {
600*bebae9c0SAndroid Build Coastguard Worker (*remove)(thisItf);
601*bebae9c0SAndroid Build Coastguard Worker }
602*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_INITIALIZED;
603*bebae9c0SAndroid Build Coastguard Worker }
604*bebae9c0SAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
605*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_INITIALIZED:
606*bebae9c0SAndroid Build Coastguard Worker {
607*bebae9c0SAndroid Build Coastguard Worker VoidHook deinit = MPH_init_table[x->mMPH].mDeinit;
608*bebae9c0SAndroid Build Coastguard Worker if (NULL != deinit) {
609*bebae9c0SAndroid Build Coastguard Worker (*deinit)(thisItf);
610*bebae9c0SAndroid Build Coastguard Worker }
611*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_UNINITIALIZED;
612*bebae9c0SAndroid Build Coastguard Worker }
613*bebae9c0SAndroid Build Coastguard Worker break;
614*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_1: // active states indicate incorrect use of API
615*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_1A:
616*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_2:
617*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_1:
618*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_1A:
619*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_2:
620*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_REMOVING:
621*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_SUSPENDING:
622*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("Object::Destroy(%p) while interface %u active", thiz, index);
623*bebae9c0SAndroid Build Coastguard Worker break;
624*bebae9c0SAndroid Build Coastguard Worker default:
625*bebae9c0SAndroid Build Coastguard Worker assert(SL_BOOLEAN_FALSE);
626*bebae9c0SAndroid Build Coastguard Worker break;
627*bebae9c0SAndroid Build Coastguard Worker }
628*bebae9c0SAndroid Build Coastguard Worker }
629*bebae9c0SAndroid Build Coastguard Worker // The mutex is unlocked and destroyed by IObject_deinit, which is the last deinitializer
630*bebae9c0SAndroid Build Coastguard Worker memset(thiz, 0x55, clazz->mSize); // catch broken applications that continue using interfaces
631*bebae9c0SAndroid Build Coastguard Worker // was ifdef USE_DEBUG but safer to do this unconditionally
632*bebae9c0SAndroid Build Coastguard Worker if (SL_OBJECTID_ENGINE == clazz->mSLObjectID) {
633*bebae9c0SAndroid Build Coastguard Worker CEngine_Destroyed((CEngine *) thiz);
634*bebae9c0SAndroid Build Coastguard Worker }
635*bebae9c0SAndroid Build Coastguard Worker free(thiz);
636*bebae9c0SAndroid Build Coastguard Worker
637*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE_VOID
638*bebae9c0SAndroid Build Coastguard Worker }
639*bebae9c0SAndroid Build Coastguard Worker
640*bebae9c0SAndroid Build Coastguard Worker
IObject_SetPriority(SLObjectItf self,SLint32 priority,SLboolean preemptable)641*bebae9c0SAndroid Build Coastguard Worker static SLresult IObject_SetPriority(SLObjectItf self, SLint32 priority, SLboolean preemptable)
642*bebae9c0SAndroid Build Coastguard Worker {
643*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
644*bebae9c0SAndroid Build Coastguard Worker
645*bebae9c0SAndroid Build Coastguard Worker #if USE_PROFILES & USE_PROFILES_BASE
646*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
647*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
648*bebae9c0SAndroid Build Coastguard Worker thiz->mPriority = priority;
649*bebae9c0SAndroid Build Coastguard Worker thiz->mPreemptable = SL_BOOLEAN_FALSE != preemptable; // normalize
650*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
651*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
652*bebae9c0SAndroid Build Coastguard Worker #else
653*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_FEATURE_UNSUPPORTED;
654*bebae9c0SAndroid Build Coastguard Worker #endif
655*bebae9c0SAndroid Build Coastguard Worker
656*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
657*bebae9c0SAndroid Build Coastguard Worker }
658*bebae9c0SAndroid Build Coastguard Worker
659*bebae9c0SAndroid Build Coastguard Worker
IObject_GetPriority(SLObjectItf self,SLint32 * pPriority,SLboolean * pPreemptable)660*bebae9c0SAndroid Build Coastguard Worker static SLresult IObject_GetPriority(SLObjectItf self, SLint32 *pPriority, SLboolean *pPreemptable)
661*bebae9c0SAndroid Build Coastguard Worker {
662*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
663*bebae9c0SAndroid Build Coastguard Worker
664*bebae9c0SAndroid Build Coastguard Worker #if USE_PROFILES & USE_PROFILES_BASE
665*bebae9c0SAndroid Build Coastguard Worker if (NULL == pPriority || NULL == pPreemptable) {
666*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PARAMETER_INVALID;
667*bebae9c0SAndroid Build Coastguard Worker } else {
668*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
669*bebae9c0SAndroid Build Coastguard Worker object_lock_shared(thiz);
670*bebae9c0SAndroid Build Coastguard Worker SLint32 priority = thiz->mPriority;
671*bebae9c0SAndroid Build Coastguard Worker SLboolean preemptable = thiz->mPreemptable;
672*bebae9c0SAndroid Build Coastguard Worker object_unlock_shared(thiz);
673*bebae9c0SAndroid Build Coastguard Worker *pPriority = priority;
674*bebae9c0SAndroid Build Coastguard Worker *pPreemptable = preemptable;
675*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
676*bebae9c0SAndroid Build Coastguard Worker }
677*bebae9c0SAndroid Build Coastguard Worker #else
678*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_FEATURE_UNSUPPORTED;
679*bebae9c0SAndroid Build Coastguard Worker #endif
680*bebae9c0SAndroid Build Coastguard Worker
681*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
682*bebae9c0SAndroid Build Coastguard Worker }
683*bebae9c0SAndroid Build Coastguard Worker
684*bebae9c0SAndroid Build Coastguard Worker
IObject_SetLossOfControlInterfaces(SLObjectItf self,SLint16 numInterfaces,SLInterfaceID * pInterfaceIDs,SLboolean enabled)685*bebae9c0SAndroid Build Coastguard Worker static SLresult IObject_SetLossOfControlInterfaces(SLObjectItf self,
686*bebae9c0SAndroid Build Coastguard Worker SLint16 numInterfaces, SLInterfaceID *pInterfaceIDs, SLboolean enabled)
687*bebae9c0SAndroid Build Coastguard Worker {
688*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
689*bebae9c0SAndroid Build Coastguard Worker
690*bebae9c0SAndroid Build Coastguard Worker #if USE_PROFILES & USE_PROFILES_BASE
691*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
692*bebae9c0SAndroid Build Coastguard Worker if (0 < numInterfaces) {
693*bebae9c0SAndroid Build Coastguard Worker SLuint32 i;
694*bebae9c0SAndroid Build Coastguard Worker if (NULL == pInterfaceIDs) {
695*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PARAMETER_INVALID;
696*bebae9c0SAndroid Build Coastguard Worker } else {
697*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
698*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thiz->mClass;
699*bebae9c0SAndroid Build Coastguard Worker unsigned lossOfControlMask = 0;
700*bebae9c0SAndroid Build Coastguard Worker // The cast is due to a typo in the spec, bug 6482
701*bebae9c0SAndroid Build Coastguard Worker for (i = 0; i < (SLuint32) numInterfaces; ++i) {
702*bebae9c0SAndroid Build Coastguard Worker SLInterfaceID iid = pInterfaceIDs[i];
703*bebae9c0SAndroid Build Coastguard Worker if (NULL == iid) {
704*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PARAMETER_INVALID;
705*bebae9c0SAndroid Build Coastguard Worker goto out;
706*bebae9c0SAndroid Build Coastguard Worker }
707*bebae9c0SAndroid Build Coastguard Worker int MPH, index;
708*bebae9c0SAndroid Build Coastguard Worker // We ignore without error any invalid MPH or index, but spec is unclear
709*bebae9c0SAndroid Build Coastguard Worker if ((0 <= (MPH = IID_to_MPH(iid))) &&
710*bebae9c0SAndroid Build Coastguard Worker // no need to check for an initialization hook
711*bebae9c0SAndroid Build Coastguard Worker // (NULL == MPH_init_table[MPH].mInit) ||
712*bebae9c0SAndroid Build Coastguard Worker (0 <= (index = clazz->mMPH_to_index[MPH]))) {
713*bebae9c0SAndroid Build Coastguard Worker lossOfControlMask |= (1 << index);
714*bebae9c0SAndroid Build Coastguard Worker }
715*bebae9c0SAndroid Build Coastguard Worker }
716*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thiz);
717*bebae9c0SAndroid Build Coastguard Worker if (enabled) {
718*bebae9c0SAndroid Build Coastguard Worker thiz->mLossOfControlMask |= lossOfControlMask;
719*bebae9c0SAndroid Build Coastguard Worker } else {
720*bebae9c0SAndroid Build Coastguard Worker thiz->mLossOfControlMask &= ~lossOfControlMask;
721*bebae9c0SAndroid Build Coastguard Worker }
722*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thiz);
723*bebae9c0SAndroid Build Coastguard Worker }
724*bebae9c0SAndroid Build Coastguard Worker }
725*bebae9c0SAndroid Build Coastguard Worker out:
726*bebae9c0SAndroid Build Coastguard Worker #else
727*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_FEATURE_UNSUPPORTED;
728*bebae9c0SAndroid Build Coastguard Worker #endif
729*bebae9c0SAndroid Build Coastguard Worker
730*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
731*bebae9c0SAndroid Build Coastguard Worker }
732*bebae9c0SAndroid Build Coastguard Worker
733*bebae9c0SAndroid Build Coastguard Worker
734*bebae9c0SAndroid Build Coastguard Worker static const struct SLObjectItf_ IObject_Itf = {
735*bebae9c0SAndroid Build Coastguard Worker IObject_Realize,
736*bebae9c0SAndroid Build Coastguard Worker IObject_Resume,
737*bebae9c0SAndroid Build Coastguard Worker IObject_GetState,
738*bebae9c0SAndroid Build Coastguard Worker IObject_GetInterface,
739*bebae9c0SAndroid Build Coastguard Worker IObject_RegisterCallback,
740*bebae9c0SAndroid Build Coastguard Worker IObject_AbortAsyncOperation,
741*bebae9c0SAndroid Build Coastguard Worker IObject_Destroy,
742*bebae9c0SAndroid Build Coastguard Worker IObject_SetPriority,
743*bebae9c0SAndroid Build Coastguard Worker IObject_GetPriority,
744*bebae9c0SAndroid Build Coastguard Worker IObject_SetLossOfControlInterfaces
745*bebae9c0SAndroid Build Coastguard Worker };
746*bebae9c0SAndroid Build Coastguard Worker
747*bebae9c0SAndroid Build Coastguard Worker
748*bebae9c0SAndroid Build Coastguard Worker /** \brief This must be the first initializer called for an object */
749*bebae9c0SAndroid Build Coastguard Worker
IObject_init(void * self)750*bebae9c0SAndroid Build Coastguard Worker void IObject_init(void *self)
751*bebae9c0SAndroid Build Coastguard Worker {
752*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
753*bebae9c0SAndroid Build Coastguard Worker thiz->mItf = &IObject_Itf;
754*bebae9c0SAndroid Build Coastguard Worker // initialized in construct:
755*bebae9c0SAndroid Build Coastguard Worker // mClass
756*bebae9c0SAndroid Build Coastguard Worker // mInstanceID
757*bebae9c0SAndroid Build Coastguard Worker // mLossOfControlMask
758*bebae9c0SAndroid Build Coastguard Worker // mEngine
759*bebae9c0SAndroid Build Coastguard Worker // mInterfaceStates
760*bebae9c0SAndroid Build Coastguard Worker thiz->mState = SL_OBJECT_STATE_UNREALIZED;
761*bebae9c0SAndroid Build Coastguard Worker thiz->mGottenMask = 1; // IObject
762*bebae9c0SAndroid Build Coastguard Worker thiz->mAttributesMask = 0;
763*bebae9c0SAndroid Build Coastguard Worker thiz->mCallback = NULL;
764*bebae9c0SAndroid Build Coastguard Worker thiz->mContext = NULL;
765*bebae9c0SAndroid Build Coastguard Worker #if USE_PROFILES & USE_PROFILES_BASE
766*bebae9c0SAndroid Build Coastguard Worker thiz->mPriority = SL_PRIORITY_NORMAL;
767*bebae9c0SAndroid Build Coastguard Worker thiz->mPreemptable = SL_BOOLEAN_FALSE;
768*bebae9c0SAndroid Build Coastguard Worker #endif
769*bebae9c0SAndroid Build Coastguard Worker thiz->mStrongRefCount = 0;
770*bebae9c0SAndroid Build Coastguard Worker int ok;
771*bebae9c0SAndroid Build Coastguard Worker ok = pthread_mutex_init(&thiz->mMutex, (const pthread_mutexattr_t *) NULL);
772*bebae9c0SAndroid Build Coastguard Worker assert(0 == ok);
773*bebae9c0SAndroid Build Coastguard Worker #ifdef USE_DEBUG
774*bebae9c0SAndroid Build Coastguard Worker memset(&thiz->mOwner, 0, sizeof(pthread_t));
775*bebae9c0SAndroid Build Coastguard Worker thiz->mFile = NULL;
776*bebae9c0SAndroid Build Coastguard Worker thiz->mLine = 0;
777*bebae9c0SAndroid Build Coastguard Worker thiz->mGeneration = 0;
778*bebae9c0SAndroid Build Coastguard Worker #endif
779*bebae9c0SAndroid Build Coastguard Worker ok = pthread_cond_init(&thiz->mCond, (const pthread_condattr_t *) NULL);
780*bebae9c0SAndroid Build Coastguard Worker assert(0 == ok);
781*bebae9c0SAndroid Build Coastguard Worker }
782*bebae9c0SAndroid Build Coastguard Worker
783*bebae9c0SAndroid Build Coastguard Worker
784*bebae9c0SAndroid Build Coastguard Worker /** \brief This must be the last deinitializer called for an object */
785*bebae9c0SAndroid Build Coastguard Worker
IObject_deinit(void * self)786*bebae9c0SAndroid Build Coastguard Worker void IObject_deinit(void *self)
787*bebae9c0SAndroid Build Coastguard Worker {
788*bebae9c0SAndroid Build Coastguard Worker IObject *thiz = (IObject *) self;
789*bebae9c0SAndroid Build Coastguard Worker #ifdef USE_DEBUG
790*bebae9c0SAndroid Build Coastguard Worker assert(pthread_equal(pthread_self(), thiz->mOwner));
791*bebae9c0SAndroid Build Coastguard Worker #endif
792*bebae9c0SAndroid Build Coastguard Worker int ok;
793*bebae9c0SAndroid Build Coastguard Worker ok = pthread_cond_destroy(&thiz->mCond);
794*bebae9c0SAndroid Build Coastguard Worker assert(0 == ok);
795*bebae9c0SAndroid Build Coastguard Worker // equivalent to object_unlock_exclusive, but without the rigmarole
796*bebae9c0SAndroid Build Coastguard Worker ok = pthread_mutex_unlock(&thiz->mMutex);
797*bebae9c0SAndroid Build Coastguard Worker assert(0 == ok);
798*bebae9c0SAndroid Build Coastguard Worker ok = pthread_mutex_destroy(&thiz->mMutex);
799*bebae9c0SAndroid Build Coastguard Worker assert(0 == ok);
800*bebae9c0SAndroid Build Coastguard Worker // redundant: thiz->mState = SL_OBJECT_STATE_UNREALIZED;
801*bebae9c0SAndroid Build Coastguard Worker }
802*bebae9c0SAndroid Build Coastguard Worker
803*bebae9c0SAndroid Build Coastguard Worker
804*bebae9c0SAndroid Build Coastguard Worker /** \brief Publish a new object after it is fully initialized.
805*bebae9c0SAndroid Build Coastguard Worker * Publishing will expose the object to sync thread and debugger,
806*bebae9c0SAndroid Build Coastguard Worker * and make it safe to return the SLObjectItf to the application.
807*bebae9c0SAndroid Build Coastguard Worker */
808*bebae9c0SAndroid Build Coastguard Worker
IObject_Publish(IObject * thiz)809*bebae9c0SAndroid Build Coastguard Worker void IObject_Publish(IObject *thiz)
810*bebae9c0SAndroid Build Coastguard Worker {
811*bebae9c0SAndroid Build Coastguard Worker IEngine *thisEngine = &thiz->mEngine->mEngine;
812*bebae9c0SAndroid Build Coastguard Worker interface_lock_exclusive(thisEngine);
813*bebae9c0SAndroid Build Coastguard Worker // construct earlier reserved a pending slot, but did not choose the actual slot number
814*bebae9c0SAndroid Build Coastguard Worker unsigned availMask = ~thisEngine->mInstanceMask;
815*bebae9c0SAndroid Build Coastguard Worker assert(availMask);
816*bebae9c0SAndroid Build Coastguard Worker unsigned i = ctz(availMask);
817*bebae9c0SAndroid Build Coastguard Worker assert(MAX_INSTANCE > i);
818*bebae9c0SAndroid Build Coastguard Worker assert(NULL == thisEngine->mInstances[i]);
819*bebae9c0SAndroid Build Coastguard Worker thisEngine->mInstances[i] = thiz;
820*bebae9c0SAndroid Build Coastguard Worker thisEngine->mInstanceMask |= 1 << i;
821*bebae9c0SAndroid Build Coastguard Worker // avoid zero as a valid instance ID
822*bebae9c0SAndroid Build Coastguard Worker thiz->mInstanceID = i + 1;
823*bebae9c0SAndroid Build Coastguard Worker interface_unlock_exclusive(thisEngine);
824*bebae9c0SAndroid Build Coastguard Worker }
825