utc-Dali-SignalDelegate.cpp
utc-Dali-Scripting.cpp
utc-Dali-Shader.cpp
+ utc-Dali-Thread.cpp
utc-Dali-WeakHandle.cpp
)
#include <stdlib.h>
#include <unistd.h>
#include <dali-test-suite-utils.h>
-#include <dali/devel-api/common/conditional-wait.h>
+#include <dali/devel-api/threading/conditional-wait.h>
+#include <dali/devel-api/threading/thread.h>
using Dali::ConditionalWait;
+using Dali::Thread;
namespace // for local variables to avoid name clashes
{
volatile bool gWorkerThreadWait = true;
enum ThreadState { INIT, RUN, TERMINATE } volatile gWorkerThreadState = INIT;
ConditionalWait* volatile gConditionalWait; // volatile pointer to a ConditionalWait object
-}
-void* WorkerThreadNotify( void* ptr )
+class WorkerThreadNotify : public Thread
{
- gGlobalValue = -1;
- while( gWorkerThreadWait ) // wait till we can exit
+ virtual void Run()
{
- gWorkerThreadState = RUN;
- usleep( 1 ); // 1 microseconds
+ gGlobalValue = -1;
+ while( gWorkerThreadWait ) // wait till we can exit
+ {
+ gWorkerThreadState = RUN;
+ usleep( 1 ); // 1 microseconds
+ }
+ usleep( 200 ); // give other thread time to get to Wait
+ gGlobalValue = 1;
+ gConditionalWait->Notify();
+ gWorkerThreadState = TERMINATE;
}
- usleep( 200 ); // give other thread time to get to Wait
- gGlobalValue = 1;
- gConditionalWait->Notify();
- gWorkerThreadState = TERMINATE;
- return NULL;
+};
+
+volatile int gNotifyCount = 0;
+class WorkerThreadNotifyN : public Thread
+{
+ virtual void Run()
+ {
+ while( gNotifyCount > 0 )
+ {
+ gConditionalWait->Notify();
+ usleep( 10 ); // 10 microseconds between each notify
+ }
+ }
+};
+
+class WorkerThreadWaitN : public Thread
+{
+ virtual void Run()
+ {
+ gConditionalWait->Wait();
+ }
+};
+
}
int UtcConditionalWait1P(void)
{
tet_infoline("Testing ConditionalWait - scenario: wait - notify with 2 threads");
- pthread_t thread1;
+ WorkerThreadNotify thread1;
// initialize values
gConditionalWait = new ConditionalWait();
gWorkerThreadWait = true;
DALI_TEST_EQUALS( INIT, gWorkerThreadState, TEST_LOCATION );
DALI_TEST_EQUALS( 0, gGlobalValue, TEST_LOCATION );
- pthread_create( &thread1, NULL, &WorkerThreadNotify, NULL );
+ thread1.Start();
// wait till the thread is in run state
while( RUN != gWorkerThreadState )
{
usleep( 1 ); // 1 microsecond
}
- void* exitValue;
- pthread_join( thread1, &exitValue );
+ thread1.Join();
delete gConditionalWait;
END_TEST;
END_TEST;
}
-volatile int gNotifyCount = 0;
-void* WorkerThreadNotifyN( void* ptr )
-{
- while( gNotifyCount > 0 )
- {
- gConditionalWait->Notify();
- usleep( 10 ); // 10 microseconds between each notify
- }
- return NULL;
-}
int UtcConditionalWait3P(void)
{
gConditionalWait = new ConditionalWait();
gNotifyCount = 100;
- pthread_t thread1;
- pthread_create( &thread1, NULL, &WorkerThreadNotifyN, NULL );
+ WorkerThreadNotifyN thread1;
+ thread1.Start();
while( gNotifyCount > 0 )
{
}
DALI_TEST_EQUALS( 0u, gConditionalWait->GetWaitCount(), TEST_LOCATION );
- void* exitValue;
- pthread_join( thread1, &exitValue );
+ thread1.Join();
delete gConditionalWait;
END_TEST;
gConditionalWait = new ConditionalWait();
gNotifyCount = 100;
- pthread_t thread1;
- pthread_create( &thread1, NULL, &WorkerThreadNotifyN, NULL );
- pthread_t thread2;
- pthread_create( &thread2, NULL, &WorkerThreadNotifyN, NULL );
- pthread_t thread3;
- pthread_create( &thread3, NULL, &WorkerThreadNotifyN, NULL );
+ WorkerThreadNotifyN thread1;
+ thread1.Start();
+ WorkerThreadNotifyN thread2;
+ thread2.Start();
+ WorkerThreadNotifyN thread3;
+ thread3.Start();
while( gNotifyCount > 0 )
{
usleep( 10 ); // 10 microseconds between each notify
}
- void* exitValue;
- pthread_join( thread1, &exitValue );
- pthread_join( thread2, &exitValue );
- pthread_join( thread3, &exitValue );
+ thread1.Join();
+ thread2.Join();
+ thread3.Join();
delete gConditionalWait;
END_TEST;
}
-void* WorkerThreadWaitN( void* ptr )
-{
- gConditionalWait->Wait();
-
- return NULL;
-}
-
int UtcConditionalWait5P(void)
{
tet_infoline("Testing ConditionalWait - scenario: 4 threads wait - notify once from 1 thread");
// initialize values
gConditionalWait = new ConditionalWait();
- pthread_t thread1;
- pthread_create( &thread1, NULL, &WorkerThreadWaitN, NULL );
- pthread_t thread2;
- pthread_create( &thread2, NULL, &WorkerThreadWaitN, NULL );
- pthread_t thread3;
- pthread_create( &thread3, NULL, &WorkerThreadWaitN, NULL );
- pthread_t thread4;
- pthread_create( &thread4, NULL, &WorkerThreadWaitN, NULL );
-
+ WorkerThreadWaitN thread1;
+ thread1.Start();
+ WorkerThreadWaitN thread2;
+ thread2.Start();
+ WorkerThreadWaitN thread3;
+ thread3.Start();
+ WorkerThreadWaitN thread4;
+ thread4.Start();
// wait till all child threads are waiting
while( gConditionalWait->GetWaitCount() < 4 )
{ }
// notify once, it will resume all threads
gConditionalWait->Notify();
- void* exitValue;
- pthread_join( thread1, &exitValue );
- pthread_join( thread2, &exitValue );
- pthread_join( thread3, &exitValue );
- pthread_join( thread4, &exitValue );
+ thread1.Join();
+ thread2.Join();
+ thread3.Join();
+ thread4.Join();
DALI_TEST_EQUALS( 0u, gConditionalWait->GetWaitCount(), TEST_LOCATION );
#include <stdlib.h>
#include <unistd.h>
#include <dali/public-api/dali-core.h>
-#include <dali/devel-api/common/mutex.h>
+#include <dali/devel-api/threading/mutex.h>
+#include <dali/devel-api/threading/thread.h>
#include <dali-test-suite-utils.h>
using Dali::Mutex;
+using Dali::Thread;
int UtcDaliMutexSingleThread(void)
{
volatile bool gWorkerThreadWait = true;
volatile enum ThreadState { INIT, RUN, LOCKING, TERMINATE } gWorkerThreadState = INIT;
Mutex* volatile gGlobalValueMutex; // volatile pointer to a mutex object
-}
-void* WorkerThread1( void* ptr )
+
+class TestThread : public Thread
{
- gWorkerThreadState = RUN;
+ virtual void Run()
{
- Mutex::ScopedLock lock( *gGlobalValueMutex );
- gWorkerThreadState = LOCKING;
- gGlobalValue = -1;
- while( gWorkerThreadWait ) // wait till we can exit
+ gWorkerThreadState = RUN;
{
- usleep( 1 ); // 1 microsecond
+ Mutex::ScopedLock lock( *gGlobalValueMutex );
+ gWorkerThreadState = LOCKING;
+ gGlobalValue = -1;
+ while( gWorkerThreadWait ) // wait till we can exit
+ {
+ usleep( 1 ); // 1 microsecond
+ }
}
+ gWorkerThreadState = TERMINATE;
}
- gWorkerThreadState = TERMINATE;
- return NULL;
+};
}
int UtcDaliMutexMultiThread(void)
gGlobalValueMutex = new Dali::Mutex();
- pthread_t thread1;
+ TestThread thread1;
// initialize values
gGlobalValue = 0;
gWorkerThreadWait = true;
{
Mutex::ScopedLock lock( *gGlobalValueMutex );
DALI_TEST_EQUALS( true, gGlobalValueMutex->IsLocked(), TEST_LOCATION );
- pthread_create( &thread1, NULL, &WorkerThread1, NULL );
+ thread1.Start();
// wait till the thread is in run state
while( RUN != gWorkerThreadState )
{
usleep( 1 ); // 1 microsecond
}
DALI_TEST_EQUALS( false, gGlobalValueMutex->IsLocked(), TEST_LOCATION );
- void* exitValue;
- pthread_join( thread1, &exitValue );
+ thread1.Join();
END_TEST;
}
--- /dev/null
+/*
+ * 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.
+ * 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 <iostream>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dali-test-suite-utils.h>
+#include <dali/devel-api/threading/thread.h>
+
+using Dali::Thread;
+
+namespace
+{
+volatile bool gRunThreadEntryFunc = false;
+
+class TestThread : public Thread
+{
+ virtual void Run()
+ {
+ gRunThreadEntryFunc = true;
+ }
+};
+}
+
+int UtcDaliThreadP(void)
+{
+ tet_infoline("Testing Dali::Thread");
+
+ gRunThreadEntryFunc = false;
+
+ TestThread thread;
+
+ thread.Start();
+ // wait till the thread is terminated
+ while( !gRunThreadEntryFunc )
+ {
+ usleep( 1 ); // 1 microsecond
+ }
+ DALI_TEST_EQUALS( true, gRunThreadEntryFunc, TEST_LOCATION );
+
+ thread.Join();
+
+ // Restart the thread after joined
+ gRunThreadEntryFunc = false;
+ thread.Start();
+ thread.Join();
+ // wait till the thread is terminated
+ while( !gRunThreadEntryFunc )
+ {
+ usleep( 1 ); // 1 microsecond
+ }
+ DALI_TEST_EQUALS( true, gRunThreadEntryFunc, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliThreadNonCopyable(void)
+{
+ // we want to make sure that mutex is not copyable (its copy constructor is not defined)
+ // this test will stop compiling if Mutex has compiler generated copy constructor
+ DALI_COMPILE_TIME_ASSERT( !__has_trivial_copy( Thread ) );
+
+ DALI_TEST_CHECK( true );
+ END_TEST;
+}
develapirenderingdir = $(develapidir)/rendering
develapiscriptingdir = $(develapidir)/scripting
develapisignalsdir = $(develapidir)/signals
+develapithreadingdir = $(develapidir)/threading
develapi_HEADERS = $(devel_api_header_files)
develapiactors_HEADERS = $(devel_api_core_actors_header_files)
develapirendering_HEADERS = $(devel_api_core_rendering_header_files)
develapiscripting_HEADERS = $(devel_api_core_scripting_header_files)
develapisignals_HEADERS = $(devel_api_core_signals_header_files)
+develapithreading_HEADERS = $(devel_api_core_threading_header_files)
#public api
devel_api_src_files = \
$(devel_api_src_dir)/animation/animation-data.cpp \
$(devel_api_src_dir)/animation/path-constrainer.cpp \
- $(devel_api_src_dir)/common/conditional-wait.cpp \
$(devel_api_src_dir)/common/hash.cpp \
- $(devel_api_src_dir)/common/mutex.cpp \
$(devel_api_src_dir)/events/hit-test-algorithm.cpp \
$(devel_api_src_dir)/images/atlas.cpp \
$(devel_api_src_dir)/images/distance-field.cpp \
$(devel_api_src_dir)/rendering/sampler.cpp \
$(devel_api_src_dir)/rendering/shader.cpp \
$(devel_api_src_dir)/scripting/scripting.cpp \
- $(devel_api_src_dir)/signals/signal-delegate.cpp
+ $(devel_api_src_dir)/signals/signal-delegate.cpp \
+ $(devel_api_src_dir)/threading/conditional-wait.cpp \
+ $(devel_api_src_dir)/threading/mutex.cpp \
+ $(devel_api_src_dir)/threading/thread.cpp
# Add devel header files here DALi internal developer files used by Adaptor & Toolkit
devel_api_core_common_header_files = \
$(devel_api_src_dir)/common/hash.h \
$(devel_api_src_dir)/common/map-wrapper.h \
- $(devel_api_src_dir)/common/conditional-wait.h \
- $(devel_api_src_dir)/common/mutex.h \
$(devel_api_src_dir)/common/owner-container.h \
$(devel_api_src_dir)/common/ref-counted-dali-vector.h \
- $(devel_api_src_dir)/common/set-wrapper.h
+ $(devel_api_src_dir)/common/set-wrapper.h
devel_api_core_events_header_files = \
$(devel_api_src_dir)/events/hit-test-algorithm.h
devel_api_core_scripting_header_files = \
$(devel_api_src_dir)/scripting/scripting.h
+devel_api_core_threading_header_files = \
+ $(devel_api_src_dir)/threading/conditional-wait.h \
+ $(devel_api_src_dir)/threading/mutex.h \
+ $(devel_api_src_dir)/threading/thread.h
*/
// CLASS HEADER
-#include <dali/devel-api/common/conditional-wait.h>
+#include <dali/devel-api/threading/conditional-wait.h>
// INTERNAL INCLUDES
#include <dali/internal/common/mutex-impl.h>
*/
// CLASS HEADER
-#include <dali/devel-api/common/mutex.h>
+#include <dali/devel-api/threading/mutex.h>
// INTERNAL INCLUDES
#include <dali/internal/common/mutex-impl.h>
--- /dev/null
+/*
+ * 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.
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/threading/thread.h>
+
+// EXTERNAL INCLUDES
+#include <cstddef>
+#include <pthread.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+struct Thread::ThreadImpl
+{
+ pthread_t thread;
+ bool isCreated;
+};
+
+Thread::Thread()
+: mImpl( new ThreadImpl )
+{
+ mImpl->isCreated = false;
+}
+
+Thread::~Thread()
+{
+ delete mImpl;
+}
+
+void Thread::Start()
+{
+ 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()
+{
+ if( mImpl->isCreated )
+ {
+ mImpl->isCreated = false;
+ pthread_join( mImpl->thread, NULL );
+ }
+}
+
+void* Thread::InternalThreadEntryFunc( void* This )
+{
+ ( static_cast<Thread*>( This ) )->Run();
+ return NULL;
+}
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_THREAD_H__
+#define __DALI_THREAD_H__
+
+/*
+ * 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.
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+
+/**
+ * The top level DALi namespace
+ */
+namespace Dali
+{
+
+/*
+ * @brief Abstract class for thread functionality. Can be used for worker threads.
+ */
+class DALI_IMPORT_API Thread
+{
+public:
+
+ /**
+ * @brief Creates a new thread and make it executable.
+ */
+ void Start();
+
+ /**
+ * @brief Wait for thread termination.
+ */
+ void Join();
+
+protected:
+
+ /**
+ * @brief Constructor
+ */
+ Thread();
+
+ /**
+ * @brief Destructor, virtual as this is used as base class
+ */
+ virtual ~Thread();
+
+ /**
+ * The routine that the thread will execute once it is started.
+ */
+ virtual void Run() = 0;
+
+private:
+
+ /**
+ * Helper for the thread calling the entry function.
+ * @param[in] This A pointer to the current RenderThread object
+ */
+ static void* InternalThreadEntryFunc( void* This );
+
+ // Undefined
+ Thread( const Thread& );
+ // Undefined
+ const Thread& operator=( const Thread& );
+
+private:
+
+ struct ThreadImpl;
+ ThreadImpl* mImpl;
+};
+
+}
+
+#endif /* __DALI_THREAD_H__ */
// INTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
-#include <dali/devel-api/common/mutex.h>
#include <dali/devel-api/common/owner-container.h>
+#include <dali/devel-api/threading/mutex.h>
#include <dali/internal/common/message.h>
#include <dali/internal/event/common/property-notification-impl.h>
#include <dali/internal/event/common/complete-notification-interface.h>
// INTERNAL INCLUDES
#include <dali/public-api/common/stage.h>
#include <dali/devel-api/common/set-wrapper.h>
-#include <dali/devel-api/common/mutex.h>
#include <dali/devel-api/common/owner-container.h>
+#include <dali/devel-api/threading/mutex.h>
#include <dali/integration-api/core.h>
#include <dali/integration-api/render-controller.h>
// INTERNAL INCLUDES
#include <dali/public-api/common/vector-wrapper.h>
-#include <dali/devel-api/common/mutex.h>
+#include <dali/devel-api/threading/mutex.h>
#include <dali/integration-api/render-controller.h>
#include <dali/internal/common/message.h>
#include <dali/internal/common/message-buffer.h>