multithread.c revision c6853892c94800e72c0bd676d5d2136d48cea76e
17126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten/*
27126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
37126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten *
47126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
57126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * you may not use this file except in compliance with the License.
67126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * You may obtain a copy of the License at
77126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten *
87126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
97126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten *
107126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * Unless required by applicable law or agreed to in writing, software
117126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
127126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * See the License for the specific language governing permissions and
147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten * limitations under the License.
157126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten */
167126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Multiple threads create and destroy objects
187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
19c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES.h>
207126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <assert.h>
217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <pthread.h>
227126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten//#include <string.h>
237126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <stdio.h>
247126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <stdlib.h>
257126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <unistd.h>
267126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
277126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastentypedef struct {
287126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLuint32 mObjectID;
297126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLchar *mURI;
307126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLEngineItf mEngineEngine;
317126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLObjectItf mMixObject;
327126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLuint32 mCounter;
337126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten} ThreadArgument;
347126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
357126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenvolatile int timeToExit = 0;
367126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#define MAX_THREAD 10
377126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenpthread_t threads[MAX_THREAD];
387126c25d7c037e5086216cf540ecf40779c3585aGlenn KastenThreadArgument thread_args[MAX_THREAD];
397126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
407126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenpthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
417126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
427126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenvoid *thread_start(void *param)
437126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten{
447126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    //pthread_mutex_lock(&mutex);
457126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    //pthread_mutex_unlock(&mutex);
467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    ThreadArgument *ta = (ThreadArgument *) param;
477126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    while (!timeToExit) {
497126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        SLresult result;
507126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
517126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        ++ta->mCounter;
527126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        switch (ta->mObjectID) {
537126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        case SL_OBJECTID_OUTPUTMIX:
547126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            {
557126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLObjectItf myMixObject;
567126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            result = (*ta->mEngineEngine)->CreateOutputMix(ta->mEngineEngine, &myMixObject, 0, NULL,
577126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten                    NULL);
587126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
597126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            result = (*myMixObject)->Realize(myMixObject, SL_BOOLEAN_FALSE);
607126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
617126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            (*myMixObject)->Destroy(myMixObject);
627126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            }
637126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            break;
647126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
657126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        case SL_OBJECTID_AUDIOPLAYER:
667126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            {
677126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLDataLocator_URI locURI = {SL_DATALOCATOR_URI, ta->mURI};
687126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLDataFormat_MIME dfMIME = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
697126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLDataSource audioSrc = {&locURI, &dfMIME};
707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLDataLocator_OutputMix locOutputMix = {SL_DATALOCATOR_OUTPUTMIX, ta->mMixObject};
717126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLDataSink audioSnk = {&locOutputMix, NULL};
727126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLObjectItf myPlayerObject;
737126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            result = (*ta->mEngineEngine)->CreateAudioPlayer(ta->mEngineEngine, &myPlayerObject,
747126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten                    &audioSrc, &audioSnk, 0, NULL, NULL);
757126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
767126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            result = (*myPlayerObject)->Realize(myPlayerObject, SL_BOOLEAN_FALSE);
777126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
787126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            SLPlayItf playerPlay;
797126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            result = (*myPlayerObject)->GetInterface(myPlayerObject, SL_IID_PLAY, &playerPlay);
807126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
810a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED);
827126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
830a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            usleep(1000 + (rand() & 0xFFF));
840a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            //usleep(1000);
850a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            //sleep(1);
867126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            (*myPlayerObject)->Destroy(myPlayerObject);
877126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            }
887126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            break;
897126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
907126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        default:
917126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            break;
927126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
937126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        }
947126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        //usleep(100000);
950a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        //break;
967126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    }
977126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
987126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    return NULL;
997126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten}
1007126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1017126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1020a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten//const char * const uris[4] = {"wav/frog.wav", "wav/bach.wav", "wav/8days.wav", "wav/help16.wav"};
1030a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenconst char * const uris[4] = {"wav/frog.wav", "wav/frog.wav", "wav/frog.wav", "wav/frog.wav"};
1047126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1057126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Main program
1067126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1077126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenint main(int argc, char **argv)
1087126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten{
1097126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLresult result;
1107126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1117126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // create engine
1127126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLObjectItf engineObject;
1137126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
1147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1157126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
1167126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLEngineItf engineEngine;
1187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
1197126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1207126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // create output mix
1227126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    SLObjectItf mixObject;
1237126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    result = (*engineEngine)->CreateOutputMix(engineEngine, &mixObject, 0, NULL, NULL);
1247126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1257126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    result = (*mixObject)->Realize(mixObject, SL_BOOLEAN_FALSE);
1267126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1277126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1287126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // create threads
1297126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    int i;
1307126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    int ok;
1317126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    for (i = 0; i < MAX_THREAD; ++i) {
1327126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        ThreadArgument *ta = &thread_args[i];
1337126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        int r = rand();
1347126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        switch (r & 1) {
1357126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#if 0
1367126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        case 0:
1377126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mObjectID = SL_OBJECTID_OUTPUTMIX;
1387126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mURI = NULL;
1397126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mEngineEngine = engineEngine;
1407126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mMixObject = NULL;
1417126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mCounter = 0;
1427126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            break;
1437126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        case 1:
1447126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#endif
1457126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        default:
1467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mObjectID = SL_OBJECTID_AUDIOPLAYER;
1477126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mURI = (SLchar *) uris[(r >> 1) & 3];
1487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mEngineEngine = engineEngine;
1497126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mMixObject = mixObject;
1507126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ta->mCounter = 0;
1517126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            break;
1527126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        }
1537126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        //pthread_mutex_lock(&mutex);
1547126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        //pthread_mutex_unlock(&mutex);
1557126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        ok = pthread_create(&threads[i], (const pthread_attr_t *) NULL, thread_start,
1567126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten                &thread_args[i]);
1577126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        assert(0 == ok);
1587126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    }
1597126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1607126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // let it run for a while
1617126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    int j;
1620a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    for (j = 0; j < 100; ++j) {
1637126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        sleep(1);
1647126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        for (i = 0; i < MAX_THREAD; ++i) {
1657126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ThreadArgument *ta = &thread_args[i];
16658432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten            printf("[%d]=%u ", j, ta->mCounter);
1677126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        }
1687126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        printf("\n");
1697126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    }
1707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1717126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // signal threads that they should exit
1727126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    timeToExit = 1;
1737126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1747126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    for (j = 0; j < 3; ++j) {
1757126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        sleep(1);
1767126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        for (i = 0; i < MAX_THREAD; ++i) {
1777126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten            ThreadArgument *ta = &thread_args[i];
17858432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten            printf("[%d]=%u ", j, ta->mCounter);
1797126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        }
1807126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        printf("\n");
1817126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    }
1827126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1837126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // now wait for the threads to actually exit
1847126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    for (i = 0; i < MAX_THREAD; ++i) {
1857126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        ok = pthread_join(threads[i], NULL);
1867126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten        assert(0 == ok);
1877126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    }
1887126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1897126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // tear down objects
1907126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    (*mixObject)->Destroy(mixObject);
1917126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    (*engineObject)->Destroy(engineObject);
1927126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
1937126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    return EXIT_SUCCESS;
1947126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten}
195