Apache Log4cxx  Version 2.0.0
Loading...
Searching...
No Matches
lazyptr.h
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#ifndef _LOG4CXX_HELPERS_LAZY_PTR_H
19#define _LOG4CXX_HELPERS_LAZY_PTR_H
20#include <atomic>
21#include <memory>
22#include <utility>
23
24namespace LOG4CXX_NS { namespace helpers
25{
26
28template <typename T>
30{
31private:
32 std::function<void(T*)> m_initialiser;
33 std::atomic<T*> m_ptr{nullptr};
34
35public: // ...structors
36 LazyPtr(std::function<void(T*)> initialiser = {})
37 : m_initialiser(initialiser)
38 {}
39
40 // Clean up allocated resource on destruction
42 {
43 delete m_ptr.load(std::memory_order_acquire);
44 }
45
46 // Prevent copying to avoid double-free errors
47 LazyPtr(const LazyPtr&) = delete;
48 LazyPtr& operator=(const LazyPtr&) = delete;
49
50 // Allow moving
51 LazyPtr(LazyPtr&& other) noexcept
52 : m_ptr(other.m_ptr.exchange(nullptr, std::memory_order_acq_rel))
53 {}
54
55public: // Operators
56 // Allow assignment
57 LazyPtr& operator=(LazyPtr&& other) noexcept
58 {
59 if (this != &other)
60 {
61 delete m_ptr.load(std::memory_order_acquire);
62 m_ptr.store(other.m_ptr.exchange(nullptr, std::memory_order_acq_rel),
63 std::memory_order_release);
64 }
65 return *this;
66 }
67
68 // Lazy initialization & dereference
69 T& operator*() { return *get_or_throw(); }
70
71 // Lazy initialization
72 T* operator->() { return get_or_throw(); }
73
74 // Explicit bool conversion
75 explicit operator bool() const noexcept
76 {
77 return m_ptr.load(std::memory_order_acquire) != nullptr;
78 }
79
80 // The raw pointer value
81 T* get_ptr() const noexcept
82 {
83 return m_ptr.load(std::memory_order_acquire);
84 }
85
86private: // Modifiers
87 // Lazily initialize if required
88 T* get_or_throw()
89 {
90 T* p = m_ptr.load(std::memory_order_acquire);
91 if (!p)
92 {
93 auto* new_p = new T();
94 if (m_initialiser)
95 m_initialiser(new_p);
96 if (!m_ptr.compare_exchange_strong(p, new_p
97 , std::memory_order_release
98 , std::memory_order_acquire
99 )
100 )
101 {
102 delete new_p; // Lost the race
103 }
104 else
105 {
106 p = new_p;
107 }
108 }
109 return p;
110 }
111};
112
113} } // namespace LOG4CXX_NS::helpers
114
115#endif // _LOG4CXX_HELPERS_LAZY_PTR_H
T & operator*()
Definition lazyptr.h:69
~LazyPtr()
Definition lazyptr.h:41
LazyPtr & operator=(LazyPtr &&other) noexcept
Definition lazyptr.h:57
LazyPtr & operator=(const LazyPtr &)=delete
LazyPtr(const LazyPtr &)=delete
LazyPtr(LazyPtr &&other) noexcept
Definition lazyptr.h:51
LazyPtr(std::function< void(T *)> initialiser={})
Definition lazyptr.h:36
T * operator->()
Definition lazyptr.h:72
T * get_ptr() const noexcept
Definition lazyptr.h:81