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