161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* 261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Copyright (C) 2010 The Android Open Source Project 361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * 461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * you may not use this file except in compliance with the License. 661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * You may obtain a copy of the License at 761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * 861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * 1061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Unless required by applicable law or agreed to in writing, software 1161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 1261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * See the License for the specific language governing permissions and 1461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * limitations under the License. 1561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten */ 1661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 1761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* Object implementation */ 1861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 1961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#include "sles_allinclusive.h" 2061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 21ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 22510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous Object.Realize. 23510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the Object. 24d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 25cf3a6383a9bc9a94ca5b424ea97313293ee0dcb0Glenn Kastenstatic void HandleRealize(void *self, void *ignored, int unused) 2661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 27510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 28510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // validate input parameters 29bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 30bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(NULL != thiz); 31bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thiz->mClass; 32bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(NULL != clazz); 33bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten AsyncHook realize = clazz->mRealize; 343a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten SLresult result; 35276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state; 36510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 37510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // check object state 38bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 39bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten state = thiz->mState; 40510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 41510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 42510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // normal case 43510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (NULL != realize) { 44bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = SL_OBJECT_STATE_REALIZING_2; 454260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten // Note that the mutex is locked on entry to and exit from the realize hook, 464260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten // but the hook is permitted to temporarily unlock the mutex (e.g. for async). 47bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten result = (*realize)(thiz, SL_BOOLEAN_TRUE); 48bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(SL_OBJECT_STATE_REALIZING_2 == thiz->mState); 49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED : 50510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SL_OBJECT_STATE_UNREALIZED; 51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 52510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_SUCCESS; 53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_REALIZED; 54510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 55510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 56510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 57510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: // operation was aborted while on work queue 58510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_OPERATION_ABORTED; 59510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_UNREALIZED; 60510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 61510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 62510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: // impossible 63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 64510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_INTERNAL_ERROR; 65510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 6761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 68510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mutex is locked, update state 70bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = state; 71510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 72d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Make a copy of these, so we can call the callback with mutex unlocked 73bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten slObjectCallback callback = thiz->mCallback; 74bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten void *context = thiz->mContext; 75bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 76510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 77d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Note that the mutex is unlocked during the callback 788c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (NULL != callback) { 79bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (*callback)(&thiz->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL); 808c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 81d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 82d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 83ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 84d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IObject_Realize(SLObjectItf self, SLboolean async) 85d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 86ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 87ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 88bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 89276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state; 90bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thiz->mClass; 911d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten bool isSharedEngine = false; 92bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 931d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten // note that SL_OBJECTID_ENGINE and XA_OBJECTID_ENGINE map to same class 94bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten if (clazz == objectIDtoClass(SL_OBJECTID_ENGINE)) { 951d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten // important: the lock order is engine followed by theOneTrueMutex 961d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten int ok = pthread_mutex_lock(&theOneTrueMutex); 971d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten assert(0 == ok); 981d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten isSharedEngine = 1 < theOneTrueRefCount; 991d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten ok = pthread_mutex_unlock(&theOneTrueMutex); 1001d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten assert(0 == ok); 1011d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten } 102bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten state = thiz->mState; 1031d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten // Reject redundant calls to Realize, except on a shared engine 104d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (SL_OBJECT_STATE_UNREALIZED != state) { 105bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 1061d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten // redundant realize on the shared engine is permitted 1071d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten if (isSharedEngine && (SL_OBJECT_STATE_REALIZED == state)) { 1081d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten result = SL_RESULT_SUCCESS; 1091d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten } else { 1101d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 1111d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten } 112d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } else { 113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Asynchronous: mark operation pending and cancellable 114bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten if (async && (SL_OBJECTID_ENGINE != clazz->mSLObjectID)) { 115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_REALIZING_1; 116ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Synchronous: mark operation pending and non-cancellable 117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_REALIZING_2; 119d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 120bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = state; 121ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (state) { 122ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // asynchronous on non-Engine 1234260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten object_unlock_exclusive(thiz); 124ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(async); 125cf3a6383a9bc9a94ca5b424ea97313293ee0dcb0Glenn Kasten result = ThreadPool_add_ppi(&thiz->mEngine->mThreadPool, HandleRealize, thiz, NULL, 0); 126ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (SL_RESULT_SUCCESS != result) { 127ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Engine was destroyed during realize, or insufficient memory 128bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 129bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = SL_OBJECT_STATE_UNREALIZED; 130bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 131ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 132ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 133ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: // synchronous, or asynchronous on Engine 134ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten { 135bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten AsyncHook realize = clazz->mRealize; 1364260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten // Note that the mutex is locked on entry to and exit from the realize hook, 1374260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten // but the hook is permitted to temporarily unlock the mutex (e.g. for async). 138bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten result = (NULL != realize) ? (*realize)(thiz, async) : SL_RESULT_SUCCESS; 139bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(SL_OBJECT_STATE_REALIZING_2 == thiz->mState); 140ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED : 141ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_OBJECT_STATE_UNREALIZED; 142bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = state; 143bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten slObjectCallback callback = thiz->mCallback; 144bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten void *context = thiz->mContext; 145bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 146ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // asynchronous Realize on an Engine is actually done synchronously, but still has 147ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // callback because there is no thread pool yet to do it asynchronously. 1488c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (async && (NULL != callback)) { 149bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (*callback)(&thiz->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, 150ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten NULL); 151ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 1528c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 153ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 154ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: // impossible 1554260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten object_unlock_exclusive(thiz); 156ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_BOOLEAN_FALSE); 157ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 158d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 159d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 160ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 161ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 16261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 16361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 164ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 165510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous Object.Resume. 166510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the Object. 167510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 168cf3a6383a9bc9a94ca5b424ea97313293ee0dcb0Glenn Kastenstatic void HandleResume(void *self, void *ignored, int unused) 16961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 170510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 171510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // valid input parameters 172bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 173bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(NULL != thiz); 174bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thiz->mClass; 175bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(NULL != clazz); 176bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten AsyncHook resume = clazz->mResume; 1773a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten SLresult result; 178276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state; 179510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 180510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // check object state 181bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 182bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten state = thiz->mState; 183510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 184510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 185510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // normal case 186510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (NULL != resume) { 187bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = SL_OBJECT_STATE_RESUMING_2; 1884260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten // Note that the mutex is locked on entry to and exit from the resume hook, 1894260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten // but the hook is permitted to temporarily unlock the mutex (e.g. for async). 190bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten result = (*resume)(thiz, SL_BOOLEAN_TRUE); 191bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(SL_OBJECT_STATE_RESUMING_2 == thiz->mState); 192510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED : 193510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SL_OBJECT_STATE_SUSPENDED; 194510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 195510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_SUCCESS; 196510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_REALIZED; 1973a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten } 198510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 199510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 200510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: // operation was aborted while on work queue 201510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_OPERATION_ABORTED; 202510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_SUSPENDED; 203510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 204510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 205510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: // impossible 206510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 207510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_INTERNAL_ERROR; 208510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 209510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 21061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 211510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 212510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mutex is unlocked, update state 213bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = state; 214510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 215510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Make a copy of these, so we can call the callback with mutex unlocked 216bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten slObjectCallback callback = thiz->mCallback; 217bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten void *context = thiz->mContext; 218bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 219510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 220510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the callback 2218c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (NULL != callback) { 222bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (*callback)(&thiz->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL); 2238c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 224510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten} 225510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 226ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 227510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic SLresult IObject_Resume(SLObjectItf self, SLboolean async) 228510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{ 229ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 230ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 231bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 232bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thiz->mClass; 233276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state; 234bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 235bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten state = thiz->mState; 236510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Reject redundant calls to Resume 237510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (SL_OBJECT_STATE_SUSPENDED != state) { 238bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 239ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 240510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 241ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Asynchronous: mark operation pending and cancellable 242ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (async) { 243ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_RESUMING_1; 244ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Synchronous: mark operatio pending and non-cancellable 245ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 246ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_RESUMING_2; 247510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 248bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = state; 249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (state) { 250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // asynchronous 2514260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten object_unlock_exclusive(thiz); 252ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(async); 253cf3a6383a9bc9a94ca5b424ea97313293ee0dcb0Glenn Kasten result = ThreadPool_add_ppi(&thiz->mEngine->mThreadPool, HandleResume, thiz, NULL, 0); 254ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (SL_RESULT_SUCCESS != result) { 255ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Engine was destroyed during resume, or insufficient memory 256bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 257bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = SL_OBJECT_STATE_SUSPENDED; 258bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 259ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 260ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 261ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: // synchronous 262ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten { 263bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten AsyncHook resume = clazz->mResume; 2644260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten // Note that the mutex is locked on entry to and exit from the resume hook, 2654260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten // but the hook is permitted to temporarily unlock the mutex (e.g. for async). 266bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten result = (NULL != resume) ? (*resume)(thiz, SL_BOOLEAN_FALSE) : SL_RESULT_SUCCESS; 267bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(SL_OBJECT_STATE_RESUMING_2 == thiz->mState); 268bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED : 269ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_OBJECT_STATE_SUSPENDED; 270bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 271ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 272ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 273ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: // impossible 2744260ff7b8f65fdfe8d0176cdce66faf0a10c4b10Glenn Kasten object_unlock_exclusive(thiz); 275ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_BOOLEAN_FALSE); 276ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 277510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 278510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 279ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 280ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 28161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 28261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 283ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 28461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_GetState(SLObjectItf self, SLuint32 *pState) 28561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 286ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 287ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 288ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pState) { 289ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 290ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 291bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 292b566926611b2105a46c4ff98238ad06aca54104dGlenn Kasten object_lock_shared(thiz); 293bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten SLuint8 state = thiz->mState; 294b566926611b2105a46c4ff98238ad06aca54104dGlenn Kasten object_unlock_shared(thiz); 295ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Re-map the realizing, resuming, and suspending states 296ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (state) { 297ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: 298ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: 299ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: 300928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_DESTROYING: // application shouldn't call GetState after Destroy 301ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_UNREALIZED; 302ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 303ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: 304ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: 305ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: 306ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_SUSPENDING: 307ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_SUSPENDED; 308ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 309ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_UNREALIZED: 310ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZED: 311ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_SUSPENDED: 312ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // These are the "official" object states, return them as is 313ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 314ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: 315ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_BOOLEAN_FALSE); 316ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 317ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 318ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pState = state; 319ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 320d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 321ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 322ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 32361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 32461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 3253a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetInterface(SLObjectItf self, const SLInterfaceID iid, void *pInterface) 32661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 327ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 328ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 329ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pInterface) { 33061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten result = SL_RESULT_PARAMETER_INVALID; 331ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 332ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten void *interface = NULL; 333ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == iid) { 334ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 335510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 336bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 337bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thiz->mClass; 338ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten int MPH, index; 339a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten if ((0 > (MPH = IID_to_MPH(iid))) || 340a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // no need to check for an initialization hook 341a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // (NULL == MPH_init_table[MPH].mInit) || 342bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (0 > (index = clazz->mMPH_to_index[MPH]))) { 343ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 344510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 345ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten unsigned mask = 1 << index; 346bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 347bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten if ((SL_OBJECT_STATE_REALIZED != thiz->mState) && 348bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten !(INTERFACE_PREREALIZE & clazz->mInterfaces[index].mInterface)) { 349104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten // Can't get interface on an unrealized object unless pre-realize is ok 350ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 3518b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten } else if ((MPH_MUTESOLO == MPH) && (SL_OBJECTID_AUDIOPLAYER == 352bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten clazz->mSLObjectID) && (1 == ((CAudioPlayer *) thiz)->mNumChannels)) { 353f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten // Can't get the MuteSolo interface of an audio player if the channel count is 354f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten // mono, but _can_ get the MuteSolo interface if the channel count is unknown 355f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 356ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 357bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten switch (thiz->mInterfaceStates[index]) { 358ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_EXPOSED: 359ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_ADDED: 360bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interface = (char *) thiz + clazz->mInterfaces[index].mOffset; 361ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Note that interface has been gotten, 362ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // for debugger and to detect incorrect use of interfaces 363bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten if (!(thiz->mGottenMask & mask)) { 364bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mGottenMask |= mask; 365711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // This trickery validates the v-table 366e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten ((size_t *) interface)[0] ^= ~0; 367e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten } 368ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 369ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 370a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // Can't get interface if uninitialized, initialized, suspended, 371a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // suspending, resuming, adding, or removing 372ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: 373ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 374ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 375ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 376510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 377bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 37861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 37961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 380ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *(void **)pInterface = interface; 38161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 382ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 383ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 38461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 38561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 386ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 38761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_RegisterCallback(SLObjectItf self, 38861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten slObjectCallback callback, void *pContext) 38961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 390ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 391ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 392bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 393bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 394bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mCallback = callback; 395bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mContext = pContext; 396bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 397ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 398ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 399ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 40061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 40161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 402ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 403928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief This is internal common code for Abort and Destroy. 404928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten * Note: called with mutex unlocked, and returns with mutex locked. 405928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */ 406510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 407bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenstatic void Abort_internal(IObject *thiz) 408510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{ 409bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thiz->mClass; 410928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten bool anyAsync = false; 411bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 412928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 413510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Abort asynchronous operations on the object 414bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten switch (thiz->mState) { 415510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // Realize 416bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = SL_OBJECT_STATE_REALIZING_1A; 417928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 418510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 419510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // Resume 420bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = SL_OBJECT_STATE_RESUMING_1A; 421928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 422928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 423928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: // Realize 424928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: 425928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: // Resume 426928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: 427928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 428928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 429928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_DESTROYING: 430928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten assert(false); 431510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 432510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 433510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 434510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 435928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 436510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Abort asynchronous operations on interfaces 437bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten SLuint8 *interfaceStateP = thiz->mInterfaceStates; 438510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned index; 439bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten for (index = 0; index < clazz->mInterfaceCount; ++index, ++interfaceStateP) { 440510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (*interfaceStateP) { 441510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1: // AddInterface 442510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_ADDING_1A; 443928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 444510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 445510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: // ResumeInterface 446510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_RESUMING_1A; 447928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 448928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 449928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_1A: // AddInterface 450928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_2: 451928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_1A: // ResumeInterface 452928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_2: 453711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten case INTERFACE_REMOVING: // not observable: RemoveInterface is synchronous & mutex locked 454928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 455510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 456510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 457510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 458510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 459510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 460928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 461928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // Wait until all asynchronous operations either complete normally or recognize the abort 462928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten while (anyAsync) { 463bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 464928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // FIXME should use condition variable instead of polling 465928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten usleep(20000); 466928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = false; 467bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 468bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten switch (thiz->mState) { 469928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // state 1 means it cycled during the usleep window 470928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: 471928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: 472928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: 473928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: 474928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: 475928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 476928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 477928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_DESTROYING: 478928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten assert(false); 479928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 480928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten default: 481928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 482928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 483bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten interfaceStateP = thiz->mInterfaceStates; 484bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten for (index = 0; index < clazz->mInterfaceCount; ++index, ++interfaceStateP) { 485928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten switch (*interfaceStateP) { 486928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_1: // state 1 means it cycled during the usleep window 487928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_1: 488928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_1A: 489928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_2: 490928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_1A: 491928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_2: 492928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_REMOVING: 493928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 494928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 495928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten default: 496928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 497928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 498928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 499928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 500928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 501928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // At this point there are no pending asynchronous operations 502510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten} 503510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 504ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 50561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_AbortAsyncOperation(SLObjectItf self) 50661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 507ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE_VOID 508ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 509bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 510bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten Abort_internal(thiz); 511bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 512ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 513ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE_VOID 51461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 51561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 516ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 517f51dba65751107c930759938775b75531ec1f330Glenn Kastenvoid IObject_Destroy(SLObjectItf self) 51861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 519ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE_VOID 520ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 521bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 522928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // mutex is unlocked 523bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten Abort_internal(thiz); 524928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // mutex is locked 525bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thiz->mClass; 526bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten PreDestroyHook preDestroy = clazz->mPreDestroy; 527928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // The pre-destroy hook is called with mutex locked, and should block until it is safe to 528928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // destroy. It is OK to unlock the mutex temporarily, as it long as it re-locks the mutex 529928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // before returning. 530928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten if (NULL != preDestroy) { 531bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten predestroy_t okToDestroy = (*preDestroy)(thiz); 5321d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten switch (okToDestroy) { 5331d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten case predestroy_ok: 5341d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten break; 5351d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten case predestroy_error: 536bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten SL_LOGE("Object::Destroy(%p) not allowed", thiz); 5371d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten // fall through 5381d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten case predestroy_again: 539bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 540928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // unfortunately Destroy doesn't return a result 541928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten SL_LEAVE_INTERFACE_VOID 5421d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten // unreachable 5431d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten default: 5441d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten assert(false); 5451d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten break; 546928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 547928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 548bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = SL_OBJECT_STATE_DESTROYING; 549bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten VoidHook destroy = clazz->mDestroy; 550ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // const, no lock needed 551bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IEngine *thisEngine = &thiz->mEngine->mEngine; 552bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten unsigned i = thiz->mInstanceID; 553f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(MAX_INSTANCE >= i); 554928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // avoid a recursive lock on the engine when destroying the engine itself 555bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten if (thisEngine->mThis != thiz) { 556928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten interface_lock_exclusive(thisEngine); 557928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 558f51dba65751107c930759938775b75531ec1f330Glenn Kasten // An unpublished object has a slot reserved, but the ID hasn't been chosen yet 559ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten assert(0 < thisEngine->mInstanceCount); 560ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten --thisEngine->mInstanceCount; 561f51dba65751107c930759938775b75531ec1f330Glenn Kasten // If object is published, then remove it from exposure to sync thread and debugger 562f51dba65751107c930759938775b75531ec1f330Glenn Kasten if (0 != i) { 563f51dba65751107c930759938775b75531ec1f330Glenn Kasten --i; 564104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten unsigned mask = 1 << i; 565104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten assert(thisEngine->mInstanceMask & mask); 566104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten thisEngine->mInstanceMask &= ~mask; 567bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(thisEngine->mInstances[i] == thiz); 568f51dba65751107c930759938775b75531ec1f330Glenn Kasten thisEngine->mInstances[i] = NULL; 56900d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten } 570928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // avoid a recursive unlock on the engine when destroying the engine itself 571bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten if (thisEngine->mThis != thiz) { 572928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten interface_unlock_exclusive(thisEngine); 573928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 574d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten // The destroy hook is called with mutex locked 5758c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (NULL != destroy) { 576bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (*destroy)(thiz); 5778c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 578a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // Call the deinitializer for each currently initialized interface, 57961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten // whether it is implicit, explicit, optional, or dynamically added. 5804597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // The deinitializers are called in the reverse order that the 5814597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // initializers were called, so that IObject_deinit is called last. 582bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten unsigned index = clazz->mInterfaceCount; 583bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const struct iid_vtable *x = &clazz->mInterfaces[index]; 584bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten SLuint8 *interfaceStateP = &thiz->mInterfaceStates[index]; 5854597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten for ( ; index > 0; --index) { 5864597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten --x; 587711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten size_t offset = x->mOffset; 588bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten void *thisItf = (char *) thiz + offset; 5894597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten SLuint32 state = *--interfaceStateP; 590510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 591510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_UNINITIALIZED: 592510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 593510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_EXPOSED: // quiescent states 594510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDED: 595510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDED: 596711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // The remove hook is called with mutex locked 597711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten { 598711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten VoidHook remove = MPH_init_table[x->mMPH].mRemove; 599711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten if (NULL != remove) { 600711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten (*remove)(thisItf); 601711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten } 602711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten *interfaceStateP = INTERFACE_INITIALIZED; 603711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten } 604a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // fall through 605a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten case INTERFACE_INITIALIZED: 606510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten { 60761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten VoidHook deinit = MPH_init_table[x->mMPH].mDeinit; 6088c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (NULL != deinit) { 609a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten (*deinit)(thisItf); 610510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 611a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten *interfaceStateP = INTERFACE_UNINITIALIZED; 6128c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 613510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 614510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1: // active states indicate incorrect use of API 615510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1A: 616510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_2: 617510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: 618510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1A: 619510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_2: 620510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_REMOVING: 621510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDING: 622bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten SL_LOGE("Object::Destroy(%p) while interface %u active", thiz, index); 623510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 624510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 625510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 626510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 62761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 62861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 6294597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // The mutex is unlocked and destroyed by IObject_deinit, which is the last deinitializer 630bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten memset(thiz, 0x55, clazz->mSize); // catch broken applications that continue using interfaces 631711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // was ifdef USE_DEBUG but safer to do this unconditionally 632bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten free(thiz); 633ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 634bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten if (SL_OBJECTID_ENGINE == clazz->mSLObjectID) { 635bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten CEngine_Destroyed((CEngine *) thiz); 636711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten } 637711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten 638ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE_VOID 63961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 64061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 641ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 6423a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_SetPriority(SLObjectItf self, SLint32 priority, SLboolean preemptable) 64361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 644ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 645ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 646a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 647bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 648bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 649bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mPriority = priority; 650bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mPreemptable = SL_BOOLEAN_FALSE != preemptable; // normalize 651bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 652ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 6537a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#else 6547a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 6557a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 656ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 657ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 65861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 65961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 660ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 6613a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetPriority(SLObjectItf self, SLint32 *pPriority, SLboolean *pPreemptable) 66261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 663ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 664ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 665a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 666ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pPriority || NULL == pPreemptable) { 667ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 668ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 669bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 670bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_shared(thiz); 671bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten SLint32 priority = thiz->mPriority; 672bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten SLboolean preemptable = thiz->mPreemptable; 673bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_shared(thiz); 674ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pPriority = priority; 675ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pPreemptable = preemptable; 676ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 677ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 6787a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#else 6797a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 6807a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 681ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 682ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 68361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 68461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 685ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 68661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_SetLossOfControlInterfaces(SLObjectItf self, 68761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLint16 numInterfaces, SLInterfaceID *pInterfaceIDs, SLboolean enabled) 68861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 689ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 690ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 691a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 692ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 69361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (0 < numInterfaces) { 69461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLuint32 i; 695ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pInterfaceIDs) { 696ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 697ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 698bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 699bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thiz->mClass; 700ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten unsigned lossOfControlMask = 0; 7017a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten // The cast is due to a typo in the spec, bug 6482 702ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten for (i = 0; i < (SLuint32) numInterfaces; ++i) { 703ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLInterfaceID iid = pInterfaceIDs[i]; 704ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == iid) { 705ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 706ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten goto out; 707ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 708ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten int MPH, index; 7097a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten // We ignore without error any invalid MPH or index, but spec is unclear 710a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten if ((0 <= (MPH = IID_to_MPH(iid))) && 711a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // no need to check for an initialization hook 712a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // (NULL == MPH_init_table[MPH].mInit) || 713bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (0 <= (index = clazz->mMPH_to_index[MPH]))) { 714ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten lossOfControlMask |= (1 << index); 715928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 716ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 717bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_lock_exclusive(thiz); 7188c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (enabled) { 719bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mLossOfControlMask |= lossOfControlMask; 7208c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } else { 721bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mLossOfControlMask &= ~lossOfControlMask; 7228c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 723bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten object_unlock_exclusive(thiz); 72461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 72561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 726ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kastenout: 7277a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#else 7287a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 7297a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 730ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 731ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 73261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 73361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 734ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 73561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLObjectItf_ IObject_Itf = { 73661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Realize, 73761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Resume, 73861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetState, 73961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetInterface, 74061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_RegisterCallback, 74161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_AbortAsyncOperation, 74261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Destroy, 74361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_SetPriority, 74461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetPriority, 745a361b51914aeb5f8f65c7ecad719d1e01f90913bGlenn Kasten IObject_SetLossOfControlInterfaces 74661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}; 74761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 7484597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7494597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten/** \brief This must be the first initializer called for an object */ 7504597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 75161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IObject_init(void *self) 75261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 753bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 754bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mItf = &IObject_Itf; 7550b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // initialized in construct: 7560b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // mClass 757ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // mInstanceID 7580b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // mLossOfControlMask 759ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // mEngine 760a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // mInterfaceStates 761bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mState = SL_OBJECT_STATE_UNREALIZED; 762bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mGottenMask = 1; // IObject 763bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mAttributesMask = 0; 764bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mCallback = NULL; 765bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mContext = NULL; 766a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 767bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mPriority = SL_PRIORITY_NORMAL; 768bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mPreemptable = SL_BOOLEAN_FALSE; 7697a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 770bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mStrongRefCount = 0; 77161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten int ok; 772bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_mutex_init(&thiz->mMutex, (const pthread_mutexattr_t *) NULL); 77361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten assert(0 == ok); 774fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG 775bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten memset(&thiz->mOwner, 0, sizeof(pthread_t)); 776bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mFile = NULL; 777bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mLine = 0; 7784ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten thiz->mGeneration = 0; 779fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif 780bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_cond_init(&thiz->mCond, (const pthread_condattr_t *) NULL); 78161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten assert(0 == ok); 78261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 7834597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7844597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7854597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten/** \brief This must be the last deinitializer called for an object */ 7864597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7874597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kastenvoid IObject_deinit(void *self) 7884597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten{ 789bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thiz = (IObject *) self; 7904597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#ifdef USE_DEBUG 791bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(pthread_equal(pthread_self(), thiz->mOwner)); 7924597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#endif 7934597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten int ok; 794bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_cond_destroy(&thiz->mCond); 7954597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(0 == ok); 7964597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // equivalent to object_unlock_exclusive, but without the rigmarole 797bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_mutex_unlock(&thiz->mMutex); 7984597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(0 == ok); 799bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_mutex_destroy(&thiz->mMutex); 8004597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(0 == ok); 801bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten // redundant: thiz->mState = SL_OBJECT_STATE_UNREALIZED; 8024597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten} 803f51dba65751107c930759938775b75531ec1f330Glenn Kasten 804f51dba65751107c930759938775b75531ec1f330Glenn Kasten 805f51dba65751107c930759938775b75531ec1f330Glenn Kasten/** \brief Publish a new object after it is fully initialized. 806f51dba65751107c930759938775b75531ec1f330Glenn Kasten * Publishing will expose the object to sync thread and debugger, 807f51dba65751107c930759938775b75531ec1f330Glenn Kasten * and make it safe to return the SLObjectItf to the application. 808f51dba65751107c930759938775b75531ec1f330Glenn Kasten */ 809f51dba65751107c930759938775b75531ec1f330Glenn Kasten 810bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid IObject_Publish(IObject *thiz) 811f51dba65751107c930759938775b75531ec1f330Glenn Kasten{ 812bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IEngine *thisEngine = &thiz->mEngine->mEngine; 813f51dba65751107c930759938775b75531ec1f330Glenn Kasten interface_lock_exclusive(thisEngine); 814f51dba65751107c930759938775b75531ec1f330Glenn Kasten // construct earlier reserved a pending slot, but did not choose the actual slot number 815f51dba65751107c930759938775b75531ec1f330Glenn Kasten unsigned availMask = ~thisEngine->mInstanceMask; 816f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(availMask); 817f51dba65751107c930759938775b75531ec1f330Glenn Kasten unsigned i = ctz(availMask); 818f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(MAX_INSTANCE > i); 819f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(NULL == thisEngine->mInstances[i]); 820bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thisEngine->mInstances[i] = thiz; 821f51dba65751107c930759938775b75531ec1f330Glenn Kasten thisEngine->mInstanceMask |= 1 << i; 822f51dba65751107c930759938775b75531ec1f330Glenn Kasten // avoid zero as a valid instance ID 823bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mInstanceID = i + 1; 824f51dba65751107c930759938775b75531ec1f330Glenn Kasten interface_unlock_exclusive(thisEngine); 825f51dba65751107c930759938775b75531ec1f330Glenn Kasten} 826