QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GPSCancellation.cc
Go to the documentation of this file.
1#include "GPSCancellation.h"
2
3#include <atomic>
4#include <mutex>
5#include <utility>
6#include <vector>
7
9{
10 std::atomic<bool> cancelled = false;
12 std::mutex mutex;
13 std::vector<const std::function<void()>*> callbacks;
14};
15
16GPSCancelToken::GPSCancelToken(std::shared_ptr<State> state)
17 : _state(std::move(state))
18{}
19
21{
22 return _state && _state->cancelled.load(std::memory_order_acquire);
23}
24
26 : _state(std::make_shared<GPSCancelToken::State>())
27{}
28
30{
31 return GPSCancelToken(_state);
32}
33
35{
36 // A callback that cancels again returns here, before the mutex its own cancel() holds.
37 if (_state->cancelled.load(std::memory_order_acquire)) {
38 return false;
39 }
40 const std::lock_guard lock(_state->mutex);
41 if (_state->cancelled.exchange(true, std::memory_order_acq_rel)) {
42 return false;
43 }
44 for (const auto* callback : _state->callbacks) {
45 (*callback)();
46 }
47 _state->callbacks.clear();
48 return true;
49}
50
52{
53 return _state->cancelled.load(std::memory_order_acquire);
54}
55
56GPSCancelCallback::GPSCancelCallback(const GPSCancelToken& token, std::function<void()> callback)
57 : _callback(std::move(callback))
58{
59 if (!token._state) {
60 return;
61 }
62 {
63 const std::lock_guard lock(token._state->mutex);
64 if (!token._state->cancelled.load(std::memory_order_acquire)) {
65 token._state->callbacks.push_back(&_callback);
66 _state = token._state;
67 return;
68 }
69 }
70 _callback();
71}
72
74{
75 if (!_state) {
76 return;
77 }
78 const std::lock_guard lock(_state->mutex);
79 std::erase(_state->callbacks, &_callback);
80}
GPSCancelCallback(const GPSCancelToken &token, std::function< void()> callback)
bool isCancelled() const
GPSCancelToken token() const
bool isCancelled() const
Safe to call from any thread.
GPSCancelToken()=default
A token that is never cancelled.
std::mutex mutex
Held while callbacks run, so unregistering a callback waits for a running cancel().
std::atomic< bool > cancelled
std::vector< const std::function< void()> * > callbacks