]> git.ipfire.org Git - thirdparty/squid.git/blame - src/security/LockingPointer.h
Update LockingPointer methods and documentation
[thirdparty/squid.git] / src / security / LockingPointer.h
CommitLineData
89deb186 1/*
ef57eb7b 2 * Copyright (C) 1996-2016 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
eacc1666
AJ
12#if USE_OPENSSL
13#if HAVE_OPENSSL_CRYPTO_H
14#include <openssl/crypto.h>
15#endif
16
17// Macro to be used to define the C++ wrapper function of a sk_*_pop_free
18// openssl family functions. The C++ function suffixed with the _free_wrapper
19// extension
20#define sk_free_wrapper(sk_object, argument, freefunction) \
21 extern "C++" inline void sk_object ## _free_wrapper(argument a) { \
22 sk_object ## _pop_free(a, freefunction); \
23 }
24
fdfa0570 25#endif /* USE_OPENSSL */
eacc1666
AJ
26
27// Macro to be used to define the C++ equivalent function of an extern "C"
28// function. The C++ function suffixed with the _cpp extension
29#define CtoCpp1(function, argument) \
30 extern "C++" inline void function ## _cpp(argument a) { \
31 function(a); \
32 }
33
f97700a0
AJ
34namespace Security
35{
36
37/**
d2e36b65
AJ
38 * A shared pointer to a reference-counting Object with library-specific
39 * absorption, locking, and unlocking implementations. The API largely
40 * follows std::shared_ptr.
41 *
42 * The constructor and the reset() method import a raw Object pointer.
43 * Normally, reset() would lock(), but libraries like OpenSSL
44 * pre-lock objects before they are fed to LockingPointer, necessitating
45 * this customization hook.
46 *
47 * The lock() method increments Object's reference counter.
48 *
49 * The unlock() method decrements Object's reference counter and destroys
50 * the object when the counter reaches zero.
89deb186 51 */
d2e36b65 52template <typename T, void (*UnLocker)(T *t), int lockId>
fdfa0570 53class LockingPointer
f97700a0
AJ
54{
55public:
fdfa0570 56 /// a helper label to simplify this objects API definitions below
d2e36b65 57 typedef LockingPointer<T, UnLocker, lockId> 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
AJ
64 */
65 explicit LockingPointer(T *t = nullptr): raw(t) {}
89deb186 66
d2e36b65
AJ
67 /// use the custom UnLocker to unlock any value still stored.
68 ~LockingPointer() { unlock(); }
89deb186 69
fdfa0570
AJ
70 // copy semantics are okay only when adding a lock reference
71 explicit LockingPointer(const SelfType &o) : raw(nullptr) { resetAndLock(o.get()); }
89deb186 72 SelfType &operator =(const SelfType & o) {
014a9017 73 resetAndLock(o.get());
89deb186
AJ
74 return *this;
75 }
f97700a0 76
fdfa0570
AJ
77 // move semantics are definitely okay, when possible
78 explicit LockingPointer(SelfType &&) = default;
7007ee99
AJ
79 SelfType &operator =(SelfType &&o) {
80 if (o.get() != raw)
81 reset(o.release());
82 return *this;
83 }
89deb186 84
fdfa0570
AJ
85 bool operator !() const { return !raw; }
86 explicit operator bool() const { return raw; }
87
88 /// Returns raw and possibly nullptr pointer
89 T *get() const { return raw; }
90
d2e36b65 91 /// Reset raw pointer - unlock any previous one and save new one without locking.
fdfa0570 92 void reset(T *t) {
d2e36b65 93 unlock();
fdfa0570 94 raw = t;
89deb186 95 }
f97700a0 96
014a9017 97 void resetAndLock(T *t) {
ccf24f29
AJ
98 if (t != get()) {
99 reset(t);
d2e36b65 100 lock(t);
f97700a0
AJ
101 }
102 }
fdfa0570 103
d2e36b65 104 /// Forget the raw pointer without unlocking it. Become a nil pointer.
fdfa0570
AJ
105 T *release() {
106 T *ret = raw;
107 raw = nullptr;
108 return ret;
109 }
110
111private:
d2e36b65
AJ
112 void lock(T *t) {
113#if USE_OPENSSL
114 if (t)
115 CRYPTO_add(&t->references, 1, lockId);
116#elif USE_GNUTLS
117 // XXX: GnuTLS does not provide locking ?
118#else
119 assert(false);
120#endif
121 }
122
123 /// Unlock the raw pointer. Become a nil pointer.
124 void unlock() {
fdfa0570 125 if (raw)
d2e36b65 126 UnLocker(raw);
fdfa0570
AJ
127 raw = nullptr;
128 }
129
130 T *raw; ///< pointer to T object or nullptr
f97700a0
AJ
131};
132
133} // namespace Security
134
135#endif /* SQUID_SRC_SECURITY_LOCKINGPOINTER_H */
63b8c4d7 136