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