Create LibUV / X11 profile
[platform/core/uifw/dali-adaptor.git] / dali / internal / system / libuv / timer-impl-libuv.cpp
1 /*
2  * Copyright (c) 2014 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 <dali/internal/system/common/timer-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 // EXTERNAL INCLUDES
25 #include <uv.h>
26
27 namespace Dali
28 {
29 namespace Internal
30 {
31 namespace Adaptor
32 {
33 extern uv_loop_t* GetUVMainLoop();
34
35 namespace
36 {
37 void TimerSourceFunc(uv_timer_t* handle)
38 {
39   Timer* timer = static_cast<Timer*>(handle->data);
40
41   bool keepRunning = timer->Tick();
42   if(!keepRunning)
43   {
44     timer->Stop();
45   }
46 }
47 void FreeHandleCallback(uv_handle_t* handle)
48 {
49   delete handle;
50 }
51
52 } // unnamed namespace
53
54 /**
55  * Struct to hide away libuv implementation details
56  */
57 struct Timer::Impl
58 {
59   Impl(unsigned int milliSec)
60   : mTimerHandle(NULL),
61     mInterval(milliSec),
62     mRunning(false)
63   {
64   }
65
66   ~Impl()
67   {
68     // the handle will still be alive for a short period after calling uv_close
69     // set the data to NULL to avoid a dangling pointer
70     mTimerHandle->data = NULL;
71
72     uv_close(reinterpret_cast<uv_handle_t*>(mTimerHandle), FreeHandleCallback);
73   }
74
75   bool Running()
76   {
77     return mRunning;
78   }
79
80   void Start(void* internalTimerPtr)
81   {
82     Stop(); // make sure we stop first if its currently running
83
84     if(!mTimerHandle)
85     {
86       // heap allocate the handle as its lifetime will be longer than TimerImpl
87       mTimerHandle = new uv_timer_t;
88
89       // initialize the handle
90       uv_timer_init(GetUVMainLoop(), mTimerHandle);
91     }
92
93     mRunning = true;
94
95     mTimerHandle->data = internalTimerPtr;
96
97     uv_timer_start(mTimerHandle, TimerSourceFunc, mInterval, mInterval);
98   }
99
100   void Stop()
101   {
102     if(mRunning)
103     {
104       mTimerHandle->data = NULL;
105       uv_timer_stop(mTimerHandle);
106       mRunning = false;
107     }
108   }
109
110   void Pause()
111   {
112     uv_timer_stop(mTimerHandle);
113   }
114
115   void Resume()
116   {
117     uv_timer_start(mTimerHandle, TimerSourceFunc, mInterval, mInterval);
118   }
119
120   uv_timer_t*  mTimerHandle;
121   unsigned int mInterval;
122   bool         mRunning;
123 };
124
125 TimerPtr Timer::New(unsigned int milliSec)
126 {
127   DALI_LOG_ERROR(" new timer\n");
128   TimerPtr timer(new Timer(milliSec));
129   return timer;
130 }
131
132 Timer::Timer(unsigned int milliSec)
133 : mImpl(new Impl(milliSec))
134 {
135 }
136
137 Timer::~Timer()
138 {
139   // stop timers
140   Stop();
141
142   delete mImpl;
143 }
144
145 void Timer::Start()
146 {
147   mImpl->Start(this);
148 }
149
150 void Timer::Stop()
151 {
152   mImpl->Stop();
153 }
154
155 void Timer::Pause()
156 {
157   mImpl->Pause();
158 }
159
160 void Timer::Resume()
161 {
162   mImpl->Resume();
163 }
164
165 void Timer::SetInterval(unsigned int interval, bool restart)
166 {
167   // stop existing timer
168   Stop();
169
170   mImpl->mInterval = interval;
171
172   if(restart)
173   {
174     // start new tick
175     Start();
176   }
177 }
178
179 unsigned int Timer::GetInterval() const
180 {
181   return mImpl->mInterval;
182 }
183
184 bool Timer::Tick()
185 {
186   // Guard against destruction during signal emission
187   Dali::Timer handle(this);
188
189   bool retVal(false);
190
191   // Override with new signal if used
192   if(!mTickSignal.Empty())
193   {
194     retVal = mTickSignal.Emit();
195
196     // Timer stops if return value is false
197     if(retVal == false)
198     {
199       Stop();
200     }
201     else
202     {
203       retVal = true; // continue emission
204     }
205   }
206   else // no callbacks registered
207   {
208     // periodic timer is started but nobody listens, continue
209     retVal = true;
210   }
211
212   return retVal;
213 }
214
215 Dali::Timer::TimerSignalType& Timer::TickSignal()
216 {
217   return mTickSignal;
218 }
219
220 bool Timer::IsRunning() const
221 {
222   return mImpl->mRunning;
223 }
224
225 } // namespace Adaptor
226
227 } // namespace Internal
228
229 } // namespace Dali