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>
45 const TimeValue& rDueTime,
46 const sal_Int64 nRepeatInterval,
47 const sal_Int32 nTaskId);
56 typedef std::shared_ptr<TimerTask> SharedTimerTask;
58 class TimerTaskComparator
61 bool operator() (
const SharedTimerTask& rpTask1,
const SharedTimerTask& rpTask2)
const
63 return rpTask1->maDueTime.Seconds < rpTask2->maDueTime.Seconds
64 || (rpTask1->maDueTime.Seconds == rpTask2->maDueTime.Seconds
65 && rpTask1->maDueTime.Nanosec < rpTask2->maDueTime.Nanosec);
72 :
public std::enable_shared_from_this<TimerScheduler>,
76 static std::shared_ptr<TimerScheduler> Instance(
77 uno::Reference<uno::XComponentContext>
const& xContext);
78 static SharedTimerTask CreateTimerTask (
80 const TimeValue& rDueTime,
81 const sal_Int64 nRepeatInterval);
83 void ScheduleTask (
const SharedTimerTask& rpTask);
84 void CancelTask (
const sal_Int32 nTaskId);
86 static bool GetCurrentTime (TimeValue& rCurrentTime);
87 static sal_Int64 GetTimeDifference (
88 const TimeValue& rTargetTime,
89 const TimeValue& rCurrentTime);
90 static void ConvertToTimeValue (
91 TimeValue& rTimeValue,
92 const sal_Int64 nTimeDifference);
93 static sal_Int64 ConvertFromTimeValue (
94 const TimeValue& rTimeValue);
96 static void NotifyTermination();
98 static bool HasInstance() {
return mpInstance !=
nullptr; }
108 typedef ::std::set<SharedTimerTask,TimerTaskComparator> TaskContainer;
115 uno::Reference<uno::XComponentContext>
const& xContext);
117 virtual void SAL_CALL
run()
override;
118 virtual void SAL_CALL onTerminated()
override { mpLateDestroy.reset(); }
121 class TerminateListener
122 :
public ::cppu::WeakImplHelper<frame::XTerminateListener>
124 virtual ~TerminateListener()
override
126 assert(!TimerScheduler::HasInstance());
129 virtual void SAL_CALL disposing(lang::EventObject
const&)
override
133 virtual void SAL_CALL queryTermination(lang::EventObject
const&)
override
137 virtual void SAL_CALL notifyTermination(lang::EventObject
const&)
override
139 TimerScheduler::NotifyTermination();
148 const uno::Reference<uno::XComponentContext>& xContext,
150 const sal_Int64 nDelay,
151 const sal_Int64 nInterval)
153 assert(xContext.is());
154 TimeValue aCurrentTime;
155 if (TimerScheduler::GetCurrentTime(aCurrentTime))
158 TimerScheduler::ConvertToTimeValue(
160 TimerScheduler::ConvertFromTimeValue (aCurrentTime) + nDelay);
161 SharedTimerTask pTask (TimerScheduler::CreateTimerTask(rTask, aDueTime, nInterval));
162 TimerScheduler::Instance(xContext)->ScheduleTask(pTask);
163 return pTask->mnTaskId;
171 auto const pInstance(TimerScheduler::Instance(
nullptr));
174 pInstance->CancelTask(nTaskId);
184 std::shared_ptr<TimerScheduler> TimerScheduler::Instance(
185 uno::Reference<uno::XComponentContext>
const& xContext)
187 std::scoped_lock aGuard (maInstanceMutex);
188 if (mpInstance ==
nullptr)
192 mpInstance.reset(
new TimerScheduler(xContext));
193 mpInstance->create();
198 TimerScheduler::TimerScheduler(
199 uno::Reference<uno::XComponentContext>
const& xContext)
201 uno::Reference<frame::XDesktop>
const xDesktop(
202 frame::Desktop::create(xContext));
203 uno::Reference<frame::XTerminateListener>
const xListener(
204 new TerminateListener);
206 xDesktop->addTerminateListener(xListener);
209 SharedTimerTask TimerScheduler::CreateTimerTask (
211 const TimeValue& rDueTime,
212 const sal_Int64 nRepeatInterval)
214 return std::make_shared<TimerTask>(rTask, rDueTime, nRepeatInterval, ++
mnTaskId);
217 void TimerScheduler::ScheduleTask (
const SharedTimerTask& rpTask)
221 if (rpTask->mbIsCanceled)
225 std::scoped_lock aTaskGuard (maTaskContainerMutex);
226 maScheduledTasks.insert(rpTask);
230 void TimerScheduler::CancelTask (
const sal_Int32 nTaskId)
236 std::scoped_lock aGuard (maTaskContainerMutex);
237 auto iTask = std::find_if(maScheduledTasks.begin(), maScheduledTasks.end(),
238 [nTaskId](
const SharedTimerTask& rxTask) {
return rxTask->mnTaskId == nTaskId; });
239 if (iTask != maScheduledTasks.end())
240 maScheduledTasks.erase(iTask);
247 std::scoped_lock aGuard (maCurrentTaskMutex);
249 && mpCurrentTask->mnTaskId == nTaskId)
250 mpCurrentTask->mbIsCanceled =
true;
256 void TimerScheduler::NotifyTermination()
258 std::shared_ptr<TimerScheduler>
const pInstance(TimerScheduler::mpInstance);
265 std::scoped_lock aGuard(pInstance->maTaskContainerMutex);
266 pInstance->maScheduledTasks.clear();
270 std::scoped_lock aGuard(pInstance->maCurrentTaskMutex);
271 if (pInstance->mpCurrentTask)
273 pInstance->mpCurrentTask->mbIsCanceled =
true;
277 pInstance->m_Shutdown.set();
283 void SAL_CALL TimerScheduler::run()
285 osl_setThreadName(
"sdext::presenter::TimerScheduler");
290 TimeValue aCurrentTime;
291 if ( ! GetCurrentTime(aCurrentTime))
299 SharedTimerTask pTask;
300 sal_Int64 nDifference = 0;
302 std::scoped_lock aGuard (maTaskContainerMutex);
306 if (maScheduledTasks.empty())
309 nDifference = GetTimeDifference(
312 if (nDifference <= 0)
314 pTask = *maScheduledTasks.begin();
315 maScheduledTasks.erase(maScheduledTasks.begin());
321 std::scoped_lock aGuard (maCurrentTaskMutex);
322 mpCurrentTask = pTask;
328 TimeValue aTimeValue;
329 ConvertToTimeValue(aTimeValue, nDifference);
331 m_Shutdown.wait(&aTimeValue);
336 if (pTask->maTask && !pTask->mbIsCanceled)
338 pTask->maTask(aCurrentTime);
341 if (pTask->mnRepeatInterval > 0)
345 ConvertFromTimeValue(pTask->maDueTime)
346 + pTask->mnRepeatInterval);
355 std::scoped_lock aGuard (maCurrentTaskMutex);
356 mpCurrentTask.reset();
361 std::scoped_lock aInstance( maInstanceMutex );
366 bool TimerScheduler::GetCurrentTime (TimeValue& rCurrentTime)
368 TimeValue aSystemTime;
369 if (osl_getSystemTime(&aSystemTime))
370 return osl_getLocalTimeFromSystemTime(&aSystemTime, &rCurrentTime);
374 sal_Int64 TimerScheduler::GetTimeDifference (
375 const TimeValue& rTargetTime,
376 const TimeValue& rCurrentTime)
378 return ConvertFromTimeValue(rTargetTime) - ConvertFromTimeValue(rCurrentTime);
381 void TimerScheduler::ConvertToTimeValue (
382 TimeValue& rTimeValue,
383 const sal_Int64 nTimeDifference)
385 rTimeValue.Seconds = sal::static_int_cast<sal_Int32>(nTimeDifference / 1000000000L);
386 rTimeValue.Nanosec = sal::static_int_cast<sal_Int32>(nTimeDifference % 1000000000L);
389 sal_Int64 TimerScheduler::ConvertFromTimeValue (
390 const TimeValue& rTimeValue)
392 return sal_Int64(rTimeValue.Seconds) * 1000000000L + rTimeValue.Nanosec;
399 TimerTask::TimerTask (
401 const TimeValue& rDueTime,
402 const sal_Int64 nRepeatInterval,
403 const sal_Int32 nTaskId)
419 const css::uno::Reference<css::uno::XComponentContext>& rxContext)
421 ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex());
440 mbIsCallbackPending(
false),
444 Reference<lang::XMultiComponentFactory>
xFactory =
445 rxContext->getServiceManager();
448 xFactory->createInstanceWithContext(
449 "com.sun.star.awt.AsyncCallback",
464 xComponent->dispose();
470 osl::MutexGuard aGuard (
maMutex);
487 osl::MutexGuard aGuard (
maMutex);
489 ListenerContainer::iterator iListener (::std::find(
503 mpInstance =
nullptr;
509 TimeValue aCurrentTime;
510 TimerScheduler::GetCurrentTime(aCurrentTime);
511 oslDateTime aDateTime;
512 osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime);
518 css::uno::Reference<css::awt::XRequestCallback> xRequestCallback;
519 css::uno::Reference<css::awt::XCallback> xCallback;
521 osl::MutexGuard aGuard (
maMutex);
523 TimeValue aCurrentTime (rCurrentTime);
524 oslDateTime aDateTime;
525 if (osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime))
545 if (xRequestCallback.is() && xCallback.is())
546 xRequestCallback->addCallback(xCallback,
Any());
556 osl::MutexGuard aGuard (
maMutex);
563 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)
std::mutex maCurrentTaskMutex
static std::mutex maInstanceMutex
void CheckCurrentTime(const TimeValue &rCurrentTime)
virtual void SAL_CALL notify(const css::uno::Any &rUserData) override
static::rtl::Reference< PresenterClockTimer > Instance(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
virtual ~PresenterClockTimer() override
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
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::mutex maTaskContainerMutex
::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
bool m_bDetectedRangeSegmentation false