Async image loading
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / image-loader / image-load-thread.cpp
@@ -27,46 +27,45 @@ namespace Toolkit
 namespace Internal
 {
 
-LoadingTask::LoadingTask(BitmapLoader loader, uint32_t packPositionX, uint32_t packPositionY, uint32_t width, uint32_t height )
+LoadingTask::LoadingTask(uint32_t id, BitmapLoader loader )
 : loader( loader ),
-  packRect( packPositionX, packPositionY, width, height )
+  id( id )
 {
 }
 
-LoadQueue::LoadQueue()
+ImageLoadThread::ImageLoadThread( EventThreadCallback* trigger )
+: mTrigger( trigger )
 {
 }
 
-LoadQueue::~LoadQueue()
+ImageLoadThread::~ImageLoadThread()
 {
+  // add an empty task would stop the thread from conditional wait.
+  AddTask( NULL );
+  // stop the thread
+  Join();
+
+  delete mTrigger;
 }
 
-LoadingTask* LoadQueue::NextTask()
+void ImageLoadThread::Run()
 {
-  // Lock while popping task out from the queue
-  ConditionalWait::ScopedLock lock( mConditionalWait );
-
-  while( mTasks.Empty() )
+  while( LoadingTask* task =  NextTaskToProcess())
   {
-    mConditionalWait.Wait( lock );
+    task->loader.Load();
+    AddCompletedTask( task );
   }
-
-  Vector< LoadingTask* >::Iterator next = mTasks.Begin();
-  LoadingTask* nextTask = *next;
-  mTasks.Erase( next );
-
-  return nextTask;
 }
 
-void LoadQueue::AddTask( LoadingTask* task )
+void ImageLoadThread::AddTask( LoadingTask* task )
 {
   bool wasEmpty = false;
 
   {
     // Lock while adding task to the queue
     ConditionalWait::ScopedLock lock( mConditionalWait );
-    wasEmpty = mTasks.Empty();
-    mTasks.PushBack( task );
+    wasEmpty = mLoadQueue.Empty();
+    mLoadQueue.PushBack( task );
   }
 
   if( wasEmpty)
@@ -76,62 +75,83 @@ void LoadQueue::AddTask( LoadingTask* task )
   }
 }
 
-CompleteQueue::CompleteQueue(EventThreadCallback* trigger)
-: mTrigger( trigger )
-{}
-
-CompleteQueue::~CompleteQueue()
-{
-  delete mTrigger;
-}
-
-LoadingTask* CompleteQueue::NextTask()
+LoadingTask* ImageLoadThread::NextCompletedTask()
 {
   // Lock while popping task out from the queue
   Mutex::ScopedLock lock( mMutex );
 
-  if( mTasks.Empty() )
+  if( mCompleteQueue.Empty() )
   {
     return NULL;
   }
 
-  Vector< LoadingTask* >::Iterator next = mTasks.Begin();
+  Vector< LoadingTask* >::Iterator next = mCompleteQueue.Begin();
   LoadingTask* nextTask = *next;
-  mTasks.Erase( next );
+  mCompleteQueue.Erase( next );
 
   return nextTask;
 }
 
-void CompleteQueue::AddTask( LoadingTask* task )
+bool ImageLoadThread::CancelTask( uint32_t loadingTaskId )
 {
-  // Lock while adding task to the queue
-  Mutex::ScopedLock lock( mMutex );
-  mTasks.PushBack( task );
+  // Lock while remove task from the queue
+  ConditionalWait::ScopedLock lock( mConditionalWait );
 
-  // wake up the main thread
-  mTrigger->Trigger();
+  for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); iter++ )
+  {
+    if( (*iter)->id == loadingTaskId )
+    {
+      delete (*iter);
+      mLoadQueue.Erase( iter );
+      return true;
+    }
+  }
+
+  return false;
 }
 
 
-ImageLoadThread::ImageLoadThread( LoadQueue& loadQueue, CompleteQueue& completeQueue )
-: mLoadQueue( loadQueue ),
-  mCompleteQueue( completeQueue )
+void ImageLoadThread::CancelAll()
 {
-}
+  // Lock while remove task from the queue
+  ConditionalWait::ScopedLock lock( mConditionalWait );
 
-ImageLoadThread::~ImageLoadThread()
-{
+  for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); iter++ )
+  {
+    delete (*iter);
+  }
+  mLoadQueue.Clear();
 }
 
-void ImageLoadThread::Run()
+LoadingTask* ImageLoadThread::NextTaskToProcess()
 {
-  while( LoadingTask* task = mLoadQueue.NextTask() )
+  // Lock while popping task out from the queue
+  ConditionalWait::ScopedLock lock( mConditionalWait );
+
+  while( mLoadQueue.Empty() )
   {
-    task->loader.Load();
-    mCompleteQueue.AddTask( task );
+    mConditionalWait.Wait( lock );
   }
+
+  Vector< LoadingTask* >::Iterator next = mLoadQueue.Begin();
+  LoadingTask* nextTask = *next;
+  mLoadQueue.Erase( next );
+
+  return nextTask;
 }
 
+void ImageLoadThread::AddCompletedTask( LoadingTask* task )
+{
+  // Lock while adding task to the queue
+  Mutex::ScopedLock lock( mMutex );
+  mCompleteQueue.PushBack( task );
+
+  // wake up the main thread
+  mTrigger->Trigger();
+}
+
+
+
 } // namespace Internal
 
 } // namespace Toolkit