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::atomic<T*> m_ptr{nullptr};
33
34public: // ...structors
35 LazyPtr() = default;
36
37 // Clean up allocated resource on destruction
39 {
40 delete m_ptr.load(std::memory_order_relaxed);
41 }
42
43 // Prevent copying to avoid double-free errors
44 LazyPtr(const LazyPtr&) = delete;
45 LazyPtr& operator=(const LazyPtr&) = delete;
46
47 // Allow moving
48 LazyPtr(LazyPtr&& other) noexcept
49 : m_ptr(other.m_ptr.exchange(nullptr, std::memory_order_relaxed))
50 {}
51
52public: // Operators
53 // Allow assignment
54 LazyPtr& operator=(LazyPtr&& other) noexcept
55 {
56 if (this != &other)
57 {
58 delete m_ptr.load(std::memory_order_relaxed);
59 m_ptr.store(other.m_ptr.exchange(nullptr, std::memory_order_relaxed),
60 std::memory_order_relaxed);
61 }
62 return *this;
63 }
64
65 // Lazy initialization & dereference
66 T& operator*() { return *get_or_throw(); }
67
68 // Lazy initialization
69 T* operator->() { return get_or_throw(); }
70
71 // Explicit bool conversion
72 explicit operator bool() const noexcept
73 {
74 return m_ptr.load(std::memory_order_relaxed) != nullptr;
75 }
76
77 // The raw pointer value
78 T* get_ptr() const noexcept
79 {
80 return m_ptr.load(std::memory_order_relaxed);
81 }
82
83private: // Modifiers
84 // Lazily initialize if required
85 T* get_or_throw()
86 {
87 T* p = m_ptr.load(std::memory_order_relaxed);
88 if (!p)
89 {
90 auto* new_p = new T();
91 if (!m_ptr.compare_exchange_strong(p, new_p
92 , std::memory_order_relaxed
93 , std::memory_order_relaxed
94 )
95 )
96 {
97 delete new_p; // Lost the race
98 }
99 else
100 {
101 p = new_p;
102 }
103 }
104 return p;
105 }
106};
107
108} } // namespace LOG4CXX_NS::helpers
109
110#endif // _LOG4CXX_HELPERS_LAZY_PTR_H
T & operator*()
Definition lazyptr.h:66
~LazyPtr()
Definition lazyptr.h:38
LazyPtr & operator=(LazyPtr &&other) noexcept
Definition lazyptr.h:54
LazyPtr & operator=(const LazyPtr &)=delete
LazyPtr(const LazyPtr &)=delete
LazyPtr(LazyPtr &&other) noexcept
Definition lazyptr.h:48
T * operator->()
Definition lazyptr.h:69
T * get_ptr() const noexcept
Definition lazyptr.h:78