IObject.c revision ed46c29d6a09112dbbf584c82953f63289596fd6
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
25510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleRealize(void *self, int unused)
2661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
27510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
28510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
29510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    IObject *this = (IObject *) self;
30510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != this);
3161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const ClassTable *class__ = this->mClass;
32510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != class__);
333d146e0a31f5ee2a7d9807c4e99994084fdd3283Jean-Michel Trivi    AsyncHook realize = class__->mRealize;
343a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    SLresult result;
35276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    SLuint8 state;
36510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
37510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // check object state
3861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
39510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    state = this->mState;
40510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (state) {
41510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
42510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case SL_OBJECT_STATE_REALIZING_1:   // normal case
43510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        if (NULL != realize) {
44510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            this->mState = SL_OBJECT_STATE_REALIZING_2;
45510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_unlock_exclusive(this);
46510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // Note that the mutex is unlocked during the realize hook
47510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            result = (*realize)(this, SL_BOOLEAN_TRUE);
48510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_lock_exclusive(this);
49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            assert(SL_OBJECT_STATE_REALIZING_2 == this->mState);
50510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED :
51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                SL_OBJECT_STATE_UNREALIZED;
52510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        } else {
53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            result = SL_RESULT_SUCCESS;
54510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            state = SL_OBJECT_STATE_REALIZED;
55510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        }
56510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
57510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
58510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case SL_OBJECT_STATE_REALIZING_1A:  // operation was aborted while on work queue
59510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_OPERATION_ABORTED;
60510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = SL_OBJECT_STATE_UNREALIZED;
61510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
62510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:                            // impossible
64510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(SL_BOOLEAN_FALSE);
65510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_INTERNAL_ERROR;
66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
67510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
6861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
70510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // mutex is locked, update state
71d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    this->mState = state;
72510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
73d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    // Make a copy of these, so we can call the callback with mutex unlocked
74d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    slObjectCallback callback = this->mCallback;
75d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    void *context = this->mContext;
7661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
77510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
78d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    // Note that the mutex is unlocked during the callback
793a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    if (NULL != callback)
80d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL);
81d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten}
82d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten
83ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
84d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IObject_Realize(SLObjectItf self, SLboolean async)
85d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{
86ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
87ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
88d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    IObject *this = (IObject *) self;
89276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    SLuint8 state;
90d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    const ClassTable *class__ = this->mClass;
91d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    object_lock_exclusive(this);
92d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    state = this->mState;
93d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    // Reject redundant calls to Realize
94d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    if (SL_OBJECT_STATE_UNREALIZED != state) {
95510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_unlock_exclusive(this);
96ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
97d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    } else {
98ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // Asynchronous: mark operation pending and cancellable
99ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (async && (SL_OBJECTID_ENGINE != class__->mObjectID)) {
100ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            state = SL_OBJECT_STATE_REALIZING_1;
101ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // Synchronous: mark operation pending and non-cancellable
102ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
103ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            state = SL_OBJECT_STATE_REALIZING_2;
104d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        }
105d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        this->mState = state;
106d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        object_unlock_exclusive(this);
107ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        switch (state) {
108ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_REALIZING_1: // asynchronous on non-Engine
109ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(async);
110ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = ThreadPool_add(&this->mEngine->mThreadPool, HandleRealize, this, 0);
111ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            if (SL_RESULT_SUCCESS != result) {
112ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // Engine was destroyed during realize, or insufficient memory
113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_lock_exclusive(this);
114ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                this->mState = SL_OBJECT_STATE_UNREALIZED;
115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_unlock_exclusive(this);
116ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            }
117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_REALIZING_2: // synchronous, or asynchronous on Engine
119ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            {
120ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            AsyncHook realize = class__->mRealize;
121ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // Note that the mutex is unlocked during the realize hook
122ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = (NULL != realize) ? (*realize)(this, async) : SL_RESULT_SUCCESS;
123ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_lock_exclusive(this);
124ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(SL_OBJECT_STATE_REALIZING_2 == this->mState);
125ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            state = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED :
126ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                SL_OBJECT_STATE_UNREALIZED;
127ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            this->mState = state;
128ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            slObjectCallback callback = this->mCallback;
129ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            void *context = this->mContext;
130ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_unlock_exclusive(this);
131ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // asynchronous Realize on an Engine is actually done synchronously, but still has
132ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // callback because there is no thread pool yet to do it asynchronously.
133ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            if (async && (NULL != callback))
134ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state,
135ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    NULL);
136ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            }
137ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
138ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        default:                          // impossible
139ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(SL_BOOLEAN_FALSE);
140ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
141d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        }
142d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    }
143ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
144ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
14561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
14661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
147ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
148510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous Object.Resume.
149510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the Object.
150510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
151510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleResume(void *self, int unused)
15261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
153510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
154510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // valid input parameters
15561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
156510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != this);
15761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const ClassTable *class__ = this->mClass;
158510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != class__);
159510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    AsyncHook resume = class__->mResume;
1603a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    SLresult result;
161276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    SLuint8 state;
162510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
163510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // check object state
16461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
165510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    state = this->mState;
166510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (state) {
167510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
168510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case SL_OBJECT_STATE_RESUMING_1:    // normal case
169510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        if (NULL != resume) {
170510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            this->mState = SL_OBJECT_STATE_RESUMING_2;
171510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_unlock_exclusive(this);
172510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // Note that the mutex is unlocked during the resume hook
173510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            result = (*resume)(this, SL_BOOLEAN_TRUE);
174510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_lock_exclusive(this);
175510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            assert(SL_OBJECT_STATE_RESUMING_2 == this->mState);
176510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED :
177510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                SL_OBJECT_STATE_SUSPENDED;
178510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        } else {
179510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            result = SL_RESULT_SUCCESS;
180510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            state = SL_OBJECT_STATE_REALIZED;
1813a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        }
182510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
183510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
184510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case SL_OBJECT_STATE_RESUMING_1A:   // operation was aborted while on work queue
185510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_OPERATION_ABORTED;
186510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = SL_OBJECT_STATE_SUSPENDED;
187510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
188510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
189510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:                            // impossible
190510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(SL_BOOLEAN_FALSE);
191510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_INTERNAL_ERROR;
192510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
193510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
19461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
195510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
196510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // mutex is unlocked, update state
197510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    this->mState = state;
198510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
199510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Make a copy of these, so we can call the callback with mutex unlocked
200510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    slObjectCallback callback = this->mCallback;
201510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    void *context = this->mContext;
20261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
203510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
204510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Note that the mutex is unlocked during the callback
2053a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    if (NULL != callback)
206510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL);
207510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten}
208510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
209ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
210510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic SLresult IObject_Resume(SLObjectItf self, SLboolean async)
211510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{
212ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
213ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
214510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    IObject *this = (IObject *) self;
215510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    const ClassTable *class__ = this->mClass;
216276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    SLuint8 state;
217510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_exclusive(this);
218510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    state = this->mState;
219510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Reject redundant calls to Resume
220510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (SL_OBJECT_STATE_SUSPENDED != state) {
221510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_unlock_exclusive(this);
222ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
223510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    } else {
224ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // Asynchronous: mark operation pending and cancellable
225ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (async) {
226ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            state = SL_OBJECT_STATE_RESUMING_1;
227ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // Synchronous: mark operatio pending and non-cancellable
228ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
229ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            state = SL_OBJECT_STATE_RESUMING_2;
230510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        }
231ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        this->mState = state;
232510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_unlock_exclusive(this);
233ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        switch (state) {
234ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_RESUMING_1: // asynchronous
235ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(async);
236ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = ThreadPool_add(&this->mEngine->mThreadPool, HandleResume, this, 0);
237ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            if (SL_RESULT_SUCCESS != result) {
238ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // Engine was destroyed during resume, or insufficient memory
239ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_lock_exclusive(this);
240ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                this->mState = SL_OBJECT_STATE_SUSPENDED;
241ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_unlock_exclusive(this);
242ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            }
243ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
244ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_RESUMING_2: // synchronous
245ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            {
246ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            AsyncHook resume = class__->mResume;
247ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // Note that the mutex is unlocked during the resume hook
248ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = (NULL != resume) ? (*resume)(this, SL_BOOLEAN_FALSE) : SL_RESULT_SUCCESS;
249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_lock_exclusive(this);
250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(SL_OBJECT_STATE_RESUMING_2 == this->mState);
251ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            this->mState = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED :
252ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                SL_OBJECT_STATE_SUSPENDED;
253ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_unlock_exclusive(this);
254ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            }
255ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
256ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        default:                        // impossible
257ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(SL_BOOLEAN_FALSE);
258ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
259510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        }
260510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
261ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
262ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
26361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
26461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
265ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
26661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_GetState(SLObjectItf self, SLuint32 *pState)
26761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
268ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
269ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
270ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pState) {
271ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
272ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
273ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IObject *this = (IObject *) self;
274ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // Note that the state is immediately obsolete, so a peek lock is safe
275ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        object_lock_peek(this);
276ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        SLuint8 state = this->mState;
277ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        object_unlock_peek(this);
278ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // Re-map the realizing, resuming, and suspending states
279ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        switch (state) {
280ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_REALIZING_1:
281ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_REALIZING_1A:
282ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_REALIZING_2:
283ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            state = SL_OBJECT_STATE_UNREALIZED;
284ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
285ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_RESUMING_1:
286ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_RESUMING_1A:
287ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_RESUMING_2:
288ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_SUSPENDING:
289ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            state = SL_OBJECT_STATE_SUSPENDED;
290ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
291ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_UNREALIZED:
292ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_REALIZED:
293ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        case SL_OBJECT_STATE_SUSPENDED:
294ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // These are the "official" object states, return them as is
295ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
296ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        default:
297ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(SL_BOOLEAN_FALSE);
298ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
299ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
300ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        *pState = state;
301ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
302d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    }
303ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
304ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
30561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
30661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
307ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
3083a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetInterface(SLObjectItf self, const SLInterfaceID iid, void *pInterface)
30961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
310ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
311ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
312ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pInterface) {
31361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
314ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
315ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        void *interface = NULL;
316ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == iid) {
317ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
318510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        } else {
319ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            IObject *this = (IObject *) self;
320ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            const ClassTable *class__ = this->mClass;
321ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            int MPH, index;
322ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) {
323ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                result = SL_RESULT_FEATURE_UNSUPPORTED;
324510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            } else {
325ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                unsigned mask = 1 << index;
326ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_lock_exclusive(this);
327ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // Can't get interface on a suspended/suspending/resuming object
328ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                if (SL_OBJECT_STATE_REALIZED != this->mState) {
329ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    result = SL_RESULT_PRECONDITIONS_VIOLATED;
330ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                } else {
331ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    switch (this->mInterfaceStates[index]) {
332ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    case INTERFACE_EXPOSED:
333ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    case INTERFACE_ADDED:
334ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        // Note that interface has been gotten,
335ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        // for debugger and to detect incorrect use of interfaces
336ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        this->mGottenMask |= mask;
337ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        interface = (char *) this + class__->mInterfaces[index].mOffset;
338ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        result = SL_RESULT_SUCCESS;
339ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        break;
340ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // Can't get interface if uninitialized/suspend(ed,ing)/resuming/adding/removing
341ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    default:
342ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        result = SL_RESULT_FEATURE_UNSUPPORTED;
343ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        break;
344ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    }
345510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                }
346ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_unlock_exclusive(this);
34761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            }
34861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
349ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        *(void **)pInterface = interface;
35061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
351ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
352ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
35361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
35461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
355ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
35661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_RegisterCallback(SLObjectItf self,
35761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    slObjectCallback callback, void *pContext)
35861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
359ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
360ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
36161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
36261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
36361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = callback;
36461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = pContext;
36561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
366ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    result = SL_RESULT_SUCCESS;
367ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
368ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
36961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
37061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
371ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
372510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// internal common code for Abort and Destroy
373510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
374510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void Abort_internal(IObject *this, SLboolean shutdown)
375510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{
376510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // FIXME Aborting asynchronous operations during phase 2 is not yet implemented
377510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    const ClassTable *class__ = this->mClass;
378510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_exclusive(this);
379510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Abort asynchronous operations on the object
380510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (this->mState) {
381510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case SL_OBJECT_STATE_REALIZING_1:   // Realize
382510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        this->mState = SL_OBJECT_STATE_REALIZING_1A;
383510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
384510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case SL_OBJECT_STATE_RESUMING_1:    // Resume
385510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        this->mState = SL_OBJECT_STATE_RESUMING_1A;
386510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
387510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:
388510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
389510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
390510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Abort asynchronous operations on interfaces
391510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // FIXME O(n), could be O(1) using a generation count
392510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint8 *interfaceStateP = this->mInterfaceStates;
393510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    unsigned index;
394510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    for (index = 0; index < class__->mInterfaceCount; ++index, ++interfaceStateP) {
395510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        switch (*interfaceStateP) {
396510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_ADDING_1:    // AddInterface
397510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP = INTERFACE_ADDING_1A;
398510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            break;
399510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_RESUMING_1:  // ResumeInterface
400510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP = INTERFACE_RESUMING_1A;
401510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            break;
402510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        default:
403510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            break;
404510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        }
405510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
406510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten#if 0
407510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // FIXME Not fully implemented, the intention is to advise other threads to exit from sync ops
408510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // FIXME Also need to wait for async ops to recognize the shutdown
409510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (shutdown)
410510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        this->mShutdown = SL_BOOLEAN_TRUE;
411510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten#endif
412510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_exclusive(this);
413510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten}
414510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
415ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
41661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_AbortAsyncOperation(SLObjectItf self)
41761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
418ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE_VOID
419ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
420510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    IObject *this = (IObject *) self;
421510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    Abort_internal(this, SL_BOOLEAN_FALSE);
422ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
423ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE_VOID
42461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
42561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
426ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
42761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_Destroy(SLObjectItf self)
42861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
429ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE_VOID
430ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
431ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // FIXME Check for dependencies, e.g. destroying an output mix with attached players,
432ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    //       destroying an engine with extant objects, etc.
4333a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    // FIXME The abort should be atomic w.r.t. destroy, so another async can't be started in window
434ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // FIXME Destroy may need to be made asynchronous to permit safe cleanup of resources
43561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
436510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    Abort_internal(this, SL_BOOLEAN_TRUE);
43761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const ClassTable *class__ = this->mClass;
43861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    VoidHook destroy = class__->mDestroy;
43961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const struct iid_vtable *x = class__->mInterfaces;
440ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // const, no lock needed
441ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    IEngine *thisEngine = this->mEngine;
442ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    unsigned i = this->mInstanceID;
443d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    assert(0 < i && i <= MAX_INSTANCE);
444ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    --i;
445510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // remove object from exposure to sync thread and debugger
446ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    interface_lock_exclusive(thisEngine);
447ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    assert(0 < thisEngine->mInstanceCount);
448ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    --thisEngine->mInstanceCount;
449ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    assert(0 != thisEngine->mInstanceMask);
450ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    thisEngine->mInstanceMask &= ~(1 << i);
451ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    assert(thisEngine->mInstances[i] == this);
452ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    thisEngine->mInstances[i] = NULL;
45300d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#ifdef USE_SDL
454e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if ((SL_OBJECTID_OUTPUTMIX == class__->mObjectID) &&
455e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        (((COutputMix *) this == thisEngine->mOutputMix))) {
45600d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        SDL_PauseAudio(1);
45700d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        thisEngine->mOutputMix = NULL;
45800d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        // Note we don't attempt to connect another output mix to SDL
45900d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten    }
46000d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#endif
461ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    interface_unlock_exclusive(thisEngine);
46261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
463d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    if (NULL != destroy)
464d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        (*destroy)(this);
46561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // Call the deinitializer for each currently exposed interface,
46661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // whether it is implicit, explicit, optional, or dynamically added.
467510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    unsigned incorrect = 0;
468510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint8 *interfaceStateP = this->mInterfaceStates;
469510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    unsigned index;
470510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    for (index = 0; index < class__->mInterfaceCount; ++index, ++x, ++interfaceStateP) {
471510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint32 state = *interfaceStateP;
472510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        switch (state) {
473510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_UNINITIALIZED:
474510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            break;
475510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_EXPOSED:     // quiescent states
476510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_ADDED:
477510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_SUSPENDED:
478510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            {
47961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            VoidHook deinit = MPH_init_table[x->mMPH].mDeinit;
48061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (NULL != deinit)
48161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                (*deinit)((char *) this + x->mOffset);
482510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            }
483510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            break;
484510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_ADDING_1:    // active states indicate incorrect use of API
485510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_ADDING_1A:
486510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_ADDING_2:
487510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_RESUMING_1:
488510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_RESUMING_1A:
489510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_RESUMING_2:
490510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_REMOVING:
491510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        case INTERFACE_SUSPENDING:
492510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            ++incorrect;
493510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            break;
494510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        default:
495510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            assert(SL_BOOLEAN_FALSE);
496510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            break;
49761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
49861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
49961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // redundant: this->mState = SL_OBJECT_STATE_UNREALIZED;
50061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
50161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#ifndef NDEBUG
50261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    memset(this, 0x55, class__->mSize);
50361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#endif
50461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    free(this);
505510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // one or more interfaces was actively changing at time of Destroy
506510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(incorrect == 0);
507510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // FIXME assert might be the wrong thing to do; instead block until active ops complete?
508ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
509ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE_VOID
51061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
51161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
512ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
5133a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_SetPriority(SLObjectItf self, SLint32 priority, SLboolean preemptable)
51461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
515ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
516ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
51761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
51861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
51961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mPriority = priority;
520d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    this->mPreemptable = SL_BOOLEAN_FALSE != preemptable; // normalize
52161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
522ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    result = SL_RESULT_SUCCESS;
523ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
524ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
52561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
52661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
527ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
5283a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetPriority(SLObjectItf self, SLint32 *pPriority, SLboolean *pPreemptable)
52961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
530ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
531ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
532ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pPriority || NULL == pPreemptable) {
533ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
534ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
535ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IObject *this = (IObject *) self;
536ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        object_lock_shared(this);
537ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        SLint32 priority = this->mPriority;
538ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        SLboolean preemptable = this->mPreemptable;
539ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        object_unlock_shared(this);
540ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        *pPriority = priority;
541ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        *pPreemptable = preemptable;
542ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
543ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
544ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
545ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
54661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
54761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
548ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
54961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_SetLossOfControlInterfaces(SLObjectItf self,
55061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLint16 numInterfaces, SLInterfaceID *pInterfaceIDs, SLboolean enabled)
55161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
552ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
553ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
554ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    result = SL_RESULT_SUCCESS;
55561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (0 < numInterfaces) {
55661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        SLuint32 i;
557ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == pInterfaceIDs) {
558ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
559ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
560ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            IObject *this = (IObject *) self;
561ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            const ClassTable *class__ = this->mClass;
562ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            unsigned lossOfControlMask = 0;
563ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // FIXME The cast is due to a typo in the spec
564ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            for (i = 0; i < (SLuint32) numInterfaces; ++i) {
565ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                SLInterfaceID iid = pInterfaceIDs[i];
566ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                if (NULL == iid) {
567ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
568ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    goto out;
569ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                }
570ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                int MPH, index;
571ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // FIXME no error if invalid MPH or index?
572ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                if ((0 <= (MPH = IID_to_MPH(iid))) && (0 <= (index = class__->mMPH_to_index[MPH])))
573ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    lossOfControlMask |= (1 << index);
574ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            }
575ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_lock_exclusive(this);
576ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            if (enabled)
577ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                this->mLossOfControlMask |= lossOfControlMask;
578ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            else
579ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                this->mLossOfControlMask &= ~lossOfControlMask;
580ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_unlock_exclusive(this);
58161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
58261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
583ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kastenout:
584ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
585ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
58661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
58761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
588ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
58961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLObjectItf_ IObject_Itf = {
59061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_Realize,
59161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_Resume,
59261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_GetState,
59361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_GetInterface,
59461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_RegisterCallback,
59561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_AbortAsyncOperation,
59661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_Destroy,
59761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_SetPriority,
59861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_GetPriority,
59961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_SetLossOfControlInterfaces,
60061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten};
60161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
60261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IObject_init(void *self)
60361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
60461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
60561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mItf = &IObject_Itf;
6060b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // initialized in construct:
6070b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // mClass
608ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // mInstanceID
6090b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // mLossOfControlMask
610ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // mEngine
611510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // mInstanceStates
61261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mState = SL_OBJECT_STATE_UNREALIZED;
613510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    this->mGottenMask = 1;  // IObject
614e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    this->mAttributesMask = 0;
61561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = NULL;
61661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = NULL;
617d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    this->mPriority = SL_PRIORITY_NORMAL;
61861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mPreemptable = SL_BOOLEAN_FALSE;
61961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    int ok;
62061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ok = pthread_mutex_init(&this->mMutex, (const pthread_mutexattr_t *) NULL);
62161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    assert(0 == ok);
62261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ok = pthread_cond_init(&this->mCond, (const pthread_condattr_t *) NULL);
62361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    assert(0 == ok);
62461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
625