Lagrange
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Modules Pages
copy_on_write_ptr.h
1/*
2 * Copyright 2022 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <lagrange/utils/assert.h>
15
16#include <lagrange/Logger.h>
17
18#include <lagrange/internal/shared_ptr.h>
19#include <lagrange/utils/build.h>
20
21#include <cassert>
22#include <memory>
23#include <mutex>
24
25namespace lagrange {
26
29
36template <typename T>
38{
39public:
40 using pointer = T*;
41 using const_pointer = typename std::add_const<T>::type*;
42 using reference = T&;
43 using const_reference = typename std::add_const<T>::type&;
44 using element_type = T;
45
46public:
49 : m_data(std::move(ptr))
50 {
51 if (m_data) {
52 la_runtime_assert(m_data.use_count() == 1);
53 }
54 }
55
58
61
63 template <typename Derived>
65 : m_data{std::move(ptr.m_data)}
66 {}
67
70
73
75 explicit operator bool() const { return bool(m_data); }
76
78 const T* read() const { return m_data.get(); }
79
81 template <typename Derived>
82 const Derived* static_read() const
83 {
84#if LAGRANGE_TARGET_FEATURE(RTTI)
85 la_debug_assert(dynamic_cast<const Derived*>(m_data.get()));
86#endif
87 return static_cast<const Derived*>(m_data.get());
88 }
89
91 template <typename Derived>
92 Derived* static_write()
93 {
94 ensure_unique_owner<Derived>();
95#if LAGRANGE_TARGET_FEATURE(RTTI)
96 la_debug_assert(dynamic_cast<Derived*>(m_data.get()));
97#endif
98 return static_cast<Derived*>(m_data.get());
99 }
100
102 template <typename Derived>
103 std::shared_ptr<Derived> release_ptr()
104 {
105 ensure_unique_owner<Derived>();
106 auto ptr = static_cast<Derived*>(m_data.get());
107#if LAGRANGE_TARGET_FEATURE(RTTI)
108 la_debug_assert(dynamic_cast<Derived*>(m_data.get()));
109#endif
110 auto ret = std::make_shared<Derived>(std::move(*ptr));
111 m_data.reset();
112 return ret;
113 }
114
115public:
122
129
130protected:
132
134 // std::mutex m_ownership_mutex;
135
137 template <typename Derived>
139 {
140 // Only mutex lock if we are not the owner. This prevents having to lock mutexes when we are
141 // already the unique owner of the data.
142 if (m_data.use_count() != 1) {
143 // TODO: We should be using a mutex here, but this causes the copy-on-write pointer to
144 // not be movable/copyable. We need to fix this before we can use a mutex.
145 // std::lock_guard<std::mutex> lock(m_ownership_mutex);
146 // Test again in protected section to ensure we don't copy the data twice for the same
147 // object.
148 // if (m_data.use_count() != 1) {
149 auto ptr = static_cast<const Derived*>(m_data.get());
150#if LAGRANGE_TARGET_FEATURE(RTTI)
151 la_debug_assert(dynamic_cast<const Derived*>(m_data.get()));
152#endif
153 m_data = ::lagrange::internal::make_shared<Derived>(*ptr);
154 // }
155 }
156 }
157};
158
160
161} // namespace lagrange
A handle type with copy-on-write semantics.
Definition: copy_on_write_ptr.h:38
copy_on_write_ptr(const copy_on_write_ptr &)=default
Default copy constructor.
::lagrange::internal::weak_ptr< T > _get_weak_ptr()
Return a weak pointer to the data.
Definition: copy_on_write_ptr.h:128
::lagrange::internal::weak_ptr< const T > _get_weak_ptr() const
Return a weak pointer to the data.
Definition: copy_on_write_ptr.h:121
const T * read() const
Returns a const pointer to the data. Does not require ownership and will not lead to any copy.
Definition: copy_on_write_ptr.h:78
copy_on_write_ptr & operator=(const copy_on_write_ptr &)=default
Default copy assignment operator.
copy_on_write_ptr(copy_on_write_ptr &&)=default
Default move constructor.
copy_on_write_ptr & operator=(copy_on_write_ptr &&)=default
Default move assignment operator.
std::shared_ptr< Derived > release_ptr()
Returns a writable smart pointer to the data. Will cause a copy if ownership is shared.
Definition: copy_on_write_ptr.h:103
Derived * static_write()
Returns a writable pointer to the data. Will cause a copy if ownership is shared.
Definition: copy_on_write_ptr.h:92
const Derived * static_read() const
Returns a const pointer to the data. Does not require ownership and will not lead to any copy.
Definition: copy_on_write_ptr.h:82
copy_on_write_ptr(::lagrange::internal::shared_ptr< T > &&ptr=nullptr)
Construct a copy-on-write ptr from a shared-pointer.
Definition: copy_on_write_ptr.h:48
void ensure_unique_owner()
Protect from data races when acquiring ownership to the same object from multiple threads.
Definition: copy_on_write_ptr.h:138
copy_on_write_ptr(copy_on_write_ptr< Derived > &&ptr)
Move-construct from a derived type.
Definition: copy_on_write_ptr.h:64
NOT implemented: custom allocator support.
Definition: shared_ptr.h:110
Definition: weak_ptr.h:26
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
#define la_debug_assert(...)
Debug assertion check.
Definition: assert.h:189
Main namespace for Lagrange.
Definition: AABBIGL.h:30