]> git.ipfire.org Git - thirdparty/squid.git/blame - src/security/LockingPointer.h
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / security / LockingPointer.h
CommitLineData
89deb186 1/*
f70aedc4 2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
89deb186
AJ
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
f97700a0
AJ
9#ifndef SQUID_SRC_SECURITY_LOCKINGPOINTER_H
10#define SQUID_SRC_SECURITY_LOCKINGPOINTER_H
11
4103b0c1
AJ
12#include "base/HardFun.h"
13
eacc1666 14#if USE_OPENSSL
24b30fdc 15#include "compat/openssl.h"
eacc1666
AJ
16#if HAVE_OPENSSL_CRYPTO_H
17#include <openssl/crypto.h>
18#endif
19
20// Macro to be used to define the C++ wrapper function of a sk_*_pop_free
21// openssl family functions. The C++ function suffixed with the _free_wrapper
22// extension
23#define sk_free_wrapper(sk_object, argument, freefunction) \
24 extern "C++" inline void sk_object ## _free_wrapper(argument a) { \
25 sk_object ## _pop_free(a, freefunction); \
26 }
27
fdfa0570 28#endif /* USE_OPENSSL */
eacc1666
AJ
29
30// Macro to be used to define the C++ equivalent function of an extern "C"
31// function. The C++ function suffixed with the _cpp extension
32#define CtoCpp1(function, argument) \
33 extern "C++" inline void function ## _cpp(argument a) { \
34 function(a); \
35 }
36
f97700a0
AJ
37namespace Security
38{
39
4103b0c1
AJ
40inline bool nilFunction(const void *) { return false; }
41typedef HardFun<bool, const void *, nilFunction> NilFunctor;
42
f97700a0 43/**
d2e36b65
AJ
44 * A shared pointer to a reference-counting Object with library-specific
45 * absorption, locking, and unlocking implementations. The API largely
46 * follows std::shared_ptr.
47 *
35b3559c 48 * The constructor and the resetWithoutLocking() method import a raw Object pointer.
d2e36b65
AJ
49 * Normally, reset() would lock(), but libraries like OpenSSL
50 * pre-lock objects before they are fed to LockingPointer, necessitating
35b3559c 51 * this resetWithoutLocking() customization hook.
89deb186 52 */
4103b0c1 53template <typename T, void (*UnLocker)(T *t), class Locker = NilFunctor>
fdfa0570 54class LockingPointer
f97700a0
AJ
55{
56public:
fdfa0570 57 /// a helper label to simplify this objects API definitions below
4103b0c1 58 typedef Security::LockingPointer<T, UnLocker, Locker> SelfType;
89deb186 59
83b053a0
CT
60 /// constructs a nil smart pointer
61 constexpr LockingPointer(): raw(nullptr) {}
62
63 /// constructs a nil smart pointer from nullptr
64 constexpr LockingPointer(std::nullptr_t): raw(nullptr) {}
65
fdfa0570 66 /**
83b053a0
CT
67 * Construct directly from a (possibly nil) raw pointer. If the supplied
68 * pointer is not nil, it is expected that its producer has already created
69 * one reference lock for the object pointed to, and our destructor will do
70 * the matching unlock.
fdfa0570 71 */
83b053a0 72 explicit LockingPointer(T *t): raw(nullptr) {
58a5291c
AJ
73 // de-optimized for clarity about non-locking
74 resetWithoutLocking(t);
75 }
89deb186 76
d2e36b65
AJ
77 /// use the custom UnLocker to unlock any value still stored.
78 ~LockingPointer() { unlock(); }
89deb186 79
fdfa0570 80 // copy semantics are okay only when adding a lock reference
b23f5f9c 81 LockingPointer(const SelfType &o) : raw(nullptr) {
eba8d9bb
AJ
82 resetAndLock(o.get());
83 }
84 const SelfType &operator =(const SelfType &o) {
014a9017 85 resetAndLock(o.get());
89deb186
AJ
86 return *this;
87 }
f97700a0 88
b9a9207b
AJ
89 LockingPointer(SelfType &&o) : raw(nullptr) {
90 resetWithoutLocking(o.release());
91 }
7007ee99
AJ
92 SelfType &operator =(SelfType &&o) {
93 if (o.get() != raw)
35b3559c 94 resetWithoutLocking(o.release());
7007ee99
AJ
95 return *this;
96 }
89deb186 97
fdfa0570
AJ
98 bool operator !() const { return !raw; }
99 explicit operator bool() const { return raw; }
92e3827b
AJ
100 bool operator ==(const SelfType &o) const { return (o.get() == raw); }
101 bool operator !=(const SelfType &o) const { return (o.get() != raw); }
fdfa0570 102
ad23e748
AJ
103 T *operator ->() const { return raw; }
104
fdfa0570
AJ
105 /// Returns raw and possibly nullptr pointer
106 T *get() const { return raw; }
107
d2e36b65 108 /// Reset raw pointer - unlock any previous one and save new one without locking.
35b3559c 109 void resetWithoutLocking(T *t) {
d2e36b65 110 unlock();
fdfa0570 111 raw = t;
89deb186 112 }
f97700a0 113
014a9017 114 void resetAndLock(T *t) {
ccf24f29 115 if (t != get()) {
35b3559c 116 resetWithoutLocking(t);
d2e36b65 117 lock(t);
f97700a0
AJ
118 }
119 }
fdfa0570 120
58a5291c
AJ
121 /// Forget the raw pointer - unlock if any value was set. Become a nil pointer.
122 void reset() { unlock(); }
123
d2e36b65 124 /// Forget the raw pointer without unlocking it. Become a nil pointer.
fdfa0570
AJ
125 T *release() {
126 T *ret = raw;
127 raw = nullptr;
128 return ret;
129 }
130
131private:
58a5291c 132 /// The lock() method increments Object's reference counter.
d2e36b65 133 void lock(T *t) {
4103b0c1
AJ
134 if (t) {
135 Locker doLock;
136 doLock(t);
137 }
d2e36b65
AJ
138 }
139
58a5291c
AJ
140 /// Become a nil pointer. Decrements any pointed-to Object's reference counter
141 /// using UnLocker which ideally destroys the object when the counter reaches zero.
d2e36b65 142 void unlock() {
58a5291c 143 if (raw) {
d2e36b65 144 UnLocker(raw);
58a5291c
AJ
145 raw = nullptr;
146 }
fdfa0570
AJ
147 }
148
58a5291c
AJ
149 /**
150 * Normally, no other code will have this raw pointer.
151 *
152 * However, OpenSSL does some strange and not always consistent things.
153 * OpenSSL library may keep its own internal raw pointers and manage
154 * their reference counts independently, or it may not. This varies between
155 * API functions, though it is usually documented.
156 *
2f8abb64 157 * This means the caller code needs to be carefully written to use the correct
58a5291c
AJ
158 * reset method and avoid the raw-pointer constructor unless OpenSSL function
159 * producing the pointer is clearly documented as incrementing a lock for it.
160 */
161 T *raw;
f97700a0
AJ
162};
163
164} // namespace Security
165
166#endif /* SQUID_SRC_SECURITY_LOCKINGPOINTER_H */
63b8c4d7 167