Set the thread name (image/svg)
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / image-loader / image-load-thread.cpp
1 /*
2  * Copyright (c) 2017 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 #include <dali/integration-api/adaptors/adaptor.h>
24 #include <dali/devel-api/adaptor-framework/thread-settings.h>
25
26 namespace Dali
27 {
28
29 namespace Toolkit
30 {
31
32 namespace Internal
33 {
34
35 LoadingTask::LoadingTask( uint32_t id, const VisualUrl& url, ImageDimensions dimensions,
36                           FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection )
37 : pixelBuffer(),
38   url( url ),
39   id( id ),
40   dimensions( dimensions ),
41   fittingMode( fittingMode ),
42   samplingMode( samplingMode ),
43   orientationCorrection( orientationCorrection )
44 {
45 }
46
47 void LoadingTask::Load()
48 {
49   if( url.IsLocalResource() )
50   {
51     pixelBuffer = Dali::LoadImageFromFile( url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection );
52   }
53   else
54   {
55     pixelBuffer = Dali::DownloadImageSynchronously ( url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection );
56   }
57 }
58
59
60 ImageLoadThread::ImageLoadThread( EventThreadCallback* trigger )
61 : mTrigger( trigger ),
62   mLogFactory( Dali::Adaptor::Get().GetLogFactory() )
63 {
64 }
65
66 ImageLoadThread::~ImageLoadThread()
67 {
68   // add an empty task would stop the thread from conditional wait.
69   AddTask( NULL );
70   // stop the thread
71   Join();
72
73   delete mTrigger;
74 }
75
76 void ImageLoadThread::Run()
77 {
78   SetThreadName( "ImageLoadThread" );
79   mLogFactory.InstallLogFunction();
80
81   while( LoadingTask* task = NextTaskToProcess() )
82   {
83     task->Load();
84     AddCompletedTask( task );
85   }
86 }
87
88 void ImageLoadThread::AddTask( LoadingTask* task )
89 {
90   bool wasEmpty = false;
91
92   {
93     // Lock while adding task to the queue
94     ConditionalWait::ScopedLock lock( mConditionalWait );
95     wasEmpty = mLoadQueue.Empty();
96     mLoadQueue.PushBack( task );
97   }
98
99   if( wasEmpty )
100   {
101     // wake up the image loading thread
102     mConditionalWait.Notify();
103   }
104 }
105
106 LoadingTask* ImageLoadThread::NextCompletedTask()
107 {
108   // Lock while popping task out from the queue
109   Mutex::ScopedLock lock( mMutex );
110
111   if( mCompleteQueue.Empty() )
112   {
113     return NULL;
114   }
115
116   Vector< LoadingTask* >::Iterator next = mCompleteQueue.Begin();
117   LoadingTask* nextTask = *next;
118   mCompleteQueue.Erase( next );
119
120   return nextTask;
121 }
122
123 bool ImageLoadThread::CancelTask( uint32_t loadingTaskId )
124 {
125   // Lock while remove task from the queue
126   ConditionalWait::ScopedLock lock( mConditionalWait );
127
128   for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter )
129   {
130     if( (*iter)->id == loadingTaskId )
131     {
132       delete (*iter);
133       mLoadQueue.Erase( iter );
134       return true;
135     }
136   }
137
138   return false;
139 }
140
141
142 void ImageLoadThread::CancelAll()
143 {
144   // Lock while remove task from the queue
145   ConditionalWait::ScopedLock lock( mConditionalWait );
146
147   for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter )
148   {
149     delete ( *iter );
150   }
151   mLoadQueue.Clear();
152 }
153
154 LoadingTask* ImageLoadThread::NextTaskToProcess()
155 {
156   // Lock while popping task out from the queue
157   ConditionalWait::ScopedLock lock( mConditionalWait );
158
159   while( mLoadQueue.Empty() )
160   {
161     mConditionalWait.Wait( lock );
162   }
163
164   Vector< LoadingTask* >::Iterator next = mLoadQueue.Begin();
165   LoadingTask* nextTask = *next;
166   mLoadQueue.Erase( next );
167
168   return nextTask;
169 }
170
171 void ImageLoadThread::AddCompletedTask( LoadingTask* task )
172 {
173   // Lock while adding task to the queue
174   Mutex::ScopedLock lock( mMutex );
175   mCompleteQueue.PushBack( task );
176
177   // wake up the main thread
178   mTrigger->Trigger();
179 }
180
181 } // namespace Internal
182
183 } // namespace Toolkit
184
185 } // namespace Dali