22#include <com/sun/star/lang/XMultiComponentFactory.hpp>
23#include <com/sun/star/frame/Desktop.hpp>
24#include <com/sun/star/frame/XTerminateListener.hpp>
26#include <osl/thread.hxx>
27#include <osl/conditn.hxx>
46 const TimeValue& rDueTime,
47 const sal_Int64 nRepeatInterval,
48 const sal_Int32 nTaskId);
57typedef std::shared_ptr<TimerTask> SharedTimerTask;
59class TimerTaskComparator
62 bool operator() (
const SharedTimerTask& rpTask1,
const SharedTimerTask& rpTask2)
const
64 return rpTask1->maDueTime.Seconds < rpTask2->maDueTime.Seconds
65 || (rpTask1->maDueTime.Seconds == rpTask2->maDueTime.Seconds
66 && rpTask1->maDueTime.Nanosec < rpTask2->maDueTime.Nanosec);
73 :
public std::enable_shared_from_this<TimerScheduler>,
77 static std::shared_ptr<TimerScheduler> Instance(
78 uno::Reference<uno::XComponentContext>
const& xContext);
79 static SharedTimerTask CreateTimerTask (
81 const TimeValue& rDueTime,
82 const sal_Int64 nRepeatInterval);
84 void ScheduleTask (
const SharedTimerTask& rpTask);
85 void CancelTask (
const sal_Int32 nTaskId);
87 static bool GetCurrentTime (TimeValue& rCurrentTime);
88 static sal_Int64 GetTimeDifference (
89 const TimeValue& rTargetTime,
90 const TimeValue& rCurrentTime);
91 static void ConvertToTimeValue (
92 TimeValue& rTimeValue,
93 const sal_Int64 nTimeDifference);
94 static sal_Int64 ConvertFromTimeValue (
95 const TimeValue& rTimeValue);
97 static void NotifyTermination();
99 static bool HasInstance() {
return mpInstance !=
nullptr; }
109 typedef ::std::set<SharedTimerTask,TimerTaskComparator> TaskContainer;
116 uno::Reference<uno::XComponentContext>
const& xContext);
118 virtual void SAL_CALL
run()
override;
119 virtual void SAL_CALL onTerminated()
override {
mpLateDestroy.reset(); }
122class TerminateListener
123 :
public ::cppu::WeakImplHelper<frame::XTerminateListener>
125 virtual ~TerminateListener()
override
127 assert(!TimerScheduler::HasInstance());
130 virtual void SAL_CALL disposing(lang::EventObject
const&)
override
134 virtual void SAL_CALL queryTermination(lang::EventObject
const&)
override
138 virtual void SAL_CALL notifyTermination(lang::EventObject
const&)
override
140 TimerScheduler::NotifyTermination();
149 const uno::Reference<uno::XComponentContext>& xContext,
151 const sal_Int64 nDelay,
152 const sal_Int64 nInterval)
154 assert(xContext.is());
155 TimeValue aCurrentTime;
156 if (TimerScheduler::GetCurrentTime(aCurrentTime))
159 TimerScheduler::ConvertToTimeValue(
161 TimerScheduler::ConvertFromTimeValue (aCurrentTime) + nDelay);
162 SharedTimerTask pTask (TimerScheduler::CreateTimerTask(rTask, aDueTime, nInterval));
163 TimerScheduler::Instance(xContext)->ScheduleTask(pTask);
164 return pTask->mnTaskId;
172 auto const pInstance(TimerScheduler::Instance(
nullptr));
175 pInstance->CancelTask(nTaskId);
185std::shared_ptr<TimerScheduler> TimerScheduler::Instance(
186 uno::Reference<uno::XComponentContext>
const& xContext)
193 mpInstance.reset(
new TimerScheduler(xContext));
199TimerScheduler::TimerScheduler(
200 uno::Reference<uno::XComponentContext>
const& xContext)
202 uno::Reference<frame::XDesktop>
const xDesktop(
203 frame::Desktop::create(xContext));
204 uno::Reference<frame::XTerminateListener>
const xListener(
205 new TerminateListener);
207 xDesktop->addTerminateListener(xListener);
210SharedTimerTask TimerScheduler::CreateTimerTask (
212 const TimeValue& rDueTime,
213 const sal_Int64 nRepeatInterval)
215 return std::make_shared<TimerTask>(rTask, rDueTime, nRepeatInterval, ++
mnTaskId);
218void TimerScheduler::ScheduleTask (
const SharedTimerTask& rpTask)
222 if (rpTask->mbIsCanceled)
231void TimerScheduler::CancelTask (
const sal_Int32 nTaskId)
239 [nTaskId](
const SharedTimerTask& rxTask) { return rxTask->mnTaskId == nTaskId; });
257void TimerScheduler::NotifyTermination()
266 std::scoped_lock aGuard(pInstance->maTaskContainerMutex);
267 pInstance->maScheduledTasks.clear();
271 std::scoped_lock aGuard(pInstance->maCurrentTaskMutex);
272 if (pInstance->mpCurrentTask)
274 pInstance->mpCurrentTask->mbIsCanceled =
true;
278 pInstance->m_Shutdown.set();
284void SAL_CALL TimerScheduler::run()
286 osl_setThreadName(
"sdext::presenter::TimerScheduler");
291 TimeValue aCurrentTime;
292 if ( ! GetCurrentTime(aCurrentTime))
300 SharedTimerTask pTask;
301 sal_Int64 nDifference = 0;
310 nDifference = GetTimeDifference(
313 if (nDifference <= 0)
329 TimeValue aTimeValue;
330 ConvertToTimeValue(aTimeValue, nDifference);
337 if (pTask->maTask && !pTask->mbIsCanceled)
339 pTask->maTask(aCurrentTime);
342 if (pTask->mnRepeatInterval > 0)
346 ConvertFromTimeValue(pTask->maDueTime)
347 + pTask->mnRepeatInterval);
367bool TimerScheduler::GetCurrentTime (TimeValue& rCurrentTime)
369 TimeValue aSystemTime;
370 if (osl_getSystemTime(&aSystemTime))
371 return osl_getLocalTimeFromSystemTime(&aSystemTime, &rCurrentTime);
375sal_Int64 TimerScheduler::GetTimeDifference (
376 const TimeValue& rTargetTime,
377 const TimeValue& rCurrentTime)
379 return ConvertFromTimeValue(rTargetTime) - ConvertFromTimeValue(rCurrentTime);
382void TimerScheduler::ConvertToTimeValue (
383 TimeValue& rTimeValue,
384 const sal_Int64 nTimeDifference)
386 rTimeValue.Seconds = sal::static_int_cast<sal_Int32>(nTimeDifference / 1000000000L);
387 rTimeValue.Nanosec = sal::static_int_cast<sal_Int32>(nTimeDifference % 1000000000L);
390sal_Int64 TimerScheduler::ConvertFromTimeValue (
391 const TimeValue& rTimeValue)
393 return sal_Int64(rTimeValue.Seconds) * 1000000000L + rTimeValue.Nanosec;
400TimerTask::TimerTask (
402 const TimeValue& rDueTime,
403 const sal_Int64 nRepeatInterval,
404 const sal_Int32 nTaskId)
420 const css::uno::Reference<css::uno::XComponentContext>& rxContext)
422 ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex());
441 mbIsCallbackPending(false),
445 Reference<lang::XMultiComponentFactory>
xFactory =
446 rxContext->getServiceManager();
449 xFactory->createInstanceWithContext(
450 "com.sun.star.awt.AsyncCallback",
465 xComponent->dispose();
471 std::unique_lock aGuard (
maMutex);
488 std::unique_lock aGuard (
maMutex);
490 ListenerContainer::iterator iListener (::std::find(
510 TimeValue aCurrentTime;
511 TimerScheduler::GetCurrentTime(aCurrentTime);
512 oslDateTime aDateTime;
513 osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime);
519 css::uno::Reference<css::awt::XRequestCallback> xRequestCallback;
520 css::uno::Reference<css::awt::XCallback> xCallback;
522 std::unique_lock aGuard (
maMutex);
524 TimeValue aCurrentTime (rCurrentTime);
525 oslDateTime aDateTime;
526 if (osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime))
546 if (xRequestCallback.is() && xCallback.is())
547 xRequestCallback->addCallback(xCallback,
Any());
557 std::unique_lock aGuard (
maMutex);
564 for (
const auto& rxListener : aListenerCopy)
Reference< XComponentContext > m_xContext
::osl::Condition m_Shutdown
std::mutex maCurrentTaskMutex
static std::shared_ptr< TimerScheduler > mpInstance
static std::mutex maInstanceMutex
std::shared_ptr< TimerScheduler > mpLateDestroy
PresenterTimer::Task maTask
TaskContainer maScheduledTasks
SharedTimerTask mpCurrentTask
std::mutex maTaskContainerMutex
const sal_Int64 mnRepeatInterval
css::uno::Reference< css::awt::XRequestCallback > mxRequestCallback
::std::vector< SharedListener > ListenerContainer
virtual void SAL_CALL notify(const css::uno::Any &rUserData) override
virtual ~PresenterClockTimer() override
static oslDateTime GetCurrentTime()
static ::rtl::Reference< PresenterClockTimer > Instance(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
static ::rtl::Reference< PresenterClockTimer > mpInstance
ListenerContainer maListeners
std::shared_ptr< Listener > SharedListener
const css::uno::Reference< css::uno::XComponentContext > m_xContext
PresenterClockTimer(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
void AddListener(const SharedListener &rListener)
void CheckCurrentTime(const TimeValue &rCurrentTime)
void RemoveListener(const SharedListener &rListener)
The timer allows tasks to be scheduled for execution at a specified time in the future.
static void CancelTask(const sal_Int32 nTaskId)
::std::function< void(const TimeValue &)> Task
A task is called with the current time.
static const sal_Int32 NotAValidTaskId
static sal_Int32 ScheduleRepeatedTask(const css::uno::Reference< css::uno::XComponentContext > &xContext, const Task &rTask, const sal_Int64 nFirst, const sal_Int64 nInterval)
Schedule a task to be executed repeatedly.
Reference< XSingleServiceFactory > xFactory
def run(arg=None, arg2=-1)
cppu::WeakComponentImplHelper< css::awt::XCallback > PresenterClockTimerInterfaceBase