blob: 29f208dc3f2f78bf2fab9732e4521f7e84cf939c [file] [log] [blame]
/*---------------------------------------------------------------------------*
* RecursiveMutexTest.cpp *
* *
* Copyright 2007, 2008 Nuance Communciations, Inc. *
* *
* Licensed under the Apache License, Version 2.0 (the 'License'); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an 'AS IS' BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* *
*---------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include "Runnable.h"
#include "ReturnCode.h"
#include "Mutex.h"
using namespace android::speech::recognition;
using namespace android::speech::recognition::utilities;
int Q_RecursiveMutexTest()
{
pthread_mutex_t my_mutex;
pthread_mutexattr_t my_mutex_attr;
int ret;
printf("\n--------------- Q_RecursiveMutexTest Running ---------------\n\n");
printf("Initializing mutex attribute to default value.\n");
ret = pthread_mutexattr_init(&my_mutex_attr);
if (ret)
{
fprintf(stderr, "ERROR: Failure in pthread_mutexattr_init(&my_mutex_attr), returns %d\n", ret);
return 1;
}
printf("Setting mutex attribute to type PTHREAD_MUTEX_RECURSIVE.\n");
ret = pthread_mutexattr_settype(&my_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
if (ret)
{
fprintf(stderr, "ERROR: Failure in pthread_mutexattr_settype(&my_mutex_attr, PTHREAD_MUTEX_RECURSIVE), returns %d\n", ret);
return 1;
}
printf("Initializing mutex with the above attributes.\n");
ret = pthread_mutex_init(&my_mutex, &my_mutex_attr);
if (ret)
{
fprintf(stderr, "ERROR: Failure in pthread_mutex_init(&my_mutex, &my_mutex_attr), returns %d\n", ret);
return 1;
}
printf("Locking mutex the first time from application thread\n");
ret = pthread_mutex_lock(&my_mutex);
if (ret)
{
fprintf(stderr, "ERROR: Failure in pthread_mutex_lock(&my_mutex), returns %d\n", ret);
return 1;
}
printf("\n***** MUTEX LOCKED *****\n\n");
printf("Locking the already locked mutex from the same thread.\n");
printf("This should not block since the mutex is recursive.\n");
ret = pthread_mutex_lock(&my_mutex);
if (ret)
{
fprintf(stderr, "ERROR: Failure in pthread_mutex_lock(&my_mutex), returns %d\n", ret);
return 1;
}
printf("\n***** Recursive mutex did not block (as expected) *****\n\n");
printf("Unlocking mutex\n");
ret = pthread_mutex_unlock(&my_mutex);
if (ret)
{
fprintf(stderr, "ERROR: Failure in pthread_mutex_unlock(&my_mutex), returns %d\n", ret);
return 1;
}
printf("\n***** MUTEX UNLOCKED *****\n");
printf("\n--------------- Q_RecursiveMutexTest Finished ---------------\n\n");
return 0;
}
#ifdef ENABLE_CUSTOM_MUTEX_TEST
class MyThread : public Runnable
{
public:
MyThread(Mutex* mutex) : _mutex(mutex), count(0) {}
virtual ReturnCode::Type runThread()
{
ReturnCode::Type rc;
//lock twice
_mutex->lock(rc);
if (rc != ReturnCode::SUCCESS)
return ReturnCode::THREAD_ERROR;
_mutex->lock(rc);
if (rc != ReturnCode::SUCCESS)
return ReturnCode::THREAD_ERROR;
count = 1;
Runnable::sleep(5000);
count = 2;
_mutex->unlock(rc);
if (rc != ReturnCode::SUCCESS)
return ReturnCode::THREAD_ERROR;
_mutex->unlock(rc);
if (rc != ReturnCode::SUCCESS)
return ReturnCode::THREAD_ERROR;
return ReturnCode::SUCCESS;
}
Mutex * _mutex;
int count;
};
int CustomMutexTest()
{
printf("\n--------------- CustomMutexTest Running ---------------\n\n");
ReturnCode::Type rc;
Mutex * mutex = Mutex::create(rc);
if (rc != ReturnCode::SUCCESS)
return 1;
MyThread thread(mutex);
thread.start(rc);
if (rc != ReturnCode::SUCCESS)
return 1;
//make sure thread starts
Runnable::sleep(2000);
//lock twice
mutex->lock(rc);
if (rc != ReturnCode::SUCCESS)
return 1;
mutex->lock(rc);
if (rc != ReturnCode::SUCCESS)
return 1;
if (thread.count != 2)
{
printf("Thread count is not ok\n");
return 1;
}
mutex->unlock(rc);
if (rc != ReturnCode::SUCCESS)
return 1;
mutex->unlock(rc);
if (rc != ReturnCode::SUCCESS)
return 1;
thread.join(rc);
if (rc != ReturnCode::SUCCESS)
return 1;
delete mutex;
printf("\n--------------- CustomMutexTest Finished ---------------\n\n");
return 0;
}
#endif /* ENABLE_CUSTOM_MUTEX_TEST */
int main(int argc, char *argv[])
{
/* disable stdout buffering to make sure printf() output always appear even on crash */
int ret = setvbuf(stdout, NULL, _IONBF, 0);
if (ret)
{
printf("Unable to disable buffering of stdout.\n");
}
if (Q_RecursiveMutexTest() != 0)
{
printf("Q_RecursiveMutexTest failed\n");
return 1;
}
#ifdef ENABLE_CUSTOM_MUTEX_TEST
if (CustomMutexTest() != 0)
{
printf("Custom mutex failed\n");
return 1;
}
#endif
printf("SUCCESS\n");
return 0;
}