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>
44 const TimeValue& rDueTime,
45 const sal_Int64 nRepeatInterval,
46 const sal_Int32 nTaskId);
55 typedef std::shared_ptr<TimerTask> SharedTimerTask;
57 class TimerTaskComparator
60 bool operator() (
const SharedTimerTask& rpTask1,
const SharedTimerTask& rpTask2)
const
62 return rpTask1->maDueTime.Seconds < rpTask2->maDueTime.Seconds
63 || (rpTask1->maDueTime.Seconds == rpTask2->maDueTime.Seconds
64 && rpTask1->maDueTime.Nanosec < rpTask2->maDueTime.Nanosec);
71 :
public std::enable_shared_from_this<TimerScheduler>,
75 static std::shared_ptr<TimerScheduler> Instance(
76 uno::Reference<uno::XComponentContext>
const& xContext);
77 static SharedTimerTask CreateTimerTask (
79 const TimeValue& rDueTime,
80 const sal_Int64 nRepeatInterval);
82 void ScheduleTask (
const SharedTimerTask& rpTask);
83 void CancelTask (
const sal_Int32 nTaskId);
85 static bool GetCurrentTime (TimeValue& rCurrentTime);
86 static sal_Int64 GetTimeDifference (
87 const TimeValue& rTargetTime,
88 const TimeValue& rCurrentTime);
89 static void ConvertToTimeValue (
90 TimeValue& rTimeValue,
91 const sal_Int64 nTimeDifference);
92 static sal_Int64 ConvertFromTimeValue (
93 const TimeValue& rTimeValue);
95 static void NotifyTermination();
97 static bool HasInstance() {
return mpInstance !=
nullptr; }
107 typedef ::std::set<SharedTimerTask,TimerTaskComparator> TaskContainer;
114 uno::Reference<uno::XComponentContext>
const& xContext);
116 virtual void SAL_CALL
run()
override;
117 virtual void SAL_CALL onTerminated()
override { mpLateDestroy.reset(); }
120 class TerminateListener
121 :
public ::cppu::WeakImplHelper<frame::XTerminateListener>
123 virtual ~TerminateListener()
override
125 assert(!TimerScheduler::HasInstance());
128 virtual void SAL_CALL disposing(lang::EventObject
const&)
override
132 virtual void SAL_CALL queryTermination(lang::EventObject
const&)
override
136 virtual void SAL_CALL notifyTermination(lang::EventObject
const&)
override
138 TimerScheduler::NotifyTermination();
147 const uno::Reference<uno::XComponentContext>& xContext,
149 const sal_Int64 nDelay,
150 const sal_Int64 nInterval)
153 TimeValue aCurrentTime;
154 if (TimerScheduler::GetCurrentTime(aCurrentTime))
157 TimerScheduler::ConvertToTimeValue(
159 TimerScheduler::ConvertFromTimeValue (aCurrentTime) + nDelay);
160 SharedTimerTask pTask (TimerScheduler::CreateTimerTask(rTask, aDueTime, nInterval));
161 TimerScheduler::Instance(xContext)->ScheduleTask(pTask);
162 return pTask->mnTaskId;
170 auto const pInstance(TimerScheduler::Instance(
nullptr));
173 pInstance->CancelTask(nTaskId);
183 std::shared_ptr<TimerScheduler> TimerScheduler::Instance(
184 uno::Reference<uno::XComponentContext>
const& xContext)
186 ::osl::MutexGuard aGuard (maInstanceMutex);
187 if (mpInstance ==
nullptr)
191 mpInstance.reset(
new TimerScheduler(xContext));
192 mpInstance->create();
197 TimerScheduler::TimerScheduler(
198 uno::Reference<uno::XComponentContext>
const& xContext)
199 : maTaskContainerMutex(),
201 maCurrentTaskMutex(),
204 uno::Reference<frame::XDesktop>
const xDesktop(
205 frame::Desktop::create(xContext));
206 uno::Reference<frame::XTerminateListener>
const xListener(
207 new TerminateListener);
209 xDesktop->addTerminateListener(xListener);
212 SharedTimerTask TimerScheduler::CreateTimerTask (
214 const TimeValue& rDueTime,
215 const sal_Int64 nRepeatInterval)
217 return std::make_shared<TimerTask>(rTask, rDueTime, nRepeatInterval, ++
mnTaskId);
220 void TimerScheduler::ScheduleTask (
const SharedTimerTask& rpTask)
224 if (rpTask->mbIsCanceled)
228 osl::MutexGuard aTaskGuard (maTaskContainerMutex);
229 maScheduledTasks.insert(rpTask);
233 void TimerScheduler::CancelTask (
const sal_Int32 nTaskId)
239 ::osl::MutexGuard aGuard (maTaskContainerMutex);
240 auto iTask = std::find_if(maScheduledTasks.begin(), maScheduledTasks.end(),
241 [nTaskId](
const SharedTimerTask& rxTask) {
return rxTask->mnTaskId == nTaskId; });
242 if (iTask != maScheduledTasks.end())
243 maScheduledTasks.erase(iTask);
250 ::osl::MutexGuard aGuard (maCurrentTaskMutex);
252 && mpCurrentTask->mnTaskId == nTaskId)
253 mpCurrentTask->mbIsCanceled =
true;
259 void TimerScheduler::NotifyTermination()
261 std::shared_ptr<TimerScheduler>
const pInstance(TimerScheduler::mpInstance);
268 ::osl::MutexGuard aGuard(pInstance->maTaskContainerMutex);
269 pInstance->maScheduledTasks.clear();
273 ::osl::MutexGuard aGuard(pInstance->maCurrentTaskMutex);
274 if (pInstance->mpCurrentTask)
276 pInstance->mpCurrentTask->mbIsCanceled =
true;
280 pInstance->m_Shutdown.set();
286 void SAL_CALL TimerScheduler::run()
288 osl_setThreadName(
"sdext::presenter::TimerScheduler");
293 TimeValue aCurrentTime;
294 if ( ! GetCurrentTime(aCurrentTime))
302 SharedTimerTask pTask;
303 sal_Int64 nDifference = 0;
305 ::osl::MutexGuard aGuard (maTaskContainerMutex);
309 if (maScheduledTasks.empty())
312 nDifference = GetTimeDifference(
315 if (nDifference <= 0)
317 pTask = *maScheduledTasks.begin();
318 maScheduledTasks.erase(maScheduledTasks.begin());
324 ::osl::MutexGuard aGuard (maCurrentTaskMutex);
325 mpCurrentTask = pTask;
331 TimeValue aTimeValue;
332 ConvertToTimeValue(aTimeValue, nDifference);
334 m_Shutdown.wait(&aTimeValue);
339 if (pTask->maTask && !pTask->mbIsCanceled)
341 pTask->maTask(aCurrentTime);
344 if (pTask->mnRepeatInterval > 0)
348 ConvertFromTimeValue(pTask->maDueTime)
349 + pTask->mnRepeatInterval);
358 ::osl::MutexGuard aGuard (maCurrentTaskMutex);
359 mpCurrentTask.reset();
364 osl::Guard< osl::Mutex > aInstance( maInstanceMutex );
369 bool TimerScheduler::GetCurrentTime (TimeValue& rCurrentTime)
371 TimeValue aSystemTime;
372 if (osl_getSystemTime(&aSystemTime))
373 return osl_getLocalTimeFromSystemTime(&aSystemTime, &rCurrentTime);
377 sal_Int64 TimerScheduler::GetTimeDifference (
378 const TimeValue& rTargetTime,
379 const TimeValue& rCurrentTime)
381 return ConvertFromTimeValue(rTargetTime) - ConvertFromTimeValue(rCurrentTime);
384 void TimerScheduler::ConvertToTimeValue (
385 TimeValue& rTimeValue,
386 const sal_Int64 nTimeDifference)
388 rTimeValue.Seconds = sal::static_int_cast<sal_Int32>(nTimeDifference / 1000000000L);
389 rTimeValue.Nanosec = sal::static_int_cast<sal_Int32>(nTimeDifference % 1000000000L);
392 sal_Int64 TimerScheduler::ConvertFromTimeValue (
393 const TimeValue& rTimeValue)
395 return sal_Int64(rTimeValue.Seconds) * 1000000000L + rTimeValue.Nanosec;
402 TimerTask::TimerTask (
404 const TimeValue& rDueTime,
405 const sal_Int64 nRepeatInterval,
406 const sal_Int32 nTaskId)
422 const css::uno::Reference<css::uno::XComponentContext>& rxContext)
424 ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex());
444 mbIsCallbackPending(false),
449 Reference<lang::XMultiComponentFactory>
xFactory =
450 rxContext->getServiceManager();
453 xFactory->createInstanceWithContext(
454 "com.sun.star.awt.AsyncCallback",
469 xComponent->dispose();
475 osl::MutexGuard aGuard (
maMutex);
492 osl::MutexGuard aGuard (
maMutex);
494 ListenerContainer::iterator iListener (::std::find(
508 mpInstance =
nullptr;
514 TimeValue aCurrentTime;
515 TimerScheduler::GetCurrentTime(aCurrentTime);
516 oslDateTime aDateTime;
517 osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime);
523 css::uno::Reference<css::awt::XRequestCallback> xRequestCallback;
524 css::uno::Reference<css::awt::XCallback> xCallback;
526 osl::MutexGuard aGuard (
maMutex);
528 TimeValue aCurrentTime (rCurrentTime);
529 oslDateTime aDateTime;
530 if (osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime))
550 if (xRequestCallback.is() && xCallback.is())
551 xRequestCallback->addCallback(xCallback,
Any());
561 osl::MutexGuard aGuard (
maMutex);
568 for (
const auto& rxListener : aListenerCopy)
TaskContainer maScheduledTasks
SharedTimerTask mpCurrentTask
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.
void AddListener(const SharedListener &rListener)
::osl::Mutex maInstanceMutex
void CheckCurrentTime(const TimeValue &rCurrentTime)
virtual void SAL_CALL notify(const css::uno::Any &rUserData) override
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
static::rtl::Reference< PresenterClockTimer > Instance(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
virtual ~PresenterClockTimer() override
::osl::Mutex maCurrentTaskMutex
const css::uno::Reference< css::uno::XComponentContext > m_xContext
PresenterClockTimer(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
static void CancelTask(const sal_Int32 nTaskId)
std::shared_ptr< TimerScheduler > mpLateDestroy
PresenterTimer::Task maTask
ListenerContainer maListeners
::osl::Mutex maTaskContainerMutex
const sal_Int64 mnRepeatInterval
static oslDateTime GetCurrentTime()
::osl::Condition m_Shutdown
css::uno::Reference< css::awt::XRequestCallback > mxRequestCallback
static std::shared_ptr< TimerScheduler > mpInstance
std::shared_ptr< Listener > SharedListener
::std::vector< SharedListener > ListenerContainer
void RemoveListener(const SharedListener &rListener)
static const sal_Int32 NotAValidTaskId
cppu::WeakComponentImplHelper< css::awt::XCallback > PresenterClockTimerInterfaceBase
Reference< XSingleServiceFactory > xFactory
The timer allows tasks to be scheduled for execution at a specified time in the future.
::std::function< void(const TimeValue &)> Task
A task is called with the current time.
static::rtl::Reference< PresenterClockTimer > mpInstance
const uno::Reference< uno::XComponentContext > m_xContext