Lagrange
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 return static_cast<const Derived*>(m_data.get());
85 }
86
88 template <typename Derived>
89 Derived* static_write()
90 {
91 ensure_unique_owner<Derived>();
92 return static_cast<Derived*>(m_data.get());
93 }
94
96 template <typename Derived>
97 std::shared_ptr<Derived> release_ptr()
98 {
99 ensure_unique_owner<Derived>();
100 auto ptr = static_cast<Derived*>(m_data.get());
101#if LAGRANGE_TARGET_FEATURE(RTTI)
102 la_debug_assert(dynamic_cast<Derived*>(m_data.get()));
103#endif
104 auto ret = std::make_shared<Derived>(std::move(*ptr));
105 m_data.reset();
106 return ret;
107 }
108
109public:
116
123
124protected:
126
128 // std::mutex m_ownership_mutex;
129
131 template <typename Derived>
133 {
134 // Only mutex lock if we are not the owner. This prevents having to lock mutexes when we are
135 // already the unique owner of the data.
136 if (m_data.use_count() != 1) {
137 // TODO: We should be using a mutex here, but this causes the copy-on-write pointer to
138 // not be movable/copyable. We need to fix this before we can use a mutex.
139 // std::lock_guard<std::mutex> lock(m_ownership_mutex);
140 // Test again in protected section to ensure we don't copy the data twice for the same
141 // object.
142 // if (m_data.use_count() != 1) {
143 auto ptr = static_cast<const Derived*>(m_data.get());
144#if LAGRANGE_TARGET_FEATURE(RTTI)
145 la_debug_assert(dynamic_cast<const Derived*>(m_data.get()));
146#endif
147 m_data = ::lagrange::internal::make_shared<Derived>(*ptr);
148 // }
149 }
150 }
151};
152
154
155} // 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:122
::lagrange::internal::weak_ptr< const T > _get_weak_ptr() const
Return a weak pointer to the data.
Definition: copy_on_write_ptr.h:115
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:97
Derived * static_write()
Returns a writable pointer to the data. Will cause a copy if ownership is shared.
Definition: copy_on_write_ptr.h:89
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:132
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