Avoid debug assert when Timer is destroyed
[platform/core/uifw/dali-adaptor.git] / adaptors / common / event-loop / ecore / ecore-timer-impl.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 "timer-impl.h"
20
21 // INTERNAL INCLUDES
22 #include <adaptor-impl.h>
23
24 // EXTERNAL INCLUDES
25 #include <dali/public-api/common/dali-common.h>
26
27 // Ecore is littered with C style cast
28 #pragma GCC diagnostic push
29 #pragma GCC diagnostic ignored "-Wold-style-cast"
30 #include <Ecore.h>
31
32 namespace Dali
33 {
34
35 namespace Internal
36 {
37
38 namespace Adaptor
39 {
40
41 // LOCAL STUFF
42 namespace
43 {
44 Eina_Bool TimerSourceFunc (void *data)
45 {
46   Timer* timer = static_cast<Timer*>(data);
47
48   bool keepRunning = timer->Tick();
49
50   return keepRunning ? EINA_TRUE : EINA_FALSE;
51 }
52 } // unnamed namespace
53
54 /**
55  * Struct to hide away Ecore implementation details
56  */
57 struct Timer::Impl
58 {
59   Impl( unsigned int milliSec )
60   : mId(NULL),
61     mInterval(milliSec)
62   {
63   }
64
65   Ecore_Timer * mId;
66   unsigned int mInterval;
67 };
68
69 TimerPtr Timer::New( unsigned int milliSec )
70 {
71   TimerPtr timer( new Timer( milliSec ) );
72   return timer;
73 }
74
75 Timer::Timer( unsigned int milliSec )
76 : mImpl(new Impl(milliSec))
77 {
78 }
79
80 Timer::~Timer()
81 {
82   ResetTimerData();
83   delete mImpl;
84 }
85
86 void Timer::Start()
87 {
88   // Timer should be used in the event thread
89   DALI_ASSERT_DEBUG( Adaptor::IsAvailable() );
90
91   if(mImpl->mId != NULL)
92   {
93     Stop();
94   }
95   mImpl->mId = ecore_timer_add( (double)mImpl->mInterval/1000.0f, (Ecore_Task_Cb)TimerSourceFunc, this );
96 }
97
98 void Timer::Stop()
99 {
100   // Timer should be used in the event thread
101   DALI_ASSERT_DEBUG( Adaptor::IsAvailable() );
102
103   ResetTimerData();
104 }
105
106 void Timer::SetInterval( unsigned int interval )
107 {
108   // stop existing timer
109   Stop();
110   mImpl->mInterval = interval;
111   // start new tick
112   Start();
113 }
114
115 unsigned int Timer::GetInterval() const
116 {
117   return mImpl->mInterval;
118 }
119
120 bool Timer::Tick()
121 {
122   // Guard against destruction during signal emission
123   Dali::Timer handle( this );
124
125   bool retVal( false );
126
127   // Override with new signal if used
128   if( !mTickSignal.Empty() )
129   {
130     retVal = mTickSignal.Emit();
131
132     // Timer stops if return value is false
133     if (retVal == false)
134     {
135       Stop();
136     }
137     else
138     {
139       retVal = true;   // continue emission
140     }
141   }
142   else // no callbacks registered
143   {
144     // periodic timer is started but nobody listens, continue
145     retVal = true;
146   }
147
148   return retVal;
149 }
150
151 Dali::Timer::TimerSignalType& Timer::TickSignal()
152 {
153   return mTickSignal;
154 }
155
156 void Timer::ResetTimerData()
157 {
158   if (mImpl->mId != NULL)
159   {
160     ecore_timer_del(mImpl->mId);
161     mImpl->mId = NULL;
162   }
163 }
164
165 bool Timer::IsRunning() const
166 {
167   return mImpl->mId != NULL;
168 }
169
170 } // namespace Adaptor
171
172 } // namespace Internal
173
174 } // namespace Dali
175
176 #pragma GCC diagnostic pop