Merge "Update README for dali-swig" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / image-loader / image-load-thread.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "image-load-thread.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/adaptor-framework/image-loading.h>
23
24 namespace Dali
25 {
26
27 namespace Toolkit
28 {
29
30 namespace Internal
31 {
32
33 LoadingTask::LoadingTask( uint32_t id, const std::string& url, ImageDimensions dimensions,
34                           FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection )
35 : pixelData(),
36   url( url ),
37   id( id ),
38   dimensions( dimensions ),
39   fittingMode( fittingMode ),
40   samplingMode( samplingMode ),
41   orientationCorrection( orientationCorrection )
42 {
43 }
44
45 void LoadingTask::Load()
46 {
47   pixelData = Dali::LoadImageFromFile( url, dimensions, fittingMode, samplingMode, orientationCorrection );
48 }
49
50
51 ImageLoadThread::ImageLoadThread( EventThreadCallback* trigger )
52 : mTrigger( trigger )
53 {
54 }
55
56 ImageLoadThread::~ImageLoadThread()
57 {
58   // add an empty task would stop the thread from conditional wait.
59   AddTask( NULL );
60   // stop the thread
61   Join();
62
63   delete mTrigger;
64 }
65
66 void ImageLoadThread::Run()
67 {
68   while( LoadingTask* task = NextTaskToProcess() )
69   {
70     task->Load();
71     AddCompletedTask( task );
72   }
73 }
74
75 void ImageLoadThread::AddTask( LoadingTask* task )
76 {
77   bool wasEmpty = false;
78
79   {
80     // Lock while adding task to the queue
81     ConditionalWait::ScopedLock lock( mConditionalWait );
82     wasEmpty = mLoadQueue.Empty();
83     mLoadQueue.PushBack( task );
84   }
85
86   if( wasEmpty )
87   {
88     // wake up the image loading thread
89     mConditionalWait.Notify();
90   }
91 }
92
93 LoadingTask* ImageLoadThread::NextCompletedTask()
94 {
95   // Lock while popping task out from the queue
96   Mutex::ScopedLock lock( mMutex );
97
98   if( mCompleteQueue.Empty() )
99   {
100     return NULL;
101   }
102
103   Vector< LoadingTask* >::Iterator next = mCompleteQueue.Begin();
104   LoadingTask* nextTask = *next;
105   mCompleteQueue.Erase( next );
106
107   return nextTask;
108 }
109
110 bool ImageLoadThread::CancelTask( uint32_t loadingTaskId )
111 {
112   // Lock while remove task from the queue
113   ConditionalWait::ScopedLock lock( mConditionalWait );
114
115   for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter )
116   {
117     if( (*iter)->id == loadingTaskId )
118     {
119       delete (*iter);
120       mLoadQueue.Erase( iter );
121       return true;
122     }
123   }
124
125   return false;
126 }
127
128
129 void ImageLoadThread::CancelAll()
130 {
131   // Lock while remove task from the queue
132   ConditionalWait::ScopedLock lock( mConditionalWait );
133
134   for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter )
135   {
136     delete ( *iter );
137   }
138   mLoadQueue.Clear();
139 }
140
141 LoadingTask* ImageLoadThread::NextTaskToProcess()
142 {
143   // Lock while popping task out from the queue
144   ConditionalWait::ScopedLock lock( mConditionalWait );
145
146   while( mLoadQueue.Empty() )
147   {
148     mConditionalWait.Wait( lock );
149   }
150
151   Vector< LoadingTask* >::Iterator next = mLoadQueue.Begin();
152   LoadingTask* nextTask = *next;
153   mLoadQueue.Erase( next );
154
155   return nextTask;
156 }
157
158 void ImageLoadThread::AddCompletedTask( LoadingTask* task )
159 {
160   // Lock while adding task to the queue
161   Mutex::ScopedLock lock( mMutex );
162   mCompleteQueue.PushBack( task );
163
164   // wake up the main thread
165   mTrigger->Trigger();
166 }
167
168 } // namespace Internal
169
170 } // namespace Toolkit
171
172 } // namespace Dali