multithread.c revision 086a6f51a7b12880ed114962136972f89ed70da2
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 107086a6f51a7b12880ed114962136972f89ed70da2Glenn Kastenint main(int argc __unused, char **argv __unused) 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