X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Fdevel-api%2Fthreading%2Fconditional-wait.cpp;h=fa0a86c42404a684b840e396734bd1da81174381;hb=refs%2Ftags%2Faccepted%2Ftizen%2F4.0%2Funified%2F20171129.150239;hp=adc5760a6f7e0e234f2db6ef9aa352aebfa516b4;hpb=f49ab405dbdef08aa06ab03077d61dab2626704d;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/devel-api/threading/conditional-wait.cpp b/dali/devel-api/threading/conditional-wait.cpp index adc5760..fa0a86c 100644 --- a/dali/devel-api/threading/conditional-wait.cpp +++ b/dali/devel-api/threading/conditional-wait.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,77 +19,78 @@ #include // EXTERNAL INCLUDES -#include +#include +#include // INTERNAL INCLUDES #include -#include +#include namespace Dali { - +/** + * Data members for ConditionalWait + */ struct ConditionalWait::ConditionalWaitImpl { - pthread_mutex_t mutex; - pthread_cond_t condition; + std::mutex mutex; + std::condition_variable condition; volatile unsigned int count; }; +/** + * Data members for ConditionalWait::ScopedLock + */ +struct ConditionalWait::ScopedLock::ScopedLockImpl +{ + ScopedLockImpl( ConditionalWait& wait ) + : wait( wait ), + lock( wait.mImpl->mutex ) // locks for the lifecycle of this object + { } + ConditionalWait& wait; + std::unique_lock lock; +}; -ConditionalWait::ScopedLock::ScopedLock( ConditionalWait& wait ) : mWait(wait) +ConditionalWait::ScopedLock::ScopedLock( ConditionalWait& wait ) +: mImpl( new ConditionalWait::ScopedLock::ScopedLockImpl( wait ) ) { - Internal::Mutex::Lock( &wait.mImpl->mutex ); + Internal::MutexTrace::Lock(); // matching sequence in mutex.cpp } ConditionalWait::ScopedLock::~ScopedLock() { - ConditionalWait& wait = mWait; - Internal::Mutex::Unlock( &wait.mImpl->mutex ); + Internal::MutexTrace::Unlock(); + delete mImpl; +} + +ConditionalWait& ConditionalWait::ScopedLock::GetLockedWait() const +{ + return mImpl->wait; // mImpl can never be NULL } ConditionalWait::ConditionalWait() : mImpl( new ConditionalWaitImpl ) { - if( pthread_mutex_init( &mImpl->mutex, NULL ) ) - { - DALI_LOG_ERROR( "Unable to initialise mutex in ConditionalWait\n" ); - } - if( pthread_cond_init( &mImpl->condition, NULL ) ) - { - DALI_LOG_ERROR( "Unable to initialise conditional\n" ); - } mImpl->count = 0; } ConditionalWait::~ConditionalWait() { - if( pthread_cond_destroy( &mImpl->condition ) ) - { - DALI_LOG_ERROR( "Unable to destroy conditional\n" ); - } - if( pthread_mutex_destroy( &mImpl->mutex ) ) - { - DALI_LOG_ERROR( "Unable to destroy mutex in ConditionalWait\n" ); - } delete mImpl; } void ConditionalWait::Notify() { - // pthread_cond_wait requires a lock to be held - Internal::Mutex::Lock( &mImpl->mutex ); + // conditional wait requires a lock to be held + ScopedLock lock( *this ); volatile unsigned int previousCount = mImpl->count; mImpl->count = 0; // change state before broadcast as that may wake clients immediately - // broadcast does nothing if the thread is not waiting but still has a system call overhead - // broadcast all threads to continue + // notify does nothing if the thread is not waiting but still has a system call overhead + // notify all threads to continue if( 0 != previousCount ) { - if( pthread_cond_broadcast( &mImpl->condition ) ) - { - DALI_LOG_ERROR( "Error calling pthread_cond_broadcast\n" ); - } + mImpl->condition.notify_all(); // no return value } - Internal::Mutex::Unlock( &mImpl->mutex ); } void ConditionalWait::Notify( const ScopedLock& scope ) @@ -99,35 +100,26 @@ void ConditionalWait::Notify( const ScopedLock& scope ) volatile unsigned int previousCount = mImpl->count; mImpl->count = 0; // change state before broadcast as that may wake clients immediately - // broadcast does nothing if the thread is not waiting but still has a system call overhead - // broadcast all threads to continue + // notify does nothing if the thread is not waiting but still has a system call overhead + // notify all threads to continue if( 0 != previousCount ) { - if( pthread_cond_broadcast( &mImpl->condition ) ) - { - DALI_LOG_ERROR( "Error calling pthread_cond_broadcast\n" ); - } + mImpl->condition.notify_all(); // no return value } } void ConditionalWait::Wait() { - // pthread_cond_wait requires a lock to be held - Internal::Mutex::Lock( &mImpl->mutex ); + // conditional wait requires a lock to be held + ScopedLock scope( *this ); ++(mImpl->count); - // pthread_cond_wait may wake up without anyone calling Notify + // conditional wait may wake up without anyone calling Notify do { // wait while condition changes - if( pthread_cond_wait( &mImpl->condition, &mImpl->mutex ) ) // releases the lock whilst waiting - { - DALI_LOG_ERROR( "Error calling pthread_cond_wait\n" ); - break; - } + mImpl->condition.wait( scope.mImpl->lock ); // need to pass in the std::unique_lock } while( 0 != mImpl->count ); - // when condition returns the mutex is locked so release the lock - Internal::Mutex::Unlock( &mImpl->mutex ); } void ConditionalWait::Wait( const ScopedLock& scope ) @@ -137,16 +129,11 @@ void ConditionalWait::Wait( const ScopedLock& scope ) ++(mImpl->count); - // pthread_cond_wait may wake up without anyone calling Notify so loop until - // count has been reset in a notify: + // conditional wait may wake up without anyone calling Notify do { // wait while condition changes - if( pthread_cond_wait( &mImpl->condition, &mImpl->mutex ) ) // releases the lock whilst waiting - { - DALI_LOG_ERROR( "Error calling pthread_cond_wait\n" ); - break; - } + mImpl->condition.wait( scope.mImpl->lock ); // need to pass in the std::unique_lock } while( 0 != mImpl->count );