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