1// Copyright (C) 2024 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#ifndef QRHIVALUEMAPPER_P_H
5#define QRHIVALUEMAPPER_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtMultimedia/qtmultimediaglobal.h>
19
20#include <qreadwritelock.h>
21
22#include <memory>
23#include <map>
24
25QT_BEGIN_NAMESPACE
26
27class QRhi;
28
29/**
30 * @brief The QRhiCallback class implements a thread-safe wrapper around QRhi
31 * cleanup callbacks. For adding a callback to QRhi, create a shared insance
32 * of the class and invoke addToRhi for the specific QRhi. To deactivate
33 * the callback delete the instance.
34 */
35class Q_MULTIMEDIA_EXPORT QRhiCallback : public std::enable_shared_from_this<QRhiCallback>
36{
37public:
38 class Manager;
39
40 QRhiCallback();
41 virtual ~QRhiCallback();
42
43 void registerCallback(QRhi &rhi);
44
45protected:
46 virtual void onRhiCleanup(QRhi &rhi) = 0;
47
48private:
49 std::shared_ptr<Manager> m_manager;
50};
51
52/**
53 * @brief The class associates values of the specified type with different QRhi.
54 * One instance of QRhiValueMapper associates one QRhi with one value.
55 * The mapped value is deleted when the matching QRhi is cleaned/deleted,
56 * when QRhiValueMapper::clear is invoked, or the QRhiValueMapper's
57 * instance is deleted.
58 *
59 * QRhiValueMapper's API is thread safe, whereas the objects, which pointers you
60 * obtain via QRhiValueMapper::get(), are not. Thus, their thread-safity
61 * has to be managed by the code using the mapper.
62
63 * Note, that QRhiValueMapper destructs the values under its mutex.
64 * Keep it in mind and aim to avoid callbacks and signals emissions fror
65 * the Value's destructor.
66 */
67template <typename Value>
68class QRhiValueMapper
69{
70 struct Data : QRhiCallback
71 {
72 QReadWriteLock lock;
73 // In most cases, one or 2 elements will be here, so let's use map
74 // instead of unordered_map for better efficiency with few elements.
75 std::map<QRhi *, Value> storage;
76
77 void onRhiCleanup(QRhi &rhi) override
78 {
79 QWriteLocker locker(&lock);
80 storage.erase(&rhi);
81 }
82 };
83
84public:
85 ~QRhiValueMapper()
86 {
87 clear(); // it must be cleared when on the destruction to synchronize with rhi cleanup
88 }
89
90 Q_DISABLE_COPY(QRhiValueMapper);
91
92 QRhiValueMapper(QRhiValueMapper&& ) noexcept = default;
93 QRhiValueMapper& operator = (QRhiValueMapper&&) noexcept = default;
94
95 QRhiValueMapper() : m_data(std::make_shared<Data>()) { }
96
97 template <typename V>
98 std::pair<Value *, bool> tryMap(QRhi &rhi, V &&value)
99 {
100 QWriteLocker locker(&m_data->lock);
101
102 auto [rhiIt, rhiAdded] = m_data->storage.try_emplace(&rhi, std::forward<V>(value));
103
104 if (rhiAdded)
105 m_data->registerCallback(rhi);
106
107 return { &rhiIt->second, rhiAdded };
108 }
109
110 Value *get(QRhi &rhi) const
111 {
112 QReadLocker locker(&m_data->lock);
113 auto rhiIt = m_data->storage.find(&rhi);
114 return rhiIt == m_data->storage.end() ? nullptr : &rhiIt->second;
115 }
116
117 // To be added for thread-safe value read:
118 //
119 // template <typename Reader>
120 // void read(QRhi &rhi, Reader&& reader) const {
121 // QReadLocker locker(&m_data->lock);
122 // auto rhiIt = m_data->storage.find(&rhi);
123 // if (rhiIt != m_data->storage.end())
124 // reader(const_cast<const Value&>(rhiIt->second));
125 // }
126
127 void clear()
128 {
129 if (!m_data)
130 return; // the object has been moved
131 QWriteLocker locker(&m_data->lock);
132 m_data->storage.clear();
133 }
134
135 template <typename Predicate>
136 QRhi *findRhi(Predicate &&p) const
137 {
138 QReadLocker locker(&m_data->lock);
139 auto &storage = m_data->storage;
140
141 auto it = std::find_if(storage.begin(), storage.end(),
142 [&p](auto &rhiItem) { return p(*rhiItem.first); });
143 return it == storage.end() ? nullptr : it->first;
144 }
145
146private:
147 std::shared_ptr<Data> m_data;
148};
149
150QT_END_NAMESPACE
151
152#endif // QRHIVALUEMAPPER_P_H
153

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtmultimedia/src/multimedia/qrhivaluemapper_p.h