7e0a181dd36fdcc6dec3a8541bcd8841cbd76b15
[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 VisualUrl& url, ImageDimensions dimensions,
34                           FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection )
35 : pixelBuffer(),
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   if( url.IsLocalResource() )
48   {
49     pixelBuffer = Dali::LoadImageFromFile( url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection );
50   }
51   else
52   {
53     pixelBuffer = Dali::DownloadImageSynchronously ( url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection );
54   }
55 }
56
57
58 ImageLoadThread::ImageLoadThread( EventThreadCallback* trigger )
59 : mTrigger( trigger )
60 {
61 }
62
63 ImageLoadThread::~ImageLoadThread()
64 {
65   // add an empty task would stop the thread from conditional wait.
66   AddTask( NULL );
67   // stop the thread
68   Join();
69
70   delete mTrigger;
71 }
72
73 void ImageLoadThread::Run()
74 {
75   while( LoadingTask* task = NextTaskToProcess() )
76   {
77     task->Load();
78     AddCompletedTask( task );
79   }
80 }
81
82 void ImageLoadThread::AddTask( LoadingTask* task )
83 {
84   bool wasEmpty = false;
85
86   {
87     // Lock while adding task to the queue
88     ConditionalWait::ScopedLock lock( mConditionalWait );
89     wasEmpty = mLoadQueue.Empty();
90     mLoadQueue.PushBack( task );
91   }
92
93   if( wasEmpty )
94   {
95     // wake up the image loading thread
96     mConditionalWait.Notify();
97   }
98 }
99
100 LoadingTask* ImageLoadThread::NextCompletedTask()
101 {
102   // Lock while popping task out from the queue
103   Mutex::ScopedLock lock( mMutex );
104
105   if( mCompleteQueue.Empty() )
106   {
107     return NULL;
108   }
109
110   Vector< LoadingTask* >::Iterator next = mCompleteQueue.Begin();
111   LoadingTask* nextTask = *next;
112   mCompleteQueue.Erase( next );
113
114   return nextTask;
115 }
116
117 bool ImageLoadThread::CancelTask( uint32_t loadingTaskId )
118 {
119   // Lock while remove task from the queue
120   ConditionalWait::ScopedLock lock( mConditionalWait );
121
122   for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter )
123   {
124     if( (*iter)->id == loadingTaskId )
125     {
126       delete (*iter);
127       mLoadQueue.Erase( iter );
128       return true;
129     }
130   }
131
132   return false;
133 }
134
135
136 void ImageLoadThread::CancelAll()
137 {
138   // Lock while remove task from the queue
139   ConditionalWait::ScopedLock lock( mConditionalWait );
140
141   for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter )
142   {
143     delete ( *iter );
144   }
145   mLoadQueue.Clear();
146 }
147
148 LoadingTask* ImageLoadThread::NextTaskToProcess()
149 {
150   // Lock while popping task out from the queue
151   ConditionalWait::ScopedLock lock( mConditionalWait );
152
153   while( mLoadQueue.Empty() )
154   {
155     mConditionalWait.Wait( lock );
156   }
157
158   Vector< LoadingTask* >::Iterator next = mLoadQueue.Begin();
159   LoadingTask* nextTask = *next;
160   mLoadQueue.Erase( next );
161
162   return nextTask;
163 }
164
165 void ImageLoadThread::AddCompletedTask( LoadingTask* task )
166 {
167   // Lock while adding task to the queue
168   Mutex::ScopedLock lock( mMutex );
169   mCompleteQueue.PushBack( task );
170
171   // wake up the main thread
172   mTrigger->Trigger();
173 }
174
175 } // namespace Internal
176
177 } // namespace Toolkit
178
179 } // namespace Dali