Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
btgcdtimer.mm
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "btgcdtimer_p.h"
5#include "btutility_p.h"
6
7#include <QtCore/qelapsedtimer.h>
8#include <QtCore/qdebug.h>
9
10#include <algorithm>
11
12QT_USE_NAMESPACE
13using namespace DarwinBluetooth;
14
15@implementation DarwinBTGCDTimer {
16@private
17 qint64 timeoutMS;
18 qint64 timeoutStepMS;
19
20 // Optional:
21 id objectUnderWatch;
22 OperationTimeout timeoutType;
23
24 QElapsedTimer timer;
25 id<QT_MANGLE_NAMESPACE(GCDTimerDelegate)> timeoutHandler;
26
27 bool cancelled;
28}
29
30- (instancetype)initWithDelegate:(id<QT_MANGLE_NAMESPACE(GCDTimerDelegate)>)delegate
31{
32 if (self = [super init]) {
33 timeoutHandler = delegate;
34 timeoutMS = 0;
35 timeoutStepMS = 0;
36 objectUnderWatch = nil;
37 timeoutType = OperationTimeout::none;
38 cancelled = false;
39 }
40 return self;
41}
42
43- (void)watchAfter:(id)object withTimeoutType:(OperationTimeout)type
44{
45 objectUnderWatch = object;
46 timeoutType = type;
47}
48
49- (void)startWithTimeout:(qint64)ms step:(qint64)stepMS
50{
51 Q_ASSERT(!timeoutMS && !timeoutStepMS);
52 Q_ASSERT(!cancelled);
53
54 if (!timeoutHandler) {
55 // Nobody to report timeout to, no need to start any task then.
56 return;
57 }
58
59 if (ms <= 0 || stepMS <= 0) {
60 qCWarning(QT_BT_DARWIN, "Invalid timeout/step parameters");
61 return;
62 }
63
64 timeoutMS = ms;
65 timeoutStepMS = stepMS;
66 timer.start();
67
68 [self handleTimeout];
69}
70
71- (void)handleTimeout
72{
73 if (cancelled)
74 return;
75
76 const qint64 elapsed = timer.elapsed();
77 if (elapsed >= timeoutMS) {
78 [timeoutHandler timeout:self];
79 } else {
80 // Re-schedule:
81 dispatch_queue_t leQueue(qt_LE_queue());
82 Q_ASSERT(leQueue);
83 const qint64 timeChunkMS = std::min(timeoutMS - elapsed, timeoutStepMS);
84 dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
85 int64_t(timeChunkMS / 1000. * NSEC_PER_SEC)),
86 leQueue,
87 ^{
88 [self handleTimeout];
89 });
90 }
91}
92
93- (void)cancelTimer
94{
95 cancelled = true;
96 timeoutHandler = nil;
97 objectUnderWatch = nil;
98 timeoutType = OperationTimeout::none;
99}
100
101- (id)objectUnderWatch
102{
103 return objectUnderWatch;
104}
105
106- (OperationTimeout)timeoutType
107{
108 return timeoutType;
109}
110
111@end