1437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten/* 2437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * Copyright (C) 2010 The Android Open Source Project 3437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * 4437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * you may not use this file except in compliance with the License. 6437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * You may obtain a copy of the License at 7437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * 8437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * 10437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * Unless required by applicable law or agreed to in writing, software 11437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * See the License for the specific language governing permissions and 14437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten * limitations under the License. 15437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten */ 16437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten 1710ee2bc6119445f4339ecef998c40c9cc95057cdGlenn Kasten/** \file CEngine.c Engine class */ 18437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten 19437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten#include "sles_allinclusive.h" 20437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten 21437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten 2210ee2bc6119445f4339ecef998c40c9cc95057cdGlenn Kasten/** \brief Hook called by Object::Realize when an engine is realized */ 23158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten 24437f9ab9914ea61112aa496a047162a0d22194cdGlenn KastenSLresult CEngine_Realize(void *self, SLboolean async) 25437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten{ 26437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten CEngine *this = (CEngine *) self; 27227b8b5fe36d5385bbb23d63198bc8e72bfda5d3Glenn Kasten SLresult result; 28227b8b5fe36d5385bbb23d63198bc8e72bfda5d3Glenn Kasten#ifndef ANDROID 2951cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten // create the sync thread 30bcf6e4f2a46544f599f6c77354650c6aad91ea5dGlenn Kasten int err = pthread_create(&this->mSyncThread, (const pthread_attr_t *) NULL, sync_start, this); 31227b8b5fe36d5385bbb23d63198bc8e72bfda5d3Glenn Kasten result = err_to_result(err); 32437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten if (SL_RESULT_SUCCESS != result) 33437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten return result; 34227b8b5fe36d5385bbb23d63198bc8e72bfda5d3Glenn Kasten#endif 3551cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten // initialize the thread pool for asynchronous operations 36437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten result = ThreadPool_init(&this->mEngine.mThreadPool, 0, 0); 37437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten if (SL_RESULT_SUCCESS != result) { 38437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten this->mEngine.mShutdown = SL_BOOLEAN_TRUE; 39437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten (void) pthread_join(this->mSyncThread, (void **) NULL); 40437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten return result; 41437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten } 42437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten#ifdef USE_SDL 43bc1596c33e134859d3ae3182d641b2dd03405b5dGlenn Kasten SDL_open(&this->mEngine); 44437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten#endif 45437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten return SL_RESULT_SUCCESS; 46437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten} 47437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten 48158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten 494f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten/** \brief Hook called by Object::Resume when an engine is resumed */ 504f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 514f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn KastenSLresult CEngine_Resume(void *self, SLboolean async) 524f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten{ 534f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten return SL_RESULT_SUCCESS; 544f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten} 554f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 564f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 5710ee2bc6119445f4339ecef998c40c9cc95057cdGlenn Kasten/** \brief Hook called by Object::Destroy when an engine is destroyed */ 58158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten 59437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kastenvoid CEngine_Destroy(void *self) 60437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten{ 61437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten CEngine *this = (CEngine *) self; 62b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten 63b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten // Verify that there are no extant objects 64b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten unsigned instanceCount = this->mEngine.mInstanceCount; 65b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten unsigned instanceMask = this->mEngine.mInstanceMask; 66b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten if ((0 < instanceCount) || (0 != instanceMask)) { 6751cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten SL_LOGE("Object::Destroy(%p) for engine ignored; %u total active objects", 6851cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten this, instanceCount); 69b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten while (0 != instanceMask) { 70b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten unsigned i = ctz(instanceMask); 71b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten assert(MAX_INSTANCE > i); 7251cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten SL_LOGE("Object::Destroy(%p) for engine ignored; active object ID %u at %p", 7351cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten this, i + 1, this->mEngine.mInstances[i]); 74b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten instanceMask &= ~(1 << i); 75b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten } 76b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten } 77b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten 78cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten // If engine was created but not realized, there will be no sync thread yet 79cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten pthread_t zero; 80cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten memset(&zero, 0, sizeof(pthread_t)); 81cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten if (0 != memcmp(&zero, &this->mSyncThread, sizeof(pthread_t))) { 82cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten 83cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten // Announce to the sync thread that engine is shutting down; it polls so should see it soon 84cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten this->mEngine.mShutdown = SL_BOOLEAN_TRUE; 85cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten // Wait for the sync thread to acknowledge the shutdown 86cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten while (!this->mEngine.mShutdownAck) { 87cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten object_cond_wait(&this->mObject); 88cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten } 89cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten // The sync thread should have exited by now, so collect it by joining 90cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten (void) pthread_join(this->mSyncThread, (void **) NULL); 91cc484cd4b7ede364e95209eb0468df3bc51f50e5Glenn Kasten 92b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten } 93b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten 94b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten // Shutdown the thread pool used for asynchronous operations (there should not be any) 95b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten ThreadPool_deinit(&this->mEngine.mThreadPool); 96b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten 97b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten#ifdef USE_SDL 98b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten SDL_close(); 99b0a0555e2fcad41d3ee0c45f0f75ed556dbee282Glenn Kasten#endif 1001f5702ed2239c79b701aa8cc3c675798b34a9656Jean-Michel Trivi 101437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten} 1024f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 1034f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 1044f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten/** \brief Hook called by Object::Destroy before an engine is about to be destroyed */ 1054f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten 1064f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kastenbool CEngine_PreDestroy(void *self) 1074f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten{ 1084f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten return true; 1094f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten} 110