]> git.ipfire.org Git - thirdparty/squid.git/blob - src/security/LockingPointer.h
Merge from trunk rev.14687
[thirdparty/squid.git] / src / security / LockingPointer.h
1 /*
2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
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
9 #ifndef SQUID_SRC_SECURITY_LOCKINGPOINTER_H
10 #define SQUID_SRC_SECURITY_LOCKINGPOINTER_H
11
12 #include "base/TidyPointer.h"
13
14 #if USE_OPENSSL
15
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
28 #else // !USE_OPENSSL
29
30 #include "base/Lock.h"
31 #include <unordered_map>
32
33 #endif
34
35 // Macro to be used to define the C++ equivalent function of an extern "C"
36 // function. The C++ function suffixed with the _cpp extension
37 #define CtoCpp1(function, argument) \
38 extern "C++" inline void function ## _cpp(argument a) { \
39 function(a); \
40 }
41
42 namespace Security
43 {
44
45 /**
46 * Add SSL locking (a.k.a. reference counting) and assignment to TidyPointer
47 */
48 template <typename T, void (*DeAllocator)(T *t), int lock>
49 class LockingPointer: public TidyPointer<T, DeAllocator>
50 {
51 public:
52 typedef TidyPointer<T, DeAllocator> Parent;
53 typedef LockingPointer<T, DeAllocator, lock> SelfType;
54
55 explicit LockingPointer(T *t = nullptr): Parent() {reset(t);}
56
57 virtual ~LockingPointer() { Parent::reset(nullptr); }
58
59 explicit LockingPointer(const SelfType &o): Parent() {
60 reset(o.get());
61 }
62
63 SelfType &operator =(const SelfType & o) {
64 reset(o.get());
65 return *this;
66 }
67
68 explicit LockingPointer(LockingPointer<T, DeAllocator, lock> &&o): Parent(o.release()) {}
69
70 LockingPointer<T, DeAllocator, lock> &operator =(LockingPointer<T, DeAllocator, lock> &&o) {
71 if (o.get() != this->get())
72 this->reset(o.release());
73 return *this;
74 }
75
76 virtual void reset(T *t) {
77 if (t == this->get())
78 return;
79
80 #if !USE_OPENSSL
81 // OpenSSL maintains the reference locks through calls to Deallocator
82 // our manual locking does not have that luxury
83 if (this->get()) {
84 if (SelfType::Locks().at(this->get()).unlock())
85 SelfType::Locks().erase(this->get());
86 }
87 #endif
88 Parent::reset(t);
89
90 if (t) {
91 #if USE_OPENSSL
92 CRYPTO_add(&t->references, 1, lock);
93 #else
94 SelfType::Locks()[t].lock(); // find/create and lock
95 #endif
96 }
97 }
98
99 private:
100 #if !USE_OPENSSL
101 // since we can never be sure if a raw-* passed to us is already being
102 // lock counted by another LockingPointer<> and the types pointed to are
103 // defined by third-party libraries we have to maintain the locks in a
104 // type-specific static external to both the Pointer and base classes.
105 static std::unordered_map<T*, Lock> & Locks() {
106 static std::unordered_map<T*, Lock> Instance;
107 return Instance;
108 }
109 #endif
110 };
111
112 } // namespace Security
113
114 #endif /* SQUID_SRC_SECURITY_LOCKINGPOINTER_H */
115