/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file CEngine.c Engine class */
#include "sles_allinclusive.h"
/** \brief Hook called by Object::Realize when an engine is realized */
SLresult CEngine_Realize(void *self, SLboolean async)
{
CEngine *this = (CEngine *) self;
SLresult result;
#ifndef ANDROID
// create the sync thread
int err = pthread_create(&this->mSyncThread, (const pthread_attr_t *) NULL, sync_start, this);
result = err_to_result(err);
if (SL_RESULT_SUCCESS != result)
return result;
#endif
// initialize the thread pool for asynchronous operations
result = ThreadPool_init(&this->mEngine.mThreadPool, 0, 0);
if (SL_RESULT_SUCCESS != result) {
this->mEngine.mShutdown = SL_BOOLEAN_TRUE;
(void) pthread_join(this->mSyncThread, (void **) NULL);
return result;
}
#ifdef USE_SDL
SDL_open(&this->mEngine);
#endif
return SL_RESULT_SUCCESS;
}
/** \brief Hook called by Object::Resume when an engine is resumed */
SLresult CEngine_Resume(void *self, SLboolean async)
{
return SL_RESULT_SUCCESS;
}
/** \brief Hook called by Object::Destroy when an engine is destroyed */
void CEngine_Destroy(void *self)
{
CEngine *this = (CEngine *) self;
// Verify that there are no extant objects
unsigned instanceCount = this->mEngine.mInstanceCount;
unsigned instanceMask = this->mEngine.mInstanceMask;
if ((0 < instanceCount) || (0 != instanceMask)) {
SL_LOGE("Object::Destroy(%p) for engine ignored; %u total active objects",
this, instanceCount);
while (0 != instanceMask) {
unsigned i = ctz(instanceMask);
assert(MAX_INSTANCE > i);
SL_LOGE("Object::Destroy(%p) for engine ignored; active object ID %u at %p",
this, i + 1, this->mEngine.mInstances[i]);
instanceMask &= ~(1 << i);
}
}
// If engine was created but not realized, there will be no sync thread yet
pthread_t zero;
memset(&zero, 0, sizeof(pthread_t));
if (0 != memcmp(&zero, &this->mSyncThread, sizeof(pthread_t))) {
// Announce to the sync thread that engine is shutting down; it polls so should see it soon
this->mEngine.mShutdown = SL_BOOLEAN_TRUE;
// Wait for the sync thread to acknowledge the shutdown
while (!this->mEngine.mShutdownAck) {
object_cond_wait(&this->mObject);
}
// The sync thread should have exited by now, so collect it by joining
(void) pthread_join(this->mSyncThread, (void **) NULL);
}
// Shutdown the thread pool used for asynchronous operations (there should not be any)
ThreadPool_deinit(&this->mEngine.mThreadPool);
#ifdef USE_SDL
SDL_close();
#endif
}
/** \brief Hook called by Object::Destroy before an engine is about to be destroyed */
bool CEngine_PreDestroy(void *self)
{
return true;
}