IObject.c revision 1d081e49a10543018e1ae33792bd3d30504719ba
10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2010 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/* Object implementation */
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
19a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#include "sles_allinclusive.h"
20b0b637dbf2a67c0e7eee917c0809f1cc54983986Robert Greenwalt
21a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville// Called by a worker thread to handle an asynchronous Object.Realize.
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville// Parameter self is the Object.
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillestatic void HandleRealize(void *self, int unused)
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
270c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville
28ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    // validate input parameters
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject *this = (IObject *) self;
300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    assert(NULL != this);
31a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    const ClassTable *class__ = this->mClass;
32b0b637dbf2a67c0e7eee917c0809f1cc54983986Robert Greenwalt    assert(NULL != class__);
33203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    AsyncHook realize = class__->mRealize;
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SLresult result;
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SLuint8 state;
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // check object state
385fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    object_lock_exclusive(this);
39ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    state = this->mState;
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    switch (state) {
41454b1dfd508844b42eb775e4ab2359be74d3672bWink Saville
42d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka    case SL_OBJECT_STATE_REALIZING_1:   // normal case
43d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka        if (NULL != realize) {
44d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka            this->mState = SL_OBJECT_STATE_REALIZING_2;
45e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka            object_unlock_exclusive(this);
46e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka            // Note that the mutex is unlocked during the realize hook
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            result = (*realize)(this, SL_BOOLEAN_TRUE);
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            object_lock_exclusive(this);
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assert(SL_OBJECT_STATE_REALIZING_2 == this->mState);
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED :
515fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville                SL_OBJECT_STATE_UNREALIZED;
525fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        } else {
535fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville            result = SL_RESULT_SUCCESS;
5460ced166cb63c35a0ebbee1fc356cddcb76b956fJeff Sharkey            state = SL_OBJECT_STATE_REALIZED;
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        break;
57e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka
58e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    case SL_OBJECT_STATE_REALIZING_1A:  // operation was aborted while on work queue
59e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka        result = SL_RESULT_OPERATION_ABORTED;
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        state = SL_OBJECT_STATE_UNREALIZED;
61ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville        break;
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
63f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville    default:                            // impossible
64f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville        assert(SL_BOOLEAN_FALSE);
6522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        result = SL_RESULT_INTERNAL_ERROR;
6622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        break;
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
680c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville    }
690c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville
705fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    // mutex is locked, update state
71ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    this->mState = state;
72ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville
73ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    // Make a copy of these, so we can call the callback with mutex unlocked
74ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    slObjectCallback callback = this->mCallback;
75ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    void *context = this->mContext;
76ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    object_unlock_exclusive(this);
77ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville
78ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    // Note that the mutex is unlocked during the callback
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    if (NULL != callback) {
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL);
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillestatic SLresult IObject_Realize(SLObjectItf self, SLboolean async)
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_ENTER_INTERFACE
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject *this = (IObject *) self;
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SLuint8 state;
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    const ClassTable *class__ = this->mClass;
9222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    bool isSharedEngine = false;
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    object_lock_exclusive(this);
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // note that SL_OBJECTID_ENGINE and XA_OBJECTID_ENGINE map to same class
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    if (class__ == objectIDtoClass(SL_OBJECTID_ENGINE)) {
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // important: the lock order is engine followed by theOneTrueMutex
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int ok = pthread_mutex_lock(&theOneTrueMutex);
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assert(0 == ok);
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        isSharedEngine = 1 < theOneTrueRefCount;
10022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ok = pthread_mutex_unlock(&theOneTrueMutex);
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assert(0 == ok);
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    state = this->mState;
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Reject redundant calls to Realize, except on a shared engine
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    if (SL_OBJECT_STATE_UNREALIZED != state) {
106203e588e3c42a81aa8a56f595119c181a63b12caWink Saville        object_unlock_exclusive(this);
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // redundant realize on the shared engine is permitted
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (isSharedEngine && (SL_OBJECT_STATE_REALIZED == state)) {
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            result = SL_RESULT_SUCCESS;
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            result = SL_RESULT_PRECONDITIONS_VIOLATED;
112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    } else {
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Asynchronous: mark operation pending and cancellable
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (async && (SL_OBJECTID_ENGINE != class__->mSLObjectID)) {
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = SL_OBJECT_STATE_REALIZING_1;
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Synchronous: mark operation pending and non-cancellable
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = SL_OBJECT_STATE_REALIZING_2;
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        this->mState = state;
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        object_unlock_exclusive(this);
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (state) {
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_REALIZING_1: // asynchronous on non-Engine
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assert(async);
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            result = ThreadPool_add(&this->mEngine->mThreadPool, HandleRealize, this, 0);
1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (SL_RESULT_SUCCESS != result) {
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Engine was destroyed during realize, or insufficient memory
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                object_lock_exclusive(this);
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                this->mState = SL_OBJECT_STATE_UNREALIZED;
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                object_unlock_exclusive(this);
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_REALIZING_2: // synchronous, or asynchronous on Engine
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            AsyncHook realize = class__->mRealize;
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Note that the mutex is unlocked during the realize hook
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            result = (NULL != realize) ? (*realize)(this, async) : SL_RESULT_SUCCESS;
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            object_lock_exclusive(this);
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assert(SL_OBJECT_STATE_REALIZING_2 == this->mState);
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED :
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                SL_OBJECT_STATE_UNREALIZED;
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            this->mState = state;
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            slObjectCallback callback = this->mCallback;
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            void *context = this->mContext;
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            object_unlock_exclusive(this);
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // asynchronous Realize on an Engine is actually done synchronously, but still has
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // callback because there is no thread pool yet to do it asynchronously.
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (async && (NULL != callback)) {
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state,
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    NULL);
152ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville            }
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        default:                          // impossible
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assert(SL_BOOLEAN_FALSE);
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_LEAVE_INTERFACE
162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
1635fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville
1645fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville
165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// Called by a worker thread to handle an asynchronous Object.Resume.
1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville// Parameter self is the Object.
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillestatic void HandleResume(void *self, int unused)
1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // valid input parameters
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject *this = (IObject *) self;
1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    assert(NULL != this);
1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    const ClassTable *class__ = this->mClass;
1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    assert(NULL != class__);
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    AsyncHook resume = class__->mResume;
1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SLresult result;
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SLuint8 state;
1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // check object state
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    object_lock_exclusive(this);
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    state = this->mState;
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    switch (state) {
1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    case SL_OBJECT_STATE_RESUMING_1:    // normal case
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (NULL != resume) {
1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            this->mState = SL_OBJECT_STATE_RESUMING_2;
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            object_unlock_exclusive(this);
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Note that the mutex is unlocked during the resume hook
1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            result = (*resume)(this, SL_BOOLEAN_TRUE);
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            object_lock_exclusive(this);
1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assert(SL_OBJECT_STATE_RESUMING_2 == this->mState);
1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED :
1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                SL_OBJECT_STATE_SUSPENDED;
1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            result = SL_RESULT_SUCCESS;
1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = SL_OBJECT_STATE_REALIZED;
1985fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        }
1995fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        break;
2005fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville
2015fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    case SL_OBJECT_STATE_RESUMING_1A:   // operation was aborted while on work queue
2025fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        result = SL_RESULT_OPERATION_ABORTED;
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        state = SL_OBJECT_STATE_SUSPENDED;
2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        break;
2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    default:                            // impossible
207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        assert(SL_BOOLEAN_FALSE);
208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        result = SL_RESULT_INTERNAL_ERROR;
209a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        break;
210a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
21303586878fb3d870373f2fdf65afb81cc5ae97067Naveen Kalla    // mutex is unlocked, update state
21403586878fb3d870373f2fdf65afb81cc5ae97067Naveen Kalla    this->mState = state;
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
216049ab0421f32e6effc5d1277b69bd382cebadb18Wink Saville    // Make a copy of these, so we can call the callback with mutex unlocked
217ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    slObjectCallback callback = this->mCallback;
218ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    void *context = this->mContext;
21922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    object_unlock_exclusive(this);
220f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville
221f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville    // Note that the mutex is unlocked during the callback
222e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka    if (NULL != callback) {
223e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka        (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL);
22422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    }
2255fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville}
226c4161078eff3305894f1f9f1b2f00952ea0e83d8Kazuya Ohshiro
227c4161078eff3305894f1f9f1b2f00952ea0e83d8Kazuya Ohshiro
228c4161078eff3305894f1f9f1b2f00952ea0e83d8Kazuya Ohshirostatic SLresult IObject_Resume(SLObjectItf self, SLboolean async)
229ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville{
230ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    SL_ENTER_INTERFACE
23103586878fb3d870373f2fdf65afb81cc5ae97067Naveen Kalla
23203586878fb3d870373f2fdf65afb81cc5ae97067Naveen Kalla    IObject *this = (IObject *) self;
23303586878fb3d870373f2fdf65afb81cc5ae97067Naveen Kalla    const ClassTable *class__ = this->mClass;
23403586878fb3d870373f2fdf65afb81cc5ae97067Naveen Kalla    SLuint8 state;
23503586878fb3d870373f2fdf65afb81cc5ae97067Naveen Kalla    object_lock_exclusive(this);
23603586878fb3d870373f2fdf65afb81cc5ae97067Naveen Kalla    state = this->mState;
23703586878fb3d870373f2fdf65afb81cc5ae97067Naveen Kalla    // Reject redundant calls to Resume
238ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    if (SL_OBJECT_STATE_SUSPENDED != state) {
23922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        object_unlock_exclusive(this);
240c26fb77c4e637466cf0483a4995fe82e6f68b8d3Alex Yakavenka        result = SL_RESULT_PRECONDITIONS_VIOLATED;
2415fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    } else {
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Asynchronous: mark operation pending and cancellable
2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (async) {
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = SL_OBJECT_STATE_RESUMING_1;
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Synchronous: mark operatio pending and non-cancellable
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = SL_OBJECT_STATE_RESUMING_2;
248ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville        }
249ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville        this->mState = state;
250ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville        object_unlock_exclusive(this);
251ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville        switch (state) {
252ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville        case SL_OBJECT_STATE_RESUMING_1: // asynchronous
253ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville            assert(async);
254ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville            result = ThreadPool_add(&this->mEngine->mThreadPool, HandleResume, this, 0);
255ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville            if (SL_RESULT_SUCCESS != result) {
256ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville                // Engine was destroyed during resume, or insufficient memory
257ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville                object_lock_exclusive(this);
258ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville                this->mState = SL_OBJECT_STATE_SUSPENDED;
259ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville                object_unlock_exclusive(this);
260ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville            }
261ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville            break;
262ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville        case SL_OBJECT_STATE_RESUMING_2: // synchronous
263ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville            {
264ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville            AsyncHook resume = class__->mResume;
265ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville            // Note that the mutex is unlocked during the resume hook
266203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            result = (NULL != resume) ? (*resume)(this, SL_BOOLEAN_FALSE) : SL_RESULT_SUCCESS;
267203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            object_lock_exclusive(this);
268203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            assert(SL_OBJECT_STATE_RESUMING_2 == this->mState);
269203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            this->mState = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED :
270203e588e3c42a81aa8a56f595119c181a63b12caWink Saville                SL_OBJECT_STATE_SUSPENDED;
271203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            object_unlock_exclusive(this);
272203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            }
273203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            break;
274203e588e3c42a81aa8a56f595119c181a63b12caWink Saville        default:                        // impossible
275203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            assert(SL_BOOLEAN_FALSE);
276203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            break;
277203e588e3c42a81aa8a56f595119c181a63b12caWink Saville        }
278203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    }
279203e588e3c42a81aa8a56f595119c181a63b12caWink Saville
280f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville    SL_LEAVE_INTERFACE
281f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville}
282f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville
283f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville
284f1317a4b3492218ac2e449ee990948bac0295b65Wink Savillestatic SLresult IObject_GetState(SLObjectItf self, SLuint32 *pState)
285f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville{
286f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville    SL_ENTER_INTERFACE
287f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville
288f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville    if (NULL == pState) {
289f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville        result = SL_RESULT_PARAMETER_INVALID;
290f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville    } else {
291f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville        IObject *this = (IObject *) self;
292f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville        // Note that the state is immediately obsolete, so a peek lock is safe
293f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville        object_lock_peek(this);
29403b37b67755a4033c6be32ae2e389c310e06e7d1Amit Mahajan        SLuint8 state = this->mState;
29517a893295d021cd48ad0e2e6ccf9ceda3f97c70cSukanya Rajkhowa        object_unlock_peek(this);
29617a893295d021cd48ad0e2e6ccf9ceda3f97c70cSukanya Rajkhowa        // Re-map the realizing, resuming, and suspending states
29717a893295d021cd48ad0e2e6ccf9ceda3f97c70cSukanya Rajkhowa        switch (state) {
29817a893295d021cd48ad0e2e6ccf9ceda3f97c70cSukanya Rajkhowa        case SL_OBJECT_STATE_REALIZING_1:
29903b37b67755a4033c6be32ae2e389c310e06e7d1Amit Mahajan        case SL_OBJECT_STATE_REALIZING_1A:
300f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville        case SL_OBJECT_STATE_REALIZING_2:
301f1317a4b3492218ac2e449ee990948bac0295b65Wink Saville        case SL_OBJECT_STATE_DESTROYING:    // application shouldn't call GetState after Destroy
3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = SL_OBJECT_STATE_UNREALIZED;
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_RESUMING_1:
3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_RESUMING_1A:
3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_RESUMING_2:
3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_SUSPENDING:
3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = SL_OBJECT_STATE_SUSPENDED;
3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_UNREALIZED:
3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_REALIZED:
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_SUSPENDED:
31322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            // These are the "official" object states, return them as is
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        default:
3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assert(SL_BOOLEAN_FALSE);
3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        *pState = state;
3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        result = SL_RESULT_SUCCESS;
3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_LEAVE_INTERFACE
3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillestatic SLresult IObject_GetInterface(SLObjectItf self, const SLInterfaceID iid, void *pInterface)
3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_ENTER_INTERFACE
3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    if (NULL == pInterface) {
3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        result = SL_RESULT_PARAMETER_INVALID;
3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    } else {
3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        void *interface = NULL;
33422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (NULL == iid) {
3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            result = SL_RESULT_PARAMETER_INVALID;
3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            IObject *this = (IObject *) self;
3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            const ClassTable *class__ = this->mClass;
3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int MPH, index;
3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if ((0 > (MPH = IID_to_MPH(iid))) ||
3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // no need to check for an initialization hook
3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // (NULL == MPH_init_table[MPH].mInit) ||
3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    (0 > (index = class__->mMPH_to_index[MPH]))) {
3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                result = SL_RESULT_FEATURE_UNSUPPORTED;
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                unsigned mask = 1 << index;
3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                object_lock_exclusive(this);
3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if ((SL_OBJECT_STATE_REALIZED != this->mState) &&
3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        !(INTERFACE_PREREALIZE & class__->mInterfaces[index].mInterface)) {
3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // Can't get interface on an unrealized object unless pre-realize is ok
3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    result = SL_RESULT_PRECONDITIONS_VIOLATED;
3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else if ((MPH_MUTESOLO == MPH) && (SL_OBJECTID_AUDIOPLAYER ==
35322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        class__->mSLObjectID) && (1 == ((CAudioPlayer *) this)->mNumChannels)) {
3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // Can't get the MuteSolo interface of an audio player if the channel count is
3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // mono, but _can_ get the MuteSolo interface if the channel count is unknown
3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    result = SL_RESULT_FEATURE_UNSUPPORTED;
3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    switch (this->mInterfaceStates[index]) {
3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case INTERFACE_EXPOSED:
3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case INTERFACE_ADDED:
3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        interface = (char *) this + class__->mInterfaces[index].mOffset;
3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // Note that interface has been gotten,
3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // for debugger and to detect incorrect use of interfaces
3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (!(this->mGottenMask & mask)) {
3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            this->mGottenMask |= mask;
3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            // This trickery validates the v-table
3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            ((size_t *) interface)[0] ^= ~0;
3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        result = SL_RESULT_SUCCESS;
3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // Can't get interface if uninitialized, initialized, suspended,
3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // suspending, resuming, adding, or removing
3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    default:
3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        result = SL_RESULT_FEATURE_UNSUPPORTED;
3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                object_unlock_exclusive(this);
3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
38022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        }
3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        *(void **)pInterface = interface;
3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_LEAVE_INTERFACE
3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
38622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville
3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillestatic SLresult IObject_RegisterCallback(SLObjectItf self,
3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    slObjectCallback callback, void *pContext)
3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_ENTER_INTERFACE
39222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville
3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject *this = (IObject *) self;
3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    object_lock_exclusive(this);
3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    this->mCallback = callback;
3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    this->mContext = pContext;
3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    object_unlock_exclusive(this);
3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    result = SL_RESULT_SUCCESS;
39922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville
4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_LEAVE_INTERFACE
4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/** \brief This is internal common code for Abort and Destroy.
4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *  Note: called with mutex unlocked, and returns with mutex locked.
4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillestatic void Abort_internal(IObject *this)
4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    const ClassTable *class__ = this->mClass;
4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    bool anyAsync = false;
4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    object_lock_exclusive(this);
4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Abort asynchronous operations on the object
4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    switch (this->mState) {
4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    case SL_OBJECT_STATE_REALIZING_1:   // Realize
4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        this->mState = SL_OBJECT_STATE_REALIZING_1A;
4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        anyAsync = true;
4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        break;
4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    case SL_OBJECT_STATE_RESUMING_1:    // Resume
421e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka        this->mState = SL_OBJECT_STATE_RESUMING_1A;
422e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka        anyAsync = true;
423e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka        break;
424e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka    case SL_OBJECT_STATE_REALIZING_1A:  // Realize
4255fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    case SL_OBJECT_STATE_REALIZING_2:
4265fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    case SL_OBJECT_STATE_RESUMING_1A:   // Resume
4275fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    case SL_OBJECT_STATE_RESUMING_2:
4285fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        anyAsync = true;
4295fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        break;
4305fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    case SL_OBJECT_STATE_DESTROYING:
4315fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        assert(false);
4325fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        break;
4335fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    default:
4345fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        break;
4355fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    }
4365fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville
4375fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    // Abort asynchronous operations on interfaces
4385fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    SLuint8 *interfaceStateP = this->mInterfaceStates;
4395fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    unsigned index;
4400c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville    for (index = 0; index < class__->mInterfaceCount; ++index, ++interfaceStateP) {
4415fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        switch (*interfaceStateP) {
4425fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        case INTERFACE_ADDING_1:    // AddInterface
4435fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville            *interfaceStateP = INTERFACE_ADDING_1A;
4445fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville            anyAsync = true;
4455fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville            break;
4465fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        case INTERFACE_RESUMING_1:  // ResumeInterface
4475fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville            *interfaceStateP = INTERFACE_RESUMING_1A;
4485fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville            anyAsync = true;
4495fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville            break;
4505fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        case INTERFACE_ADDING_1A:   // AddInterface
4515fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        case INTERFACE_ADDING_2:
4525fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        case INTERFACE_RESUMING_1A: // ResumeInterface
4535fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        case INTERFACE_RESUMING_2:
4545fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        case INTERFACE_REMOVING:    // not observable: RemoveInterface is synchronous & mutex locked
4555fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville            anyAsync = true;
4565fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville            break;
4570c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville        default:
4585fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville            break;
4595fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville        }
4605fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    }
4615fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville
4625fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    // Wait until all asynchronous operations either complete normally or recognize the abort
4635fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    while (anyAsync) {
4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        object_unlock_exclusive(this);
4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // FIXME should use condition variable instead of polling
4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        usleep(20000);
4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        anyAsync = false;
4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        object_lock_exclusive(this);
4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (this->mState) {
4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_REALIZING_1:   // state 1 means it cycled during the usleep window
4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_RESUMING_1:
4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_REALIZING_1A:
4730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_REALIZING_2:
474e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka        case SL_OBJECT_STATE_RESUMING_1A:
4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_RESUMING_2:
4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            anyAsync = true;
4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case SL_OBJECT_STATE_DESTROYING:
4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assert(false);
4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        default:
482b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal            break;
483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        interfaceStateP = this->mInterfaceStates;
4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (index = 0; index < class__->mInterfaceCount; ++index, ++interfaceStateP) {
4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            switch (*interfaceStateP) {
4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case INTERFACE_ADDING_1:    // state 1 means it cycled during the usleep window
4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case INTERFACE_RESUMING_1:
4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case INTERFACE_ADDING_1A:
4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case INTERFACE_ADDING_2:
4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case INTERFACE_RESUMING_1A:
4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case INTERFACE_RESUMING_2:
4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case INTERFACE_REMOVING:
4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                anyAsync = true;
4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            default:
4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // At this point there are no pending asynchronous operations
5030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
5040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5060825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillestatic void IObject_AbortAsyncOperation(SLObjectItf self)
5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_ENTER_INTERFACE_VOID
5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject *this = (IObject *) self;
5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    Abort_internal(this);
5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    object_unlock_exclusive(this);
5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_LEAVE_INTERFACE_VOID
5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillevoid IObject_Destroy(SLObjectItf self)
5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_ENTER_INTERFACE_VOID
521203e588e3c42a81aa8a56f595119c181a63b12caWink Saville
522203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    IObject *this = (IObject *) self;
523203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    // mutex is unlocked
524203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    Abort_internal(this);
525203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    // mutex is locked
526203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    const ClassTable *class__ = this->mClass;
527203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    PreDestroyHook preDestroy = class__->mPreDestroy;
528203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    // The pre-destroy hook is called with mutex locked, and should block until it is safe to
529203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    // destroy.  It is OK to unlock the mutex temporarily, as it long as it re-locks the mutex
530203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    // before returning.
531203e588e3c42a81aa8a56f595119c181a63b12caWink Saville    if (NULL != preDestroy) {
532203e588e3c42a81aa8a56f595119c181a63b12caWink Saville        predestroy_t okToDestroy = (*preDestroy)(this);
533203e588e3c42a81aa8a56f595119c181a63b12caWink Saville        switch (okToDestroy) {
534203e588e3c42a81aa8a56f595119c181a63b12caWink Saville        case predestroy_ok:
535203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            break;
536203e588e3c42a81aa8a56f595119c181a63b12caWink Saville        case predestroy_error:
537203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            SL_LOGE("Object::Destroy(%p) not allowed", this);
538203e588e3c42a81aa8a56f595119c181a63b12caWink Saville            // fall through
5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case predestroy_again:
5400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            object_unlock_exclusive(this);
5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // unfortunately Destroy doesn't return a result
5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            SL_LEAVE_INTERFACE_VOID
5430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // unreachable
5440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        default:
5450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assert(false);
5460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
5470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
54822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    }
5490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    this->mState = SL_OBJECT_STATE_DESTROYING;
5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    VoidHook destroy = class__->mDestroy;
5510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // const, no lock needed
5520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IEngine *thisEngine = &this->mEngine->mEngine;
5530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    unsigned i = this->mInstanceID;
5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    assert(MAX_INSTANCE >= i);
5550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // avoid a recursive lock on the engine when destroying the engine itself
5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    if (thisEngine->mThis != this) {
5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        interface_lock_exclusive(thisEngine);
5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // An unpublished object has a slot reserved, but the ID hasn't been chosen yet
5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    assert(0 < thisEngine->mInstanceCount);
5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    --thisEngine->mInstanceCount;
5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // If object is published, then remove it from exposure to sync thread and debugger
5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    if (0 != i) {
5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        --i;
5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        unsigned mask = 1 << i;
5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assert(thisEngine->mInstanceMask & mask);
5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        thisEngine->mInstanceMask &= ~mask;
5680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        assert(thisEngine->mInstances[i] == this);
5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        thisEngine->mInstances[i] = NULL;
5700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // avoid a recursive unlock on the engine when destroying the engine itself
5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    if (thisEngine->mThis != this) {
5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        interface_unlock_exclusive(thisEngine);
5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // The destroy hook is called with mutex locked
5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    if (NULL != destroy) {
5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        (*destroy)(this);
5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Call the deinitializer for each currently initialized interface,
5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // whether it is implicit, explicit, optional, or dynamically added.
5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // The deinitializers are called in the reverse order that the
5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // initializers were called, so that IObject_deinit is called last.
5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    unsigned index = class__->mInterfaceCount;
5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    const struct iid_vtable *x = &class__->mInterfaces[index];
5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SLuint8 *interfaceStateP = &this->mInterfaceStates[index];
5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    for ( ; index > 0; --index) {
5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        --x;
5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        size_t offset = x->mOffset;
5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        void *thisItf = (char *) this + offset;
5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SLuint32 state = *--interfaceStateP;
5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (state) {
5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case INTERFACE_UNINITIALIZED:
5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case INTERFACE_EXPOSED:     // quiescent states
5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case INTERFACE_ADDED:
5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case INTERFACE_SUSPENDED:
5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // The remove hook is called with mutex locked
5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            {
599454b1dfd508844b42eb775e4ab2359be74d3672bWink Saville            VoidHook remove = MPH_init_table[x->mMPH].mRemove;
6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (NULL != remove) {
6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                (*remove)(thisItf);
60275c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao            }
60375c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao            *interfaceStateP = INTERFACE_INITIALIZED;
60475c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao            }
60575c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao            // fall through
60675c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao        case INTERFACE_INITIALIZED:
60775c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao            {
60875c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao            VoidHook deinit = MPH_init_table[x->mMPH].mDeinit;
60975c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao            if (NULL != deinit) {
61075c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao                (*deinit)(thisItf);
61175c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao            }
61275c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao            *interfaceStateP = INTERFACE_UNINITIALIZED;
61375c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao            }
61475c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao            break;
61575c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao        case INTERFACE_ADDING_1:    // active states indicate incorrect use of API
61675c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao        case INTERFACE_ADDING_1A:
61775c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao        case INTERFACE_ADDING_2:
61875c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao        case INTERFACE_RESUMING_1:
61975c934492b242f8ba750b11d9dae4304c76bbc07Jing Zhao        case INTERFACE_RESUMING_1A:
6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case INTERFACE_RESUMING_2:
6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case INTERFACE_REMOVING:
6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case INTERFACE_SUSPENDING:
6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            SL_LOGE("Object::Destroy(%p) while interface %u active", this, index);
6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
6250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        default:
6260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            assert(SL_BOOLEAN_FALSE);
6270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
6280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // The mutex is unlocked and destroyed by IObject_deinit, which is the last deinitializer
6310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    memset(this, 0x55, class__->mSize); // catch broken applications that continue using interfaces
6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                        // was ifdef USE_DEBUG but safer to do this unconditionally
6330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    free(this);
6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    if (SL_OBJECTID_ENGINE == class__->mSLObjectID) {
6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CEngine_Destroyed((CEngine *) this);
6370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_LEAVE_INTERFACE_VOID
6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillestatic SLresult IObject_SetPriority(SLObjectItf self, SLint32 priority, SLboolean preemptable)
6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_ENTER_INTERFACE
6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville#if USE_PROFILES & USE_PROFILES_BASE
6480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject *this = (IObject *) self;
6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    object_lock_exclusive(this);
6500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    this->mPriority = priority;
6510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    this->mPreemptable = SL_BOOLEAN_FALSE != preemptable; // normalize
6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    object_unlock_exclusive(this);
6530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    result = SL_RESULT_SUCCESS;
6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville#else
6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    result = SL_RESULT_FEATURE_UNSUPPORTED;
6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville#endif
6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_LEAVE_INTERFACE
6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillestatic SLresult IObject_GetPriority(SLObjectItf self, SLint32 *pPriority, SLboolean *pPreemptable)
6635b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam{
6645b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam    SL_ENTER_INTERFACE
665e0e2ceb1ae025e6dd2adda75c32dba93c6dfeea4Wink Saville
666e0e2ceb1ae025e6dd2adda75c32dba93c6dfeea4Wink Saville#if USE_PROFILES & USE_PROFILES_BASE
6675b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam    if (NULL == pPriority || NULL == pPreemptable) {
668e0e2ceb1ae025e6dd2adda75c32dba93c6dfeea4Wink Saville        result = SL_RESULT_PARAMETER_INVALID;
6695b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam    } else {
6705b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam        IObject *this = (IObject *) self;
6715b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam        object_lock_shared(this);
6725b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam        SLint32 priority = this->mPriority;
6735b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam        SLboolean preemptable = this->mPreemptable;
6745b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam        object_unlock_shared(this);
6755b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam        *pPriority = priority;
6765b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam        *pPreemptable = preemptable;
6775b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam        result = SL_RESULT_SUCCESS;
6785b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam    }
6795b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam#else
6805b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam    result = SL_RESULT_FEATURE_UNSUPPORTED;
6815b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam#endif
6825b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam
683e0e2ceb1ae025e6dd2adda75c32dba93c6dfeea4Wink Saville    SL_LEAVE_INTERFACE
6845b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam}
6855b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam
6865b81adc82a53b3064f4baa3acfeabef31586588aUma Maheswari Ramalingam
6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillestatic SLresult IObject_SetLossOfControlInterfaces(SLObjectItf self,
6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SLint16 numInterfaces, SLInterfaceID *pInterfaceIDs, SLboolean enabled)
6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_ENTER_INTERFACE
6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville#if USE_PROFILES & USE_PROFILES_BASE
6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    result = SL_RESULT_SUCCESS;
69422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    if (0 < numInterfaces) {
6950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        SLuint32 i;
6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (NULL == pInterfaceIDs) {
6970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            result = SL_RESULT_PARAMETER_INVALID;
6980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
6990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            IObject *this = (IObject *) self;
7000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            const ClassTable *class__ = this->mClass;
7010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            unsigned lossOfControlMask = 0;
7020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // The cast is due to a typo in the spec, bug 6482
7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (i = 0; i < (SLuint32) numInterfaces; ++i) {
7040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                SLInterfaceID iid = pInterfaceIDs[i];
7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (NULL == iid) {
7060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    result = SL_RESULT_PARAMETER_INVALID;
7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    goto out;
7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int MPH, index;
7100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // We ignore without error any invalid MPH or index, but spec is unclear
7110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if ((0 <= (MPH = IID_to_MPH(iid))) &&
7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // no need to check for an initialization hook
7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // (NULL == MPH_init_table[MPH].mInit) ||
7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        (0 <= (index = class__->mMPH_to_index[MPH]))) {
7150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    lossOfControlMask |= (1 << index);
7160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            object_lock_exclusive(this);
7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (enabled) {
7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                this->mLossOfControlMask |= lossOfControlMask;
7210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
7220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                this->mLossOfControlMask &= ~lossOfControlMask;
7230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
7240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            object_unlock_exclusive(this);
7250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleout:
7280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville#else
7290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    result = SL_RESULT_FEATURE_UNSUPPORTED;
7300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville#endif
7310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    SL_LEAVE_INTERFACE
7330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
7340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
735e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
736e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkastatic const struct SLObjectItf_ IObject_Itf = {
737e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    IObject_Realize,
738e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    IObject_Resume,
7390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject_GetState,
7400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject_GetInterface,
7410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject_RegisterCallback,
7420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject_AbortAsyncOperation,
7430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject_Destroy,
7440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject_SetPriority,
7450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject_GetPriority,
7460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IObject_SetLossOfControlInterfaces,
7470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville};
7480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/** \brief This must be the first initializer called for an object */
7510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7520825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillevoid IObject_init(void *self)
7530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville{
754a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    IObject *this = (IObject *) self;
755a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    this->mItf = &IObject_Itf;
756a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    // initialized in construct:
757a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    // mClass
758ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    // mInstanceID
759ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    // mLossOfControlMask
760ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    // mEngine
761ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    // mInterfaceStates
7625fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    this->mState = SL_OBJECT_STATE_UNREALIZED;
7635fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    this->mGottenMask = 1;  // IObject
7645fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    this->mAttributesMask = 0;
7655fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    this->mCallback = NULL;
7665fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    this->mContext = NULL;
7670c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville#if USE_PROFILES & USE_PROFILES_BASE
7680c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville    this->mPriority = SL_PRIORITY_NORMAL;
7690c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville    this->mPreemptable = SL_BOOLEAN_FALSE;
7700c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville#endif
771bed429d6d0a0dbc6384b04e0641aa1e03e406f42Amit Mahajan    this->mStrongRefCount = 0;
7720c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville    int ok;
7730c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville    ok = pthread_mutex_init(&this->mMutex, (const pthread_mutexattr_t *) NULL);
774bed429d6d0a0dbc6384b04e0641aa1e03e406f42Amit Mahajan    assert(0 == ok);
7750c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville#ifdef USE_DEBUG
7760c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville    memset(&this->mOwner, 0, sizeof(pthread_t));
7770c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville    this->mFile = NULL;
7785fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    this->mLine = 0;
7790c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville#endif
7800c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville    ok = pthread_cond_init(&this->mCond, (const pthread_condattr_t *) NULL);
7810c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville    assert(0 == ok);
7825fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville}
7835fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville
7840c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville
7855fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville/** \brief This must be the last deinitializer called for an object */
7865fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville
7875fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Savillevoid IObject_deinit(void *self)
7880c5a2697697b49228bd2e23dc8d8217877a0fd7bWink Saville{
7895fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    IObject *this = (IObject *) self;
7905fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville#ifdef USE_DEBUG
791bed429d6d0a0dbc6384b04e0641aa1e03e406f42Amit Mahajan    assert(pthread_equal(pthread_self(), this->mOwner));
7925fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville#endif
793bed429d6d0a0dbc6384b04e0641aa1e03e406f42Amit Mahajan    int ok;
7945fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    ok = pthread_cond_destroy(&this->mCond);
795bed429d6d0a0dbc6384b04e0641aa1e03e406f42Amit Mahajan    assert(0 == ok);
7965fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    // equivalent to object_unlock_exclusive, but without the rigmarole
797bed429d6d0a0dbc6384b04e0641aa1e03e406f42Amit Mahajan    ok = pthread_mutex_unlock(&this->mMutex);
798bed429d6d0a0dbc6384b04e0641aa1e03e406f42Amit Mahajan    assert(0 == ok);
7995fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    ok = pthread_mutex_destroy(&this->mMutex);
8005fb811ff076aa6b4a9ceca6edaf504a4c6d9ad20Wink Saville    assert(0 == ok);
801ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    // redundant: this->mState = SL_OBJECT_STATE_UNREALIZED;
802ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville}
803ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville
804ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville
805ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville/** \brief Publish a new object after it is fully initialized.
806ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville *  Publishing will expose the object to sync thread and debugger,
807ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville *  and make it safe to return the SLObjectItf to the application.
808ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville */
809ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville
810ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Savillevoid IObject_Publish(IObject *this)
811ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville{
8120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    IEngine *thisEngine = &this->mEngine->mEngine;
8130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    interface_lock_exclusive(thisEngine);
81422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    // construct earlier reserved a pending slot, but did not choose the actual slot number
81522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    unsigned availMask = ~thisEngine->mInstanceMask;
816ef1d4bff9bbf7d967dbcace73f08910e14e367d0Wink Saville    assert(availMask);
8170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    unsigned i = ctz(availMask);
81822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    assert(MAX_INSTANCE > i);
8190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    assert(NULL == thisEngine->mInstances[i]);
82022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    thisEngine->mInstances[i] = this;
8210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    thisEngine->mInstanceMask |= 1 << i;
8220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // avoid zero as a valid instance ID
8230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    this->mInstanceID = i + 1;
824e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka    interface_unlock_exclusive(thisEngine);
825e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka}
826e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2Alex Yakavenka