2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/system/common/timer-impl.h>
20 #include "extern-definitions.h"
22 namespace Dali::Internal::Adaptor
27 * Struct to hide away macOS implementation details
31 Impl(Timer *parent, unsigned int milliSec)
32 : mTimer(CreateTimer(parent, milliSec)) {}
36 static void TimerProc(CFRunLoopTimerRef timer, void *info);
40 void Reset(Timer *parent, unsigned int milliSec);
42 unsigned int GetInterval() const noexcept
44 return CFRunLoopTimerGetInterval(mTimer.get()) * 1000.0;
47 bool IsRunning() const noexcept
49 return CFRunLoopTimerIsValid(mTimer.get());
53 CFRef<CFRunLoopTimerRef> CreateTimer(Timer *parent, unsigned int milliSec);
55 CFRef<CFRunLoopTimerRef> mTimer;
58 void Timer::Impl::TimerProc(CFRunLoopTimerRef timer, void *info)
60 auto *pTimer = static_cast<Timer*>(info);
64 void Timer::Impl::Start()
68 auto runLoop = CFRunLoopGetMain();
69 CFRunLoopAddTimer(runLoop, mTimer.get(), kCFRunLoopDefaultMode);
73 void Timer::Impl::Stop()
77 CFRunLoopTimerContext context;
78 CFRunLoopTimerGetContext(mTimer.get(), &context);
79 const auto interval = CFRunLoopTimerGetInterval(mTimer.get());
80 CFRunLoopTimerInvalidate(mTimer.get());
82 // After we invalidate the timer, we can't reuse it, so we create
83 // a new timer for case the user calls Start again
84 const auto fireDate = CFAbsoluteTimeGetCurrent() + interval;
85 mTimer.reset(CFRunLoopTimerCreate(
97 void Timer::Impl::Reset(Timer *parent, unsigned int milliSec)
100 mTimer = CreateTimer(parent, milliSec);
104 CFRef<CFRunLoopTimerRef>
105 Timer::Impl::CreateTimer(Timer *parent, unsigned int milliSec)
107 const auto interval = static_cast<CFAbsoluteTime>(milliSec) / 1000;
108 const auto fireDate = CFAbsoluteTimeGetCurrent() + interval;
109 CFRunLoopTimerContext context =
117 return MakeRef(CFRunLoopTimerCreate(
127 TimerPtr Timer::New( unsigned int milliSec )
129 return new Timer( milliSec );
132 Timer::Timer( unsigned int milliSec )
133 : mImpl(new Impl(this, milliSec))
166 void Timer::SetInterval( unsigned int interval, bool restart )
168 mImpl->Reset(this, interval);
171 unsigned int Timer::GetInterval() const
173 return mImpl->GetInterval();
178 // Guard against destruction during signal emission
179 Dali::Timer handle( this );
181 bool retVal( false );
183 // Override with new signal if used
184 if( !mTickSignal.Empty() )
186 retVal = mTickSignal.Emit();
188 // Timer stops if return value is false
195 retVal = true; // continue emission
198 else // no callbacks registered
200 // periodic timer is started but nobody listens, continue
207 Dali::Timer::TimerSignalType& Timer::TickSignal()
212 bool Timer::IsRunning() const
214 return mImpl->IsRunning();
217 } // namespace Dali::Internal::Adaptor