1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/** \file CEngine.c Engine class */
18
19#include "sles_allinclusive.h"
20
21
22/** \brief Hook called by Object::Realize when an engine is realized */
23
24SLresult CEngine_Realize(void *self, SLboolean async)
25{
26    CEngine *this = (CEngine *) self;
27    SLresult result;
28#ifndef ANDROID
29    // create the sync thread
30    int err = pthread_create(&this->mSyncThread, (const pthread_attr_t *) NULL, sync_start, this);
31    result = err_to_result(err);
32    if (SL_RESULT_SUCCESS != result)
33        return result;
34#endif
35    // initialize the thread pool for asynchronous operations
36    result = ThreadPool_init(&this->mEngine.mThreadPool, 0, 0);
37    if (SL_RESULT_SUCCESS != result) {
38        this->mEngine.mShutdown = SL_BOOLEAN_TRUE;
39        (void) pthread_join(this->mSyncThread, (void **) NULL);
40        return result;
41    }
42#ifdef USE_SDL
43    SDL_open(&this->mEngine);
44#endif
45    return SL_RESULT_SUCCESS;
46}
47
48
49/** \brief Hook called by Object::Resume when an engine is resumed */
50
51SLresult CEngine_Resume(void *self, SLboolean async)
52{
53    return SL_RESULT_SUCCESS;
54}
55
56
57/** \brief Hook called by Object::Destroy when an engine is destroyed */
58
59void CEngine_Destroy(void *self)
60{
61    CEngine *this = (CEngine *) self;
62
63    // Verify that there are no extant objects
64    unsigned instanceCount = this->mEngine.mInstanceCount;
65    unsigned instanceMask = this->mEngine.mInstanceMask;
66    if ((0 < instanceCount) || (0 != instanceMask)) {
67        SL_LOGE("Object::Destroy(%p) for engine ignored; %u total active objects",
68            this, instanceCount);
69        while (0 != instanceMask) {
70            unsigned i = ctz(instanceMask);
71            assert(MAX_INSTANCE > i);
72            SL_LOGE("Object::Destroy(%p) for engine ignored; active object ID %u at %p",
73                this, i + 1, this->mEngine.mInstances[i]);
74            instanceMask &= ~(1 << i);
75        }
76    }
77
78    // If engine was created but not realized, there will be no sync thread yet
79    pthread_t zero;
80    memset(&zero, 0, sizeof(pthread_t));
81    if (0 != memcmp(&zero, &this->mSyncThread, sizeof(pthread_t))) {
82
83        // Announce to the sync thread that engine is shutting down; it polls so should see it soon
84        this->mEngine.mShutdown = SL_BOOLEAN_TRUE;
85        // Wait for the sync thread to acknowledge the shutdown
86        while (!this->mEngine.mShutdownAck) {
87            object_cond_wait(&this->mObject);
88        }
89        // The sync thread should have exited by now, so collect it by joining
90        (void) pthread_join(this->mSyncThread, (void **) NULL);
91
92    }
93
94    // Shutdown the thread pool used for asynchronous operations (there should not be any)
95    ThreadPool_deinit(&this->mEngine.mThreadPool);
96
97#ifdef USE_SDL
98    SDL_close();
99#endif
100
101}
102
103
104/** \brief Hook called by Object::Destroy before an engine is about to be destroyed */
105
106bool CEngine_PreDestroy(void *self)
107{
108    return true;
109}
110