Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/alg/viewshed/notifyqueue.h
Line
Count
Source
1
/******************************************************************************
2
 * (c) 2024 info@hobu.co
3
 *
4
 * SPDX-License-Identifier: MIT
5
 ****************************************************************************/
6
7
#ifndef VIEWSHED_NOTIFYQUEUE_H_INCLUDED
8
#define VIEWSHED_NOTIFYQUEUE_H_INCLUDED
9
10
#include "cpl_port.h"
11
12
#include <condition_variable>
13
#include <mutex>
14
#include <queue>
15
16
namespace gdal
17
{
18
namespace viewshed
19
{
20
21
/// This is a thread-safe queue. Things placed in the queue must be move-constructible.
22
/// Readers will wait until there is something in the queue or the queue is empty or stopped.
23
/// If the queue is stopped (error), it will never be in the done state. If in the
24
/// done state (all writers have finished), it will never be in the error state.
25
template <class T> class NotifyQueue
26
{
27
  public:
28
    /// Destructor
29
    ~NotifyQueue()
30
0
    {
31
0
        done();
32
0
    }
Unexecuted instantiation: gdal::viewshed::NotifyQueue<gdal::viewshed::Cumulative::Location>::~NotifyQueue()
Unexecuted instantiation: gdal::viewshed::NotifyQueue<std::__1::unique_ptr<GDALDataset, std::__1::default_delete<GDALDataset> > >::~NotifyQueue()
33
34
    /// Push an object on the queue and notify readers.
35
    /// \param t  Object to be moved onto the queue.
36
    void push(T &&t)
37
0
    {
38
0
        {
39
0
            std::lock_guard<std::mutex> lock(m_mutex);
40
0
            m_queue.push(std::move(t));
41
0
        }
42
0
        m_cv.notify_all();
43
0
    }
Unexecuted instantiation: gdal::viewshed::NotifyQueue<gdal::viewshed::Cumulative::Location>::push(gdal::viewshed::Cumulative::Location&&)
Unexecuted instantiation: gdal::viewshed::NotifyQueue<std::__1::unique_ptr<GDALDataset, std::__1::default_delete<GDALDataset> > >::push(std::__1::unique_ptr<GDALDataset, std::__1::default_delete<GDALDataset> >&&)
44
45
    /// Get an item from the queue.
46
    /// \param t  Reference to an item to to which a queued item will be moved.
47
    /// \return True if an item was popped. False otherwise.  Use isStopped() or isDone()
48
    ///    to determine the state if you care when false is returned.
49
    bool pop(T &t)
50
0
    {
51
0
        std::unique_lock<std::mutex> lock(m_mutex);
52
0
        m_cv.wait(lock,
53
0
                  [this] { return !m_queue.empty() || m_done || m_stop; });
Unexecuted instantiation: gdal::viewshed::NotifyQueue<gdal::viewshed::Cumulative::Location>::pop(gdal::viewshed::Cumulative::Location&)::{lambda()#1}::operator()() const
Unexecuted instantiation: gdal::viewshed::NotifyQueue<std::__1::unique_ptr<GDALDataset, std::__1::default_delete<GDALDataset> > >::pop(std::__1::unique_ptr<GDALDataset, std::__1::default_delete<GDALDataset> >&)::{lambda()#1}::operator()() const
54
55
0
        if (m_stop)
56
0
            return false;
57
58
0
        if (m_queue.size())
59
0
        {
60
0
            t = std::move(m_queue.front());
61
0
            m_queue.pop();
62
0
            return true;
63
0
        }
64
65
        // m_done must be true and the queue is empty.
66
0
        return false;
67
0
    }
Unexecuted instantiation: gdal::viewshed::NotifyQueue<gdal::viewshed::Cumulative::Location>::pop(gdal::viewshed::Cumulative::Location&)
Unexecuted instantiation: gdal::viewshed::NotifyQueue<std::__1::unique_ptr<GDALDataset, std::__1::default_delete<GDALDataset> > >::pop(std::__1::unique_ptr<GDALDataset, std::__1::default_delete<GDALDataset> >&)
68
69
    /// When we're done putting things in the queue, set the end condition.
70
    void done()
71
0
    {
72
0
        {
73
0
            std::lock_guard<std::mutex> lock(m_mutex);
74
0
            m_done = !m_stop;  // If we're already stopped, we can't be done.
75
0
        }
76
0
        m_cv.notify_all();
77
0
    }
Unexecuted instantiation: gdal::viewshed::NotifyQueue<gdal::viewshed::Cumulative::Location>::done()
Unexecuted instantiation: gdal::viewshed::NotifyQueue<std::__1::unique_ptr<GDALDataset, std::__1::default_delete<GDALDataset> > >::done()
78
79
    /// Unblock all readers regardless of queue state.
80
    void stop()
81
0
    {
82
0
        {
83
0
            std::lock_guard<std::mutex> lock(m_mutex);
84
0
            m_stop = !m_done;  // If we're already done, we can't be stopped.
85
0
        }
86
0
        m_cv.notify_all();
87
0
    }
88
89
    /// Determine if the queue was emptied completely. Call after pop() returns false
90
    /// to check queue state.
91
    /// \return  Whether the queue was emptied completely.
92
    bool isDone()
93
    {
94
        std::lock_guard<std::mutex> lock(m_mutex);
95
        return m_done;
96
    }
97
98
    /// Determine if the queue was stopped. Call after pop() returns false
99
    /// to check queue state.
100
    /// \return  Whether the queue was stopped.
101
    bool isStopped()
102
0
    {
103
0
        std::lock_guard<std::mutex> lock(m_mutex);
104
0
        return m_stop;
105
0
    }
106
107
    /// Get the current size of the queue.
108
    /// \return Current queue size.
109
    size_t size() const
110
0
    {
111
0
        std::lock_guard<std::mutex> lock(m_mutex);
112
0
        return m_queue.size();
113
0
    }
114
115
  private:
116
    std::queue<T> m_queue{};
117
    mutable std::mutex m_mutex{};
118
    std::condition_variable m_cv{};
119
    bool m_done{false};
120
    bool m_stop{false};
121
};
122
123
}  // namespace viewshed
124
}  // namespace gdal
125
126
#endif