$(dali_core_includes) \
$(DALI_CFLAGS)
-libdali_core_la_LIBADD = $(DALI_LDFLAGS)
+libdali_core_la_LIBADD = $(DALI_LDFLAGS) \
+ -lpthread
# Install headers under the correct subdirectories
platformabstractiondir = $(includedir)/dali/integration-api
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 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.
#include <dali/devel-api/threading/conditional-wait.h>
// EXTERNAL INCLUDES
-#include <mutex>
-#include <condition_variable>
+#include <pthread.h>
// INTERNAL INCLUDES
#include <dali/integration-api/debug.h>
-#include <dali/internal/common/mutex-trace.h>
+#include <dali/internal/common/mutex-impl.h>
namespace Dali
{
-/**
- * Data members for ConditionalWait
- */
+
struct ConditionalWait::ConditionalWaitImpl
{
- std::mutex mutex;
- std::condition_variable condition;
+ pthread_mutex_t mutex;
+ pthread_cond_t 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<std::mutex> lock;
-};
-ConditionalWait::ScopedLock::ScopedLock( ConditionalWait& wait )
-: mImpl( new ConditionalWait::ScopedLock::ScopedLockImpl( wait ) )
+ConditionalWait::ScopedLock::ScopedLock( ConditionalWait& wait ) : mWait(wait)
{
- Internal::MutexTrace::Lock(); // matching sequence in mutex.cpp
+ Internal::Mutex::Lock( &wait.mImpl->mutex );
}
ConditionalWait::ScopedLock::~ScopedLock()
{
- Internal::MutexTrace::Unlock();
- delete mImpl;
-}
-
-ConditionalWait& ConditionalWait::ScopedLock::GetLockedWait() const
-{
- return mImpl->wait; // mImpl can never be NULL
+ ConditionalWait& wait = mWait;
+ Internal::Mutex::Unlock( &wait.mImpl->mutex );
}
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()
{
- // conditional wait requires a lock to be held
- ScopedLock lock( *this );
+ // pthread_cond_wait requires a lock to be held
+ Internal::Mutex::Lock( &mImpl->mutex );
volatile unsigned int previousCount = mImpl->count;
mImpl->count = 0; // change state before broadcast as that may wake clients immediately
- // notify does nothing if the thread is not waiting but still has a system call overhead
- // notify all threads to continue
+ // broadcast does nothing if the thread is not waiting but still has a system call overhead
+ // broadcast all threads to continue
if( 0 != previousCount )
{
- mImpl->condition.notify_all(); // no return value
+ if( pthread_cond_broadcast( &mImpl->condition ) )
+ {
+ DALI_LOG_ERROR( "Error calling pthread_cond_broadcast\n" );
+ }
}
+ Internal::Mutex::Unlock( &mImpl->mutex );
}
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
- // notify does nothing if the thread is not waiting but still has a system call overhead
- // notify all threads to continue
+ // broadcast does nothing if the thread is not waiting but still has a system call overhead
+ // broadcast all threads to continue
if( 0 != previousCount )
{
- mImpl->condition.notify_all(); // no return value
+ if( pthread_cond_broadcast( &mImpl->condition ) )
+ {
+ DALI_LOG_ERROR( "Error calling pthread_cond_broadcast\n" );
+ }
}
}
void ConditionalWait::Wait()
{
- // conditional wait requires a lock to be held
- ScopedLock scope( *this );
+ // pthread_cond_wait requires a lock to be held
+ Internal::Mutex::Lock( &mImpl->mutex );
++(mImpl->count);
- // conditional wait may wake up without anyone calling Notify
+ // pthread_cond_wait may wake up without anyone calling Notify
do
{
// wait while condition changes
- mImpl->condition.wait( scope.mImpl->lock ); // need to pass in the std::unique_lock
+ if( pthread_cond_wait( &mImpl->condition, &mImpl->mutex ) ) // releases the lock whilst waiting
+ {
+ DALI_LOG_ERROR( "Error calling pthread_cond_wait\n" );
+ break;
+ }
}
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 )
++(mImpl->count);
- // conditional wait may wake up without anyone calling Notify
+ // pthread_cond_wait may wake up without anyone calling Notify so loop until
+ // count has been reset in a notify:
do
{
// wait while condition changes
- mImpl->condition.wait( scope.mImpl->lock ); // need to pass in the std::unique_lock
+ if( pthread_cond_wait( &mImpl->condition, &mImpl->mutex ) ) // releases the lock whilst waiting
+ {
+ DALI_LOG_ERROR( "Error calling pthread_cond_wait\n" );
+ break;
+ }
}
while( 0 != mImpl->count );
#define __DALI_CONDITIONAL_WAIT_H__
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 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.
* Getter for the ConditionalWait locked for this instance's lifetime.
* @return the ConditionalWait object currently locked.
*/
- ConditionalWait& GetLockedWait() const;
-
- public: // Data, public to allow nesting class to access
-
- struct ScopedLockImpl;
- ScopedLockImpl* mImpl;
+ ConditionalWait& GetLockedWait() const { return mWait; }
private:
// Not implemented as ScopedLock cannot be copied:
ScopedLock( const ScopedLock& );
const ScopedLock& operator=( const ScopedLock& );
+
+ ConditionalWait& mWait;
};
/**
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 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.
#include <dali/devel-api/threading/mutex.h>
// EXTERNAL INCLUDES
-#include <mutex>
+#include <pthread.h>
// INTERNAL INCLUDES
#include <dali/integration-api/debug.h>
-#include <dali/internal/common/mutex-trace.h>
+#include <dali/internal/common/mutex-impl.h>
namespace Dali
{
struct Mutex::MutexImpl
{
- std::mutex mutex;
+ pthread_mutex_t mutex;
bool locked;
};
Mutex::Mutex()
: mImpl( new MutexImpl )
{
+ if( pthread_mutex_init( &mImpl->mutex, NULL ) )
+ {
+ DALI_LOG_ERROR( "Unable to initialise Mutex\n" );
+ }
mImpl->locked = false;
}
Mutex::~Mutex()
{
+ if( pthread_mutex_destroy( &mImpl->mutex ) )
+ {
+ DALI_LOG_ERROR( "Unable to destroy Mutex\n" );
+ }
// nothing else to do as there is no Lock/Unlock API
// ScopedLock destructor will always unlock the mutex
delete mImpl;
Mutex::ScopedLock::ScopedLock( Mutex& mutex )
: mMutex( mutex )
{
- mMutex.mImpl->mutex.lock();
- Internal::MutexTrace::Lock(); // matching sequence in conditional-wait.cpp
+ Internal::Mutex::Lock( &mMutex.mImpl->mutex );
mMutex.mImpl->locked = true;
}
Mutex::ScopedLock::~ScopedLock()
{
mMutex.mImpl->locked = false;
- Internal::MutexTrace::Unlock(); // reverse sequence from lock
- mMutex.mImpl->mutex.unlock();
+ Internal::Mutex::Unlock( &mMutex.mImpl->mutex );
}
} // namespace Dali
#define __DALI_MUTEX_H__
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 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.
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 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.
// EXTERNAL INCLUDES
#include <cstddef>
-#include <thread>
+#include <pthread.h>
#include <dali/integration-api/debug.h>
namespace Dali
struct Thread::ThreadImpl
{
- ThreadImpl( Thread& aThis )
- : thread( &Thread::InternalThreadEntryFunc, std::ref( aThis ) )
- {
- // std::thread starts execution immediately
- }
- ~ThreadImpl( )
- {
- thread.join();
- }
- std::thread thread;
+ pthread_t thread;
+ bool isCreated;
};
Thread::Thread()
-: mImpl( nullptr )
+: mImpl( new ThreadImpl )
{
+ mImpl->isCreated = false;
}
Thread::~Thread()
{
- Join();
+ delete mImpl;
}
void Thread::Start()
{
- if( !mImpl )
- {
- mImpl = new Thread::ThreadImpl( *this );
- }
+ DALI_ASSERT_DEBUG( !mImpl->isCreated );
+
+ int error = pthread_create( &(mImpl->thread), NULL, InternalThreadEntryFunc, this );
+ DALI_ASSERT_ALWAYS( !error && "Failed to create a new thread" );
+ mImpl->isCreated = true;
}
void Thread::Join()
{
- delete mImpl;
- mImpl = nullptr;
+ if( mImpl->isCreated )
+ {
+ mImpl->isCreated = false;
+ pthread_join( mImpl->thread, NULL );
+ }
}
-void Thread::InternalThreadEntryFunc( Thread& aThis )
+void* Thread::InternalThreadEntryFunc( void* This )
{
- aThis.Run();
+ ( static_cast<Thread*>( This ) )->Run();
+ return NULL;
}
} // namespace Dali
#define __DALI_THREAD_H__
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 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.
// INTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
+
/**
* The top level DALi namespace
*/
/**
* Helper for the thread calling the entry function.
- * @param[in] This A pointer to the current thread object
+ * @param[in] This A pointer to the current RenderThread object
*/
- static void InternalThreadEntryFunc( Thread& This );
+ static void* InternalThreadEntryFunc( void* This );
// Undefined
Thread( const Thread& );
struct ThreadImpl;
ThreadImpl* mImpl;
-
};
}
*/
// HEADER
-#include <dali/internal/common/mutex-trace.h>
+#include <dali/internal/common/mutex-impl.h>
+
#ifdef LOCK_BACKTRACE_ENABLED
// EXTERNAL INCLUDES
namespace Internal
{
-namespace MutexTrace
+namespace Mutex
{
namespace
thread_local unsigned int gThreadLockCount = 0; ///< Thread local storage for the backtrace of the locks
} // unnamed namespace
-void Lock()
+void Lock( pthread_mutex_t* mutex )
{
++gThreadLockCount;
//DALI_ASSERT_DEBUG( gThreadLockCount == 1 );
#endif // LOCK_BACKTRACE_ENABLED
+
+ if( pthread_mutex_lock( mutex ) )
+ {
+ DALI_LOG_ERROR( "Error calling pthread_mutex_lock\n" );
+ }
}
-void Unlock()
+void Unlock( pthread_mutex_t* mutex )
{
+ if( pthread_mutex_unlock( mutex ) )
+ {
+ DALI_LOG_ERROR( "Error calling pthread_mutex_unlock\n" );
+ }
--gThreadLockCount;
}
-} // namespace MutexTrace
+} // namespace Mutex
} // namespace Internal
-#ifndef DALI_INTERNAL_MUTEX_TRACE_H
-#define DALI_INTERNAL_MUTEX_TRACE_H
+#ifndef __DALI_INTERNAL_MUTEX_H__
+#define __DALI_INTERNAL_MUTEX_H__
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 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.
*
*/
+// EXTERNAL INCLUDES
+#include <pthread.h>
+
namespace Dali
{
*
* @note lock backtrace needs to be enabled to see the warnings.
*/
-namespace MutexTrace
+namespace Mutex
{
/**
- * @brief Increments a thread-local storage counter.
+ * @brief Locks the given mutex.
+ *
+ * Increments a thread-local storage counter.
+ *
+ * @param A pointer to the mutex that should be locked.
*
* @note If the counter is > 1 and lock backtrace is enabled, then the backtrace for all locks will be shown as a warning.
*/
-void Lock();
+void Lock( pthread_mutex_t* mutex );
/**
- * @brief Decrements a thread-local storage counter
+ * @brief Unlocks the given mutex.
+ *
+ * @param A pointer to the mutex that should be unlocked.
+ *
+ * Decrements a thread-local storage counter.
*/
-void Unlock();
+void Unlock( pthread_mutex_t* mutex );
-} // namespace MutexTrace
+} // namespace Mutex
} // namespace Internal
} // namespace Dali
-#endif // DALI_INTERNAL_MUTEX_TRACE_H
+#endif // __DALI_INTERNAL_MUTEX_H__
$(internal_src_dir)/common/internal-constants.cpp \
$(internal_src_dir)/common/math.cpp \
$(internal_src_dir)/common/message-buffer.cpp \
- $(internal_src_dir)/common/mutex-trace.cpp \
+ $(internal_src_dir)/common/mutex-impl.cpp \
$(internal_src_dir)/common/image-sampler.cpp \
$(internal_src_dir)/common/image-attributes.cpp \
$(internal_src_dir)/common/fixed-size-memory-pool.cpp \
%build
PREFIX="/usr"
CXXFLAGS+=" -Wall -g -Os -DNDEBUG -fPIC -fvisibility-inlines-hidden -fdata-sections -ffunction-sections "
-LDFLAGS+=" -Wl,--rpath=$PREFIX/lib -Wl,--as-needed -Wl,--gc-sections -lgcc_s -lgcc -Wl,-Bsymbolic-functions "
+LDFLAGS+=" -Wl,--rpath=$PREFIX/lib -Wl,--as-needed -Wl,--gc-sections -lgcc_s -lgcc -lpthread -Wl,-Bsymbolic-functions "
%ifarch %{arm}
CXXFLAGS+=" -D_ARCH_ARM_ -mfpu=neon"