Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 113, column 13
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name FrameControlsManager.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/uibase/docvw/FrameControlsManager.cxx

/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/FrameControlsManager.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include <edtwin.hxx>
11#include <FrameControlsManager.hxx>
12#include <HeaderFooterWin.hxx>
13#include <PageBreakWin.hxx>
14#include <UnfloatTableButton.hxx>
15#include <pagefrm.hxx>
16#include <flyfrm.hxx>
17#include <viewopt.hxx>
18#include <view.hxx>
19#include <wrtsh.hxx>
20#include <txtfrm.hxx>
21#include <OutlineContentVisibilityWin.hxx>
22#include <ndtxt.hxx>
23#include <IDocumentOutlineNodes.hxx>
24
25using namespace std;
26
27SwFrameControlsManager::SwFrameControlsManager( SwEditWin* pEditWin ) :
28 m_pEditWin( pEditWin ),
29 m_aControls( )
30{
31}
32
33SwFrameControlsManager::~SwFrameControlsManager()
34{
35}
36
37void SwFrameControlsManager::dispose()
38{
39 m_aControls.clear();
40 m_aTextNodeContentFrameMap.clear();
41}
42
43SwFrameControlPtr SwFrameControlsManager::GetControl( FrameControlType eType, const SwFrame* pFrame )
44{
45 SwFrameControlPtrMap& rControls = m_aControls[eType];
46
47 SwFrameControlPtrMap::iterator aIt = rControls.find(pFrame);
48
49 if (aIt != rControls.end())
50 return aIt->second;
51
52 return SwFrameControlPtr();
53}
54
55void SwFrameControlsManager::RemoveControls( const SwFrame* pFrame )
56{
57 for ( auto& rEntry : m_aControls )
58 {
59 SwFrameControlPtrMap& rMap = rEntry.second;
60 rMap.erase(pFrame);
61 }
62}
63
64void SwFrameControlsManager::RemoveControlsByType( FrameControlType eType, const SwFrame* pFrame )
65{
66 SwFrameControlPtrMap& rMap = m_aControls[eType];
67 rMap.erase(pFrame);
68}
69
70void SwFrameControlsManager::HideControls( FrameControlType eType )
71{
72 for ( const auto& rCtrl : m_aControls[eType] )
73 rCtrl.second->ShowAll( false );
74}
75
76void SwFrameControlsManager::SetReadonlyControls( bool bReadonly )
77{
78 for ( auto& rEntry : m_aControls )
79 for ( auto& rCtrl : rEntry.second )
80 rCtrl.second->SetReadonly( bReadonly );
81}
82
83void SwFrameControlsManager::SetHeaderFooterControl( const SwPageFrame* pPageFrame, FrameControlType eType, Point aOffset )
84{
85 assert( eType == FrameControlType::Header || eType == FrameControlType::Footer )(static_cast <bool> (eType == FrameControlType::Header ||
eType == FrameControlType::Footer) ? void (0) : __assert_fail
("eType == FrameControlType::Header || eType == FrameControlType::Footer"
, "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/FrameControlsManager.cxx"
, 85, __extension__ __PRETTY_FUNCTION__))
;
86
87 // Check if we already have the control
88 SwFrameControlPtr pControl;
89 const bool bHeader = ( eType == FrameControlType::Header );
90
91 SwFrameControlPtrMap& rControls = m_aControls[eType];
92
93 SwFrameControlPtrMap::iterator lb = rControls.lower_bound(pPageFrame);
94 if (lb != rControls.end() && !(rControls.key_comp()(pPageFrame, lb->first)))
95 pControl = lb->second;
96 else
97 {
98 SwFrameControlPtr pNewControl =
99 std::make_shared<SwFrameControl>( VclPtr<SwHeaderFooterWin>::Create(
100 m_pEditWin, pPageFrame, bHeader ).get() );
101 const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions();
102 pNewControl->SetReadonly( pViewOpt->IsReadonly() );
103 rControls.insert(lb, make_pair(pPageFrame, pNewControl));
104 pControl.swap( pNewControl );
105 }
106
107 tools::Rectangle aPageRect = m_pEditWin->LogicToPixel( pPageFrame->getFrameArea().SVRect() );
108
109 SwHeaderFooterWin* pWin = dynamic_cast<SwHeaderFooterWin *>(pControl->GetWindow());
110 assert( pWin != nullptr)(static_cast <bool> (pWin != nullptr) ? void (0) : __assert_fail
("pWin != nullptr", "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/FrameControlsManager.cxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 assert( pWin->IsHeader() == bHeader )(static_cast <bool> (pWin->IsHeader() == bHeader) ? void
(0) : __assert_fail ("pWin->IsHeader() == bHeader", "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/FrameControlsManager.cxx"
, 111, __extension__ __PRETTY_FUNCTION__))
;
112 pWin->SetOffset( aOffset, aPageRect.Left(), aPageRect.Right() );
113
114 if (!pWin->IsVisible())
115 pControl->ShowAll( true );
116}
117
118void SwFrameControlsManager::SetPageBreakControl( const SwPageFrame* pPageFrame )
119{
120 // Check if we already have the control
121 SwFrameControlPtr pControl;
122
123 SwFrameControlPtrMap& rControls = m_aControls[FrameControlType::PageBreak];
124
125 SwFrameControlPtrMap::iterator lb = rControls.lower_bound(pPageFrame);
126 if (lb != rControls.end() && !(rControls.key_comp()(pPageFrame, lb->first)))
1
Taking false branch
127 pControl = lb->second;
128 else
129 {
130 SwFrameControlPtr pNewControl = std::make_shared<SwFrameControl>(
5
Calling 'make_shared<SwFrameControl, SwPageBreakWin *>'
30
Returning; memory was released via 1st parameter
131 VclPtr<SwPageBreakWin>::Create( m_pEditWin, pPageFrame ).get() );
2
Calling 'VclPtr::Create'
4
Returned allocated memory
31
Calling implicit destructor for 'VclPtr<SwPageBreakWin>'
32
Calling '~Reference'
132 const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions();
133 pNewControl->SetReadonly( pViewOpt->IsReadonly() );
134
135 rControls.insert(lb, make_pair(pPageFrame, pNewControl));
136
137 pControl.swap( pNewControl );
138 }
139
140 SwPageBreakWin* pWin = dynamic_cast<SwPageBreakWin *>(pControl->GetWindow());
141 assert (pWin != nullptr)(static_cast <bool> (pWin != nullptr) ? void (0) : __assert_fail
("pWin != nullptr", "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/FrameControlsManager.cxx"
, 141, __extension__ __PRETTY_FUNCTION__))
;
142 pWin->UpdatePosition();
143 if (!pWin->IsVisible())
144 pControl->ShowAll( true );
145}
146
147void SwFrameControlsManager::SetUnfloatTableButton( const SwFlyFrame* pFlyFrame, bool bShow, Point aTopRightPixel )
148{
149 if(pFlyFrame == nullptr)
150 return;
151
152 // Check if we already have the control
153 SwFrameControlPtr pControl;
154
155 SwFrameControlPtrMap& rControls = m_aControls[FrameControlType::FloatingTable];
156
157 SwFrameControlPtrMap::iterator lb = rControls.lower_bound(pFlyFrame);
158 if (lb != rControls.end() && !(rControls.key_comp()(pFlyFrame, lb->first)))
159 pControl = lb->second;
160 else if (!bShow) // Do not create the control when it's not shown
161 return;
162 else
163 {
164 SwFrameControlPtr pNewControl = std::make_shared<SwFrameControl>(
165 VclPtr<UnfloatTableButton>::Create( m_pEditWin, pFlyFrame ).get() );
166 const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions();
167 pNewControl->SetReadonly( pViewOpt->IsReadonly() );
168
169 rControls.insert(lb, make_pair(pFlyFrame, pNewControl));
170
171 pControl.swap( pNewControl );
172 }
173
174 UnfloatTableButton* pButton = dynamic_cast<UnfloatTableButton*>(pControl->GetWindow());
175 assert(pButton != nullptr)(static_cast <bool> (pButton != nullptr) ? void (0) : __assert_fail
("pButton != nullptr", "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/FrameControlsManager.cxx"
, 175, __extension__ __PRETTY_FUNCTION__))
;
176 pButton->SetOffset(aTopRightPixel);
177 pControl->ShowAll( bShow );
178}
179
180SwFrameMenuButtonBase::SwFrameMenuButtonBase( SwEditWin* pEditWin, const SwFrame* pFrame ) :
181 MenuButton( pEditWin, WB_DIALOGCONTROL ),
182 m_pEditWin( pEditWin ),
183 m_pFrame( pFrame )
184{
185}
186
187void SwFrameControlsManager::SetOutlineContentVisibilityButtons()
188{
189 // remove entries with outline node keys that are not in the outline nodes list
190 IDocumentOutlineNodes::tSortedOutlineNodeList aOutlineNodes;
191 m_pEditWin->GetView().GetWrtShell().getIDocumentOutlineNodesAccess()->getOutlineNodes(aOutlineNodes);
192 std::map<const SwTextNode*, const SwContentFrame*>::iterator it = m_aTextNodeContentFrameMap.begin();
193 while(it != m_aTextNodeContentFrameMap.end())
194 {
195 const SwNode* pNd = it->first;
196 IDocumentOutlineNodes::tSortedOutlineNodeList::iterator i = std::find(aOutlineNodes.begin(), aOutlineNodes.end(), pNd);
197 if (i == aOutlineNodes.end())
198 {
199 RemoveControlsByType(FrameControlType::Outline, it->second);
200 it = m_aTextNodeContentFrameMap.erase(it);
201 }
202 else
203 it++;
204 }
205 for (SwNode* pNd : m_pEditWin->GetView().GetWrtShell().GetNodes().GetOutLineNds())
206 {
207 bool bOutlineContentVisibleAttr = true;
208 pNd->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
209 if (!bOutlineContentVisibleAttr)
210 SetOutlineContentVisibilityButton(pNd->GetTextNode());
211 }
212}
213
214void SwFrameControlsManager::SetOutlineContentVisibilityButton(const SwTextNode* pTextNd)
215{
216 const SwContentFrame* pContentFrame = pTextNd->getLayoutFrame(nullptr);
217
218 // has node frame changed or been deleted
219 std::map<const SwTextNode*, const SwContentFrame*>::iterator iter = m_aTextNodeContentFrameMap.find(pTextNd);
220 if (iter != m_aTextNodeContentFrameMap.end())
221 {
222 const SwContentFrame* pFrameWas = iter->second;
223 if (pContentFrame != pFrameWas)
224 {
225 // frame does not match frame in map for node
226 RemoveControlsByType(FrameControlType::Outline, pFrameWas);
227 m_aTextNodeContentFrameMap.erase(iter);
228 }
229 }
230 if (pContentFrame && !pContentFrame->IsInDtor())
231 {
232 // frame is not being destroyed and isn't in map
233 m_aTextNodeContentFrameMap.insert(make_pair(pTextNd, pContentFrame));
234 }
235 else
236 {
237 if (pContentFrame)
238 {
239 // frame is being destroyed
240 RemoveControlsByType(FrameControlType::Outline, pContentFrame);
241 }
242 return;
243 }
244
245 // Check if we already have the control
246 SwFrameControlPtr pControl;
247
248 SwFrameControlPtrMap& rControls = m_aControls[FrameControlType::Outline];
249
250 SwFrameControlPtrMap::iterator lb = rControls.lower_bound(pContentFrame);
251 if (lb != rControls.end() && !(rControls.key_comp()(pContentFrame, lb->first)))
252 {
253 pControl = lb->second;
254 }
255 else
256 {
257 SwFrameControlPtr pNewControl =
258 std::make_shared<SwFrameControl>(VclPtr<SwOutlineContentVisibilityWin>::Create(
259 m_pEditWin, pContentFrame).get());
260 rControls.insert(lb, make_pair(pContentFrame, pNewControl));
261 pControl.swap(pNewControl);
262 }
263
264 SwOutlineContentVisibilityWin* pWin = dynamic_cast<SwOutlineContentVisibilityWin *>(pControl->GetWindow());
265 assert(pWin != nullptr)(static_cast <bool> (pWin != nullptr) ? void (0) : __assert_fail
("pWin != nullptr", "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/FrameControlsManager.cxx"
, 265, __extension__ __PRETTY_FUNCTION__))
;
266 pWin->Set();
267
268 if (pWin->GetSymbol() == SymbolType::ARROW_RIGHT)
269 {
270 // show expand button immediately
271 pWin->Show();
272 // outline content might not be folded, this happens on undo, outline moves, and folded outline content reveals
273 SwOutlineNodes::size_type nPos;
274 SwOutlineNodes rOutlineNds = m_pEditWin->GetView().GetWrtShell().GetNodes().GetOutLineNds();
275 if (rOutlineNds.Seek_Entry(const_cast<SwTextNode*>(pTextNd), &nPos))
276 {
277 // don't toggle if next node is an outline node or end node
278 SwNodeIndex aIdx(*pTextNd, 1);
279 if (!(aIdx.GetNode().IsEndNode() || ((nPos + 1 < rOutlineNds.size()) && &aIdx.GetNode() == rOutlineNds[nPos +1]))
280 && aIdx.GetNode().IsContentNode() && aIdx.GetNode().GetContentNode()->getLayoutFrame(nullptr))
281 {
282 m_pEditWin->GetView().GetWrtShell().ToggleOutlineContentVisibility(nPos, true); // force fold
283 }
284 }
285 }
286 else if (!pWin->IsVisible() && pWin->GetSymbol() == SymbolType::ARROW_DOWN)
287 pWin->ShowAll(true);
288}
289
290const SwPageFrame* SwFrameMenuButtonBase::GetPageFrame() const
291{
292 if (m_pFrame->IsPageFrame())
293 return static_cast<const SwPageFrame*>( m_pFrame );
294
295 if (m_pFrame->IsFlyFrame())
296 return static_cast<const SwFlyFrame*>(m_pFrame)->GetAnchorFrame()->FindPageFrame();
297
298 return m_pFrame->FindPageFrame();
299}
300
301void SwFrameMenuButtonBase::dispose()
302{
303 m_pEditWin.clear();
304 m_pFrame = nullptr;
305 MenuButton::dispose();
306}
307
308SwFrameControl::SwFrameControl( const VclPtr<vcl::Window> &pWindow )
309{
310 assert(static_cast<bool>(pWindow))(static_cast <bool> (static_cast<bool>(pWindow)) ?
void (0) : __assert_fail ("static_cast<bool>(pWindow)"
, "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/FrameControlsManager.cxx"
, 310, __extension__ __PRETTY_FUNCTION__))
;
311 mxWindow.reset( pWindow );
312 mpIFace = dynamic_cast<ISwFrameControl *>( pWindow.get() );
313}
314
315SwFrameControl::~SwFrameControl()
316{
317 mpIFace = nullptr;
318 mxWindow.disposeAndClear();
319}
320
321ISwFrameControl::~ISwFrameControl()
322{
323}
324
325/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
3
Memory is allocated
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
205 if (aTmp.get()) {
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/shared_ptr.h

1// shared_ptr and weak_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2007-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_H1
50#define _SHARED_PTR_H1 1
51
52#include <bits/shared_ptr_base.h>
53
54namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
55{
56_GLIBCXX_BEGIN_NAMESPACE_VERSION
57
58 /**
59 * @addtogroup pointer_abstractions
60 * @{
61 */
62
63 // 20.7.2.2.11 shared_ptr I/O
64
65 /// Write the stored pointer to an ostream.
66 /// @relates shared_ptr
67 template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
68 inline std::basic_ostream<_Ch, _Tr>&
69 operator<<(std::basic_ostream<_Ch, _Tr>& __os,
70 const __shared_ptr<_Tp, _Lp>& __p)
71 {
72 __os << __p.get();
73 return __os;
74 }
75
76 template<typename _Del, typename _Tp, _Lock_policy _Lp>
77 inline _Del*
78 get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
79 {
80#if __cpp_rtti199711L
81 return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
82#else
83 return 0;
84#endif
85 }
86
87 /// 20.7.2.2.10 shared_ptr get_deleter
88
89 /// If `__p` has a deleter of type `_Del`, return a pointer to it.
90 /// @relates shared_ptr
91 template<typename _Del, typename _Tp>
92 inline _Del*
93 get_deleter(const shared_ptr<_Tp>& __p) noexcept
94 {
95#if __cpp_rtti199711L
96 return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
97#else
98 return 0;
99#endif
100 }
101
102 /**
103 * @brief A smart pointer with reference-counted copy semantics.
104 *
105 * A `shared_ptr` object is either empty or _owns_ a pointer passed
106 * to the constructor. Copies of a `shared_ptr` share ownership of
107 * the same pointer. When the last `shared_ptr` that owns the pointer
108 * is destroyed or reset, the owned pointer is freed (either by `delete`
109 * or by invoking a custom deleter that was passed to the constructor).
110 *
111 * A `shared_ptr` also stores another pointer, which is usually
112 * (but not always) the same pointer as it owns. The stored pointer
113 * can be retrieved by calling the `get()` member function.
114 *
115 * The equality and relational operators for `shared_ptr` only compare
116 * the stored pointer returned by `get()`, not the owned pointer.
117 * To test whether two `shared_ptr` objects share ownership of the same
118 * pointer see `std::shared_ptr::owner_before` and `std::owner_less`.
119 */
120 template<typename _Tp>
121 class shared_ptr : public __shared_ptr<_Tp>
122 {
123 template<typename... _Args>
124 using _Constructible = typename enable_if<
125 is_constructible<__shared_ptr<_Tp>, _Args...>::value
126 >::type;
127
128 template<typename _Arg>
129 using _Assignable = typename enable_if<
130 is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
131 >::type;
132
133 public:
134
135 /// The type pointed to by the stored pointer, remove_extent_t<_Tp>
136 using element_type = typename __shared_ptr<_Tp>::element_type;
137
138#if __cplusplus201703L >= 201703L
139# define __cpp_lib_shared_ptr_weak_type201606 201606
140 /// The corresponding weak_ptr type for this shared_ptr
141 using weak_type = weak_ptr<_Tp>;
142#endif
143 /**
144 * @brief Construct an empty %shared_ptr.
145 * @post use_count()==0 && get()==0
146 */
147 constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
148
149 shared_ptr(const shared_ptr&) noexcept = default; ///< Copy constructor
150
151 /**
152 * @brief Construct a %shared_ptr that owns the pointer @a __p.
153 * @param __p A pointer that is convertible to element_type*.
154 * @post use_count() == 1 && get() == __p
155 * @throw std::bad_alloc, in which case @c delete @a __p is called.
156 */
157 template<typename _Yp, typename = _Constructible<_Yp*>>
158 explicit
159 shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
160
161 /**
162 * @brief Construct a %shared_ptr that owns the pointer @a __p
163 * and the deleter @a __d.
164 * @param __p A pointer.
165 * @param __d A deleter.
166 * @post use_count() == 1 && get() == __p
167 * @throw std::bad_alloc, in which case @a __d(__p) is called.
168 *
169 * Requirements: _Deleter's copy constructor and destructor must
170 * not throw
171 *
172 * __shared_ptr will release __p by calling __d(__p)
173 */
174 template<typename _Yp, typename _Deleter,
175 typename = _Constructible<_Yp*, _Deleter>>
176 shared_ptr(_Yp* __p, _Deleter __d)
177 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
178
179 /**
180 * @brief Construct a %shared_ptr that owns a null pointer
181 * and the deleter @a __d.
182 * @param __p A null pointer constant.
183 * @param __d A deleter.
184 * @post use_count() == 1 && get() == __p
185 * @throw std::bad_alloc, in which case @a __d(__p) is called.
186 *
187 * Requirements: _Deleter's copy constructor and destructor must
188 * not throw
189 *
190 * The last owner will call __d(__p)
191 */
192 template<typename _Deleter>
193 shared_ptr(nullptr_t __p, _Deleter __d)
194 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
195
196 /**
197 * @brief Construct a %shared_ptr that owns the pointer @a __p
198 * and the deleter @a __d.
199 * @param __p A pointer.
200 * @param __d A deleter.
201 * @param __a An allocator.
202 * @post use_count() == 1 && get() == __p
203 * @throw std::bad_alloc, in which case @a __d(__p) is called.
204 *
205 * Requirements: _Deleter's copy constructor and destructor must
206 * not throw _Alloc's copy constructor and destructor must not
207 * throw.
208 *
209 * __shared_ptr will release __p by calling __d(__p)
210 */
211 template<typename _Yp, typename _Deleter, typename _Alloc,
212 typename = _Constructible<_Yp*, _Deleter, _Alloc>>
213 shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
214 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
215
216 /**
217 * @brief Construct a %shared_ptr that owns a null pointer
218 * and the deleter @a __d.
219 * @param __p A null pointer constant.
220 * @param __d A deleter.
221 * @param __a An allocator.
222 * @post use_count() == 1 && get() == __p
223 * @throw std::bad_alloc, in which case @a __d(__p) is called.
224 *
225 * Requirements: _Deleter's copy constructor and destructor must
226 * not throw _Alloc's copy constructor and destructor must not
227 * throw.
228 *
229 * The last owner will call __d(__p)
230 */
231 template<typename _Deleter, typename _Alloc>
232 shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
233 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
234
235 // Aliasing constructor
236
237 /**
238 * @brief Constructs a `shared_ptr` instance that stores `__p`
239 * and shares ownership with `__r`.
240 * @param __r A `shared_ptr`.
241 * @param __p A pointer that will remain valid while `*__r` is valid.
242 * @post `get() == __p && use_count() == __r.use_count()`
243 *
244 * This can be used to construct a `shared_ptr` to a sub-object
245 * of an object managed by an existing `shared_ptr`. The complete
246 * object will remain valid while any `shared_ptr` owns it, even
247 * if they don't store a pointer to the complete object.
248 *
249 * @code
250 * shared_ptr<pair<int,int>> pii(new pair<int,int>());
251 * shared_ptr<int> pi(pii, &pii->first);
252 * assert(pii.use_count() == 2);
253 * @endcode
254 */
255 template<typename _Yp>
256 shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
257 : __shared_ptr<_Tp>(__r, __p) { }
258
259#if __cplusplus201703L > 201703L
260 // _GLIBCXX_RESOLVE_LIB_DEFECTS
261 // 2996. Missing rvalue overloads for shared_ptr operations
262 /**
263 * @brief Constructs a `shared_ptr` instance that stores `__p`
264 * and shares ownership with `__r`.
265 * @param __r A `shared_ptr`.
266 * @param __p A pointer that will remain valid while `*__r` is valid.
267 * @post `get() == __p && !__r.use_count() && !__r.get()`
268 *
269 * This can be used to construct a `shared_ptr` to a sub-object
270 * of an object managed by an existing `shared_ptr`. The complete
271 * object will remain valid while any `shared_ptr` owns it, even
272 * if they don't store a pointer to the complete object.
273 *
274 * @code
275 * shared_ptr<pair<int,int>> pii(new pair<int,int>());
276 * shared_ptr<int> pi1(pii, &pii->first);
277 * assert(pii.use_count() == 2);
278 * shared_ptr<int> pi2(std::move(pii), &pii->second);
279 * assert(pii.use_count() == 0);
280 * @endcode
281 */
282 template<typename _Yp>
283 shared_ptr(shared_ptr<_Yp>&& __r, element_type* __p) noexcept
284 : __shared_ptr<_Tp>(std::move(__r), __p) { }
285#endif
286 /**
287 * @brief If @a __r is empty, constructs an empty %shared_ptr;
288 * otherwise construct a %shared_ptr that shares ownership
289 * with @a __r.
290 * @param __r A %shared_ptr.
291 * @post get() == __r.get() && use_count() == __r.use_count()
292 */
293 template<typename _Yp,
294 typename = _Constructible<const shared_ptr<_Yp>&>>
295 shared_ptr(const shared_ptr<_Yp>& __r) noexcept
296 : __shared_ptr<_Tp>(__r) { }
297
298 /**
299 * @brief Move-constructs a %shared_ptr instance from @a __r.
300 * @param __r A %shared_ptr rvalue.
301 * @post *this contains the old value of @a __r, @a __r is empty.
302 */
303 shared_ptr(shared_ptr&& __r) noexcept
304 : __shared_ptr<_Tp>(std::move(__r)) { }
305
306 /**
307 * @brief Move-constructs a %shared_ptr instance from @a __r.
308 * @param __r A %shared_ptr rvalue.
309 * @post *this contains the old value of @a __r, @a __r is empty.
310 */
311 template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>
312 shared_ptr(shared_ptr<_Yp>&& __r) noexcept
313 : __shared_ptr<_Tp>(std::move(__r)) { }
314
315 /**
316 * @brief Constructs a %shared_ptr that shares ownership with @a __r
317 * and stores a copy of the pointer stored in @a __r.
318 * @param __r A weak_ptr.
319 * @post use_count() == __r.use_count()
320 * @throw bad_weak_ptr when __r.expired(),
321 * in which case the constructor has no effect.
322 */
323 template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
324 explicit shared_ptr(const weak_ptr<_Yp>& __r)
325 : __shared_ptr<_Tp>(__r) { }
326
327#if _GLIBCXX_USE_DEPRECATED1
328#pragma GCC diagnostic push
329#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
330 template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>
331 shared_ptr(auto_ptr<_Yp>&& __r);
332#pragma GCC diagnostic pop
333#endif
334
335 // _GLIBCXX_RESOLVE_LIB_DEFECTS
336 // 2399. shared_ptr's constructor from unique_ptr should be constrained
337 template<typename _Yp, typename _Del,
338 typename = _Constructible<unique_ptr<_Yp, _Del>>>
339 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
340 : __shared_ptr<_Tp>(std::move(__r)) { }
341
342#if __cplusplus201703L <= 201402L && _GLIBCXX_USE_DEPRECATED1
343 // This non-standard constructor exists to support conversions that
344 // were possible in C++11 and C++14 but are ill-formed in C++17.
345 // If an exception is thrown this constructor has no effect.
346 template<typename _Yp, typename _Del,
347 _Constructible<unique_ptr<_Yp, _Del>, __sp_array_delete>* = 0>
348 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
349 : __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) { }
350#endif
351
352 /**
353 * @brief Construct an empty %shared_ptr.
354 * @post use_count() == 0 && get() == nullptr
355 */
356 constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
357
358 shared_ptr& operator=(const shared_ptr&) noexcept = default;
359
360 template<typename _Yp>
361 _Assignable<const shared_ptr<_Yp>&>
362 operator=(const shared_ptr<_Yp>& __r) noexcept
363 {
364 this->__shared_ptr<_Tp>::operator=(__r);
365 return *this;
366 }
367
368#if _GLIBCXX_USE_DEPRECATED1
369#pragma GCC diagnostic push
370#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
371 template<typename _Yp>
372 _Assignable<auto_ptr<_Yp>>
373 operator=(auto_ptr<_Yp>&& __r)
374 {
375 this->__shared_ptr<_Tp>::operator=(std::move(__r));
376 return *this;
377 }
378#pragma GCC diagnostic pop
379#endif
380
381 shared_ptr&
382 operator=(shared_ptr&& __r) noexcept
383 {
384 this->__shared_ptr<_Tp>::operator=(std::move(__r));
385 return *this;
386 }
387
388 template<class _Yp>
389 _Assignable<shared_ptr<_Yp>>
390 operator=(shared_ptr<_Yp>&& __r) noexcept
391 {
392 this->__shared_ptr<_Tp>::operator=(std::move(__r));
393 return *this;
394 }
395
396 template<typename _Yp, typename _Del>
397 _Assignable<unique_ptr<_Yp, _Del>>
398 operator=(unique_ptr<_Yp, _Del>&& __r)
399 {
400 this->__shared_ptr<_Tp>::operator=(std::move(__r));
401 return *this;
402 }
403
404 private:
405 // This constructor is non-standard, it is used by allocate_shared.
406 template<typename _Alloc, typename... _Args>
407 shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
408 : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
8
Calling constructor for '__shared_ptr<SwFrameControl, __gnu_cxx::_S_atomic>'
27
Returning from constructor for '__shared_ptr<SwFrameControl, __gnu_cxx::_S_atomic>'
409 { }
410
411 template<typename _Yp, typename _Alloc, typename... _Args>
412 friend shared_ptr<_Yp>
413 allocate_shared(const _Alloc& __a, _Args&&... __args);
414
415 // This constructor is non-standard, it is used by weak_ptr::lock().
416 shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
417 : __shared_ptr<_Tp>(__r, std::nothrow) { }
418
419 friend class weak_ptr<_Tp>;
420 };
421
422#if __cpp_deduction_guides201703L >= 201606
423 template<typename _Tp>
424 shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>;
425 template<typename _Tp, typename _Del>
426 shared_ptr(unique_ptr<_Tp, _Del>) -> shared_ptr<_Tp>;
427#endif
428
429 // 20.7.2.2.7 shared_ptr comparisons
430
431 /// @relates shared_ptr @{
432
433 /// Equality operator for shared_ptr objects, compares the stored pointers
434 template<typename _Tp, typename _Up>
435 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
436 operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
437 { return __a.get() == __b.get(); }
438
439 /// shared_ptr comparison with nullptr
440 template<typename _Tp>
441 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
442 operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
443 { return !__a; }
444
445#ifdef __cpp_lib_three_way_comparison
446 template<typename _Tp, typename _Up>
447 inline strong_ordering
448 operator<=>(const shared_ptr<_Tp>& __a,
449 const shared_ptr<_Up>& __b) noexcept
450 { return compare_three_way()(__a.get(), __b.get()); }
451
452 template<typename _Tp>
453 inline strong_ordering
454 operator<=>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
455 {
456 using pointer = typename shared_ptr<_Tp>::element_type*;
457 return compare_three_way()(__a.get(), static_cast<pointer>(nullptr));
458 }
459#else
460 /// shared_ptr comparison with nullptr
461 template<typename _Tp>
462 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
463 operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
464 { return !__a; }
465
466 /// Inequality operator for shared_ptr objects, compares the stored pointers
467 template<typename _Tp, typename _Up>
468 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
469 operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
470 { return __a.get() != __b.get(); }
471
472 /// shared_ptr comparison with nullptr
473 template<typename _Tp>
474 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
475 operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
476 { return (bool)__a; }
477
478 /// shared_ptr comparison with nullptr
479 template<typename _Tp>
480 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
481 operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
482 { return (bool)__a; }
483
484 /// Relational operator for shared_ptr objects, compares the stored pointers
485 template<typename _Tp, typename _Up>
486 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
487 operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
488 {
489 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
490 using _Up_elt = typename shared_ptr<_Up>::element_type;
491 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
492 return less<_Vp>()(__a.get(), __b.get());
493 }
494
495 /// shared_ptr comparison with nullptr
496 template<typename _Tp>
497 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
498 operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
499 {
500 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
501 return less<_Tp_elt*>()(__a.get(), nullptr);
502 }
503
504 /// shared_ptr comparison with nullptr
505 template<typename _Tp>
506 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
507 operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
508 {
509 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
510 return less<_Tp_elt*>()(nullptr, __a.get());
511 }
512
513 /// Relational operator for shared_ptr objects, compares the stored pointers
514 template<typename _Tp, typename _Up>
515 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
516 operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
517 { return !(__b < __a); }
518
519 /// shared_ptr comparison with nullptr
520 template<typename _Tp>
521 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
522 operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
523 { return !(nullptr < __a); }
524
525 /// shared_ptr comparison with nullptr
526 template<typename _Tp>
527 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
528 operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
529 { return !(__a < nullptr); }
530
531 /// Relational operator for shared_ptr objects, compares the stored pointers
532 template<typename _Tp, typename _Up>
533 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
534 operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
535 { return (__b < __a); }
536
537 /// shared_ptr comparison with nullptr
538 template<typename _Tp>
539 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
540 operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
541 { return nullptr < __a; }
542
543 /// shared_ptr comparison with nullptr
544 template<typename _Tp>
545 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
546 operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
547 { return __a < nullptr; }
548
549 /// Relational operator for shared_ptr objects, compares the stored pointers
550 template<typename _Tp, typename _Up>
551 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
552 operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
553 { return !(__a < __b); }
554
555 /// shared_ptr comparison with nullptr
556 template<typename _Tp>
557 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
558 operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
559 { return !(__a < nullptr); }
560
561 /// shared_ptr comparison with nullptr
562 template<typename _Tp>
563 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
564 operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
565 { return !(nullptr < __a); }
566#endif
567
568 // 20.7.2.2.8 shared_ptr specialized algorithms.
569
570 /// Swap overload for shared_ptr
571 template<typename _Tp>
572 inline void
573 swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
574 { __a.swap(__b); }
575
576 // 20.7.2.2.9 shared_ptr casts.
577
578 /// Convert type of `shared_ptr`, via `static_cast`
579 template<typename _Tp, typename _Up>
580 inline shared_ptr<_Tp>
581 static_pointer_cast(const shared_ptr<_Up>& __r) noexcept
582 {
583 using _Sp = shared_ptr<_Tp>;
584 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
585 }
586
587 /// Convert type of `shared_ptr`, via `const_cast`
588 template<typename _Tp, typename _Up>
589 inline shared_ptr<_Tp>
590 const_pointer_cast(const shared_ptr<_Up>& __r) noexcept
591 {
592 using _Sp = shared_ptr<_Tp>;
593 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
594 }
595
596 /// Convert type of `shared_ptr`, via `dynamic_cast`
597 template<typename _Tp, typename _Up>
598 inline shared_ptr<_Tp>
599 dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
600 {
601 using _Sp = shared_ptr<_Tp>;
602 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
603 return _Sp(__r, __p);
604 return _Sp();
605 }
606
607#if __cplusplus201703L >= 201703L
608 /// Convert type of `shared_ptr`, via `reinterpret_cast`
609 template<typename _Tp, typename _Up>
610 inline shared_ptr<_Tp>
611 reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept
612 {
613 using _Sp = shared_ptr<_Tp>;
614 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
615 }
616
617#if __cplusplus201703L > 201703L
618 // _GLIBCXX_RESOLVE_LIB_DEFECTS
619 // 2996. Missing rvalue overloads for shared_ptr operations
620
621 /// Convert type of `shared_ptr` rvalue, via `static_cast`
622 template<typename _Tp, typename _Up>
623 inline shared_ptr<_Tp>
624 static_pointer_cast(shared_ptr<_Up>&& __r) noexcept
625 {
626 using _Sp = shared_ptr<_Tp>;
627 return _Sp(std::move(__r),
628 static_cast<typename _Sp::element_type*>(__r.get()));
629 }
630
631 /// Convert type of `shared_ptr` rvalue, via `const_cast`
632 template<typename _Tp, typename _Up>
633 inline shared_ptr<_Tp>
634 const_pointer_cast(shared_ptr<_Up>&& __r) noexcept
635 {
636 using _Sp = shared_ptr<_Tp>;
637 return _Sp(std::move(__r),
638 const_cast<typename _Sp::element_type*>(__r.get()));
639 }
640
641 /// Convert type of `shared_ptr` rvalue, via `dynamic_cast`
642 template<typename _Tp, typename _Up>
643 inline shared_ptr<_Tp>
644 dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept
645 {
646 using _Sp = shared_ptr<_Tp>;
647 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
648 return _Sp(std::move(__r), __p);
649 return _Sp();
650 }
651
652 /// Convert type of `shared_ptr` rvalue, via `reinterpret_cast`
653 template<typename _Tp, typename _Up>
654 inline shared_ptr<_Tp>
655 reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept
656 {
657 using _Sp = shared_ptr<_Tp>;
658 return _Sp(std::move(__r),
659 reinterpret_cast<typename _Sp::element_type*>(__r.get()));
660 }
661#endif // C++20
662#endif // C++17
663
664 // @}
665
666 /**
667 * @brief A non-owning observer for a pointer owned by a shared_ptr
668 *
669 * A weak_ptr provides a safe alternative to a raw pointer when you want
670 * a non-owning reference to an object that is managed by a shared_ptr.
671 *
672 * Unlike a raw pointer, a weak_ptr can be converted to a new shared_ptr
673 * that shares ownership with every other shared_ptr that already owns
674 * the pointer. In other words you can upgrade from a non-owning "weak"
675 * reference to an owning shared_ptr, without having access to any of
676 * the existing shared_ptr objects.
677 *
678 * Also unlike a raw pointer, a weak_ptr does not become "dangling" after
679 * the object it points to has been destroyed. Instead, a weak_ptr
680 * becomes _expired_ and can no longer be converted to a shared_ptr that
681 * owns the freed pointer, so you cannot accidentally access the pointed-to
682 * object after it has been destroyed.
683 */
684 template<typename _Tp>
685 class weak_ptr : public __weak_ptr<_Tp>
686 {
687 template<typename _Arg>
688 using _Constructible = typename enable_if<
689 is_constructible<__weak_ptr<_Tp>, _Arg>::value
690 >::type;
691
692 template<typename _Arg>
693 using _Assignable = typename enable_if<
694 is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr&
695 >::type;
696
697 public:
698 constexpr weak_ptr() noexcept = default;
699
700 template<typename _Yp,
701 typename = _Constructible<const shared_ptr<_Yp>&>>
702 weak_ptr(const shared_ptr<_Yp>& __r) noexcept
703 : __weak_ptr<_Tp>(__r) { }
704
705 weak_ptr(const weak_ptr&) noexcept = default;
706
707 template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
708 weak_ptr(const weak_ptr<_Yp>& __r) noexcept
709 : __weak_ptr<_Tp>(__r) { }
710
711 weak_ptr(weak_ptr&&) noexcept = default;
712
713 template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
714 weak_ptr(weak_ptr<_Yp>&& __r) noexcept
715 : __weak_ptr<_Tp>(std::move(__r)) { }
716
717 weak_ptr&
718 operator=(const weak_ptr& __r) noexcept = default;
719
720 template<typename _Yp>
721 _Assignable<const weak_ptr<_Yp>&>
722 operator=(const weak_ptr<_Yp>& __r) noexcept
723 {
724 this->__weak_ptr<_Tp>::operator=(__r);
725 return *this;
726 }
727
728 template<typename _Yp>
729 _Assignable<const shared_ptr<_Yp>&>
730 operator=(const shared_ptr<_Yp>& __r) noexcept
731 {
732 this->__weak_ptr<_Tp>::operator=(__r);
733 return *this;
734 }
735
736 weak_ptr&
737 operator=(weak_ptr&& __r) noexcept = default;
738
739 template<typename _Yp>
740 _Assignable<weak_ptr<_Yp>>
741 operator=(weak_ptr<_Yp>&& __r) noexcept
742 {
743 this->__weak_ptr<_Tp>::operator=(std::move(__r));
744 return *this;
745 }
746
747 shared_ptr<_Tp>
748 lock() const noexcept
749 { return shared_ptr<_Tp>(*this, std::nothrow); }
750 };
751
752#if __cpp_deduction_guides201703L >= 201606
753 template<typename _Tp>
754 weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>;
755#endif
756
757 // 20.7.2.3.6 weak_ptr specialized algorithms.
758 /// Swap overload for weak_ptr
759 /// @relates weak_ptr
760 template<typename _Tp>
761 inline void
762 swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
763 { __a.swap(__b); }
764
765
766 /// Primary template owner_less
767 template<typename _Tp = void>
768 struct owner_less;
769
770 /// Void specialization of owner_less compares either shared_ptr or weak_ptr
771 template<>
772 struct owner_less<void> : _Sp_owner_less<void, void>
773 { };
774
775 /// Partial specialization of owner_less for shared_ptr.
776 template<typename _Tp>
777 struct owner_less<shared_ptr<_Tp>>
778 : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
779 { };
780
781 /// Partial specialization of owner_less for weak_ptr.
782 template<typename _Tp>
783 struct owner_less<weak_ptr<_Tp>>
784 : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
785 { };
786
787 /**
788 * @brief Base class allowing use of member function shared_from_this.
789 */
790 template<typename _Tp>
791 class enable_shared_from_this
792 {
793 protected:
794 constexpr enable_shared_from_this() noexcept { }
795
796 enable_shared_from_this(const enable_shared_from_this&) noexcept { }
797
798 enable_shared_from_this&
799 operator=(const enable_shared_from_this&) noexcept
800 { return *this; }
801
802 ~enable_shared_from_this() { }
803
804 public:
805 shared_ptr<_Tp>
806 shared_from_this()
807 { return shared_ptr<_Tp>(this->_M_weak_this); }
808
809 shared_ptr<const _Tp>
810 shared_from_this() const
811 { return shared_ptr<const _Tp>(this->_M_weak_this); }
812
813#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
814#define __cpp_lib_enable_shared_from_this201603 201603
815 weak_ptr<_Tp>
816 weak_from_this() noexcept
817 { return this->_M_weak_this; }
818
819 weak_ptr<const _Tp>
820 weak_from_this() const noexcept
821 { return this->_M_weak_this; }
822#endif
823
824 private:
825 template<typename _Tp1>
826 void
827 _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
828 { _M_weak_this._M_assign(__p, __n); }
829
830 // Found by ADL when this is an associated class.
831 friend const enable_shared_from_this*
832 __enable_shared_from_this_base(const __shared_count<>&,
833 const enable_shared_from_this* __p)
834 { return __p; }
835
836 template<typename, _Lock_policy>
837 friend class __shared_ptr;
838
839 mutable weak_ptr<_Tp> _M_weak_this;
840 };
841
842 /// @relates shared_ptr @{
843
844 /**
845 * @brief Create an object that is owned by a shared_ptr.
846 * @param __a An allocator.
847 * @param __args Arguments for the @a _Tp object's constructor.
848 * @return A shared_ptr that owns the newly created object.
849 * @throw An exception thrown from @a _Alloc::allocate or from the
850 * constructor of @a _Tp.
851 *
852 * A copy of @a __a will be used to allocate memory for the shared_ptr
853 * and the new object.
854 */
855 template<typename _Tp, typename _Alloc, typename... _Args>
856 inline shared_ptr<_Tp>
857 allocate_shared(const _Alloc& __a, _Args&&... __args)
858 {
859 return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
7
Calling constructor for 'shared_ptr<SwFrameControl>'
28
Returning from constructor for 'shared_ptr<SwFrameControl>'
860 std::forward<_Args>(__args)...);
861 }
862
863 /**
864 * @brief Create an object that is owned by a shared_ptr.
865 * @param __args Arguments for the @a _Tp object's constructor.
866 * @return A shared_ptr that owns the newly created object.
867 * @throw std::bad_alloc, or an exception thrown from the
868 * constructor of @a _Tp.
869 */
870 template<typename _Tp, typename... _Args>
871 inline shared_ptr<_Tp>
872 make_shared(_Args&&... __args)
873 {
874 typedef typename std::remove_cv<_Tp>::type _Tp_nc;
875 return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
6
Calling 'allocate_shared<SwFrameControl, std::allocator<SwFrameControl>, SwPageBreakWin *>'
29
Returning; memory was released via 2nd parameter
876 std::forward<_Args>(__args)...);
877 }
878
879 /// std::hash specialization for shared_ptr.
880 template<typename _Tp>
881 struct hash<shared_ptr<_Tp>>
882 : public __hash_base<size_t, shared_ptr<_Tp>>
883 {
884 size_t
885 operator()(const shared_ptr<_Tp>& __s) const noexcept
886 {
887 return std::hash<typename shared_ptr<_Tp>::element_type*>()(__s.get());
888 }
889 };
890
891 // @} relates shared_ptr
892 // @} group pointer_abstractions
893
894#if __cplusplus201703L >= 201703L
895 namespace __detail::__variant
896 {
897 template<typename> struct _Never_valueless_alt; // see <variant>
898
899 // Provide the strong exception-safety guarantee when emplacing a
900 // shared_ptr into a variant.
901 template<typename _Tp>
902 struct _Never_valueless_alt<std::shared_ptr<_Tp>>
903 : std::true_type
904 { };
905
906 // Provide the strong exception-safety guarantee when emplacing a
907 // weak_ptr into a variant.
908 template<typename _Tp>
909 struct _Never_valueless_alt<std::weak_ptr<_Tp>>
910 : std::true_type
911 { };
912 } // namespace __detail::__variant
913#endif // C++17
914
915_GLIBCXX_END_NAMESPACE_VERSION
916} // namespace
917
918#endif // _SHARED_PTR_H

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/shared_ptr_base.h

1// shared_ptr and weak_ptr implementation details -*- C++ -*-
2
3// Copyright (C) 2007-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file bits/shared_ptr_base.h
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_BASE_H1
50#define _SHARED_PTR_BASE_H1 1
51
52#include <typeinfo>
53#include <bits/allocated_ptr.h>
54#include <bits/refwrap.h>
55#include <bits/stl_function.h>
56#include <ext/aligned_buffer.h>
57#if __cplusplus201703L > 201703L
58# include <compare>
59#endif
60
61namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
62{
63_GLIBCXX_BEGIN_NAMESPACE_VERSION
64
65#if _GLIBCXX_USE_DEPRECATED1
66#pragma GCC diagnostic push
67#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
68 template<typename> class auto_ptr;
69#pragma GCC diagnostic pop
70#endif
71
72 /**
73 * @brief Exception possibly thrown by @c shared_ptr.
74 * @ingroup exceptions
75 */
76 class bad_weak_ptr : public std::exception
77 {
78 public:
79 virtual char const* what() const noexcept;
80
81 virtual ~bad_weak_ptr() noexcept;
82 };
83
84 // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
85 inline void
86 __throw_bad_weak_ptr()
87 { _GLIBCXX_THROW_OR_ABORT(bad_weak_ptr())(throw (bad_weak_ptr())); }
88
89 using __gnu_cxx::_Lock_policy;
90 using __gnu_cxx::__default_lock_policy;
91 using __gnu_cxx::_S_single;
92 using __gnu_cxx::_S_mutex;
93 using __gnu_cxx::_S_atomic;
94
95 // Empty helper class except when the template argument is _S_mutex.
96 template<_Lock_policy _Lp>
97 class _Mutex_base
98 {
99 protected:
100 // The atomic policy uses fully-fenced builtins, single doesn't care.
101 enum { _S_need_barriers = 0 };
102 };
103
104 template<>
105 class _Mutex_base<_S_mutex>
106 : public __gnu_cxx::__mutex
107 {
108 protected:
109 // This policy is used when atomic builtins are not available.
110 // The replacement atomic operations might not have the necessary
111 // memory barriers.
112 enum { _S_need_barriers = 1 };
113 };
114
115 template<_Lock_policy _Lp = __default_lock_policy>
116 class _Sp_counted_base
117 : public _Mutex_base<_Lp>
118 {
119 public:
120 _Sp_counted_base() noexcept
121 : _M_use_count(1), _M_weak_count(1) { }
122
123 virtual
124 ~_Sp_counted_base() noexcept
125 { }
126
127 // Called when _M_use_count drops to zero, to release the resources
128 // managed by *this.
129 virtual void
130 _M_dispose() noexcept = 0;
131
132 // Called when _M_weak_count drops to zero.
133 virtual void
134 _M_destroy() noexcept
135 { delete this; }
136
137 virtual void*
138 _M_get_deleter(const std::type_info&) noexcept = 0;
139
140 void
141 _M_add_ref_copy()
142 { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
143
144 void
145 _M_add_ref_lock();
146
147 bool
148 _M_add_ref_lock_nothrow();
149
150 void
151 _M_release() noexcept
152 {
153 // Be race-detector-friendly. For more info see bits/c++config.
154 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
155 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
156 {
157 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
158 _M_dispose();
159 // There must be a memory barrier between dispose() and destroy()
160 // to ensure that the effects of dispose() are observed in the
161 // thread that runs destroy().
162 // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
163 if (_Mutex_base<_Lp>::_S_need_barriers)
164 {
165 __atomic_thread_fence (__ATOMIC_ACQ_REL4);
166 }
167
168 // Be race-detector-friendly. For more info see bits/c++config.
169 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
170 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
171 -1) == 1)
172 {
173 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
174 _M_destroy();
175 }
176 }
177 }
178
179 void
180 _M_weak_add_ref() noexcept
181 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
182
183 void
184 _M_weak_release() noexcept
185 {
186 // Be race-detector-friendly. For more info see bits/c++config.
187 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
188 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
189 {
190 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
191 if (_Mutex_base<_Lp>::_S_need_barriers)
192 {
193 // See _M_release(),
194 // destroy() must observe results of dispose()
195 __atomic_thread_fence (__ATOMIC_ACQ_REL4);
196 }
197 _M_destroy();
198 }
199 }
200
201 long
202 _M_get_use_count() const noexcept
203 {
204 // No memory barrier is used here so there is no synchronization
205 // with other threads.
206 return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED0);
207 }
208
209 private:
210 _Sp_counted_base(_Sp_counted_base const&) = delete;
211 _Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
212
213 _Atomic_word _M_use_count; // #shared
214 _Atomic_word _M_weak_count; // #weak + (#shared != 0)
215 };
216
217 template<>
218 inline void
219 _Sp_counted_base<_S_single>::
220 _M_add_ref_lock()
221 {
222 if (_M_use_count == 0)
223 __throw_bad_weak_ptr();
224 ++_M_use_count;
225 }
226
227 template<>
228 inline void
229 _Sp_counted_base<_S_mutex>::
230 _M_add_ref_lock()
231 {
232 __gnu_cxx::__scoped_lock sentry(*this);
233 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
234 {
235 _M_use_count = 0;
236 __throw_bad_weak_ptr();
237 }
238 }
239
240 template<>
241 inline void
242 _Sp_counted_base<_S_atomic>::
243 _M_add_ref_lock()
244 {
245 // Perform lock-free add-if-not-zero operation.
246 _Atomic_word __count = _M_get_use_count();
247 do
248 {
249 if (__count == 0)
250 __throw_bad_weak_ptr();
251 // Replace the current counter value with the old value + 1, as
252 // long as it's not changed meanwhile.
253 }
254 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
255 true, __ATOMIC_ACQ_REL4,
256 __ATOMIC_RELAXED0));
257 }
258
259 template<>
260 inline bool
261 _Sp_counted_base<_S_single>::
262 _M_add_ref_lock_nothrow()
263 {
264 if (_M_use_count == 0)
265 return false;
266 ++_M_use_count;
267 return true;
268 }
269
270 template<>
271 inline bool
272 _Sp_counted_base<_S_mutex>::
273 _M_add_ref_lock_nothrow()
274 {
275 __gnu_cxx::__scoped_lock sentry(*this);
276 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
277 {
278 _M_use_count = 0;
279 return false;
280 }
281 return true;
282 }
283
284 template<>
285 inline bool
286 _Sp_counted_base<_S_atomic>::
287 _M_add_ref_lock_nothrow()
288 {
289 // Perform lock-free add-if-not-zero operation.
290 _Atomic_word __count = _M_get_use_count();
291 do
292 {
293 if (__count == 0)
294 return false;
295 // Replace the current counter value with the old value + 1, as
296 // long as it's not changed meanwhile.
297 }
298 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
299 true, __ATOMIC_ACQ_REL4,
300 __ATOMIC_RELAXED0));
301 return true;
302 }
303
304 template<>
305 inline void
306 _Sp_counted_base<_S_single>::_M_add_ref_copy()
307 { ++_M_use_count; }
308
309 template<>
310 inline void
311 _Sp_counted_base<_S_single>::_M_release() noexcept
312 {
313 if (--_M_use_count == 0)
314 {
315 _M_dispose();
316 if (--_M_weak_count == 0)
317 _M_destroy();
318 }
319 }
320
321 template<>
322 inline void
323 _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept
324 { ++_M_weak_count; }
325
326 template<>
327 inline void
328 _Sp_counted_base<_S_single>::_M_weak_release() noexcept
329 {
330 if (--_M_weak_count == 0)
331 _M_destroy();
332 }
333
334 template<>
335 inline long
336 _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
337 { return _M_use_count; }
338
339
340 // Forward declarations.
341 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
342 class __shared_ptr;
343
344 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
345 class __weak_ptr;
346
347 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
348 class __enable_shared_from_this;
349
350 template<typename _Tp>
351 class shared_ptr;
352
353 template<typename _Tp>
354 class weak_ptr;
355
356 template<typename _Tp>
357 struct owner_less;
358
359 template<typename _Tp>
360 class enable_shared_from_this;
361
362 template<_Lock_policy _Lp = __default_lock_policy>
363 class __weak_count;
364
365 template<_Lock_policy _Lp = __default_lock_policy>
366 class __shared_count;
367
368
369 // Counted ptr with no deleter or allocator support
370 template<typename _Ptr, _Lock_policy _Lp>
371 class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
372 {
373 public:
374 explicit
375 _Sp_counted_ptr(_Ptr __p) noexcept
376 : _M_ptr(__p) { }
377
378 virtual void
379 _M_dispose() noexcept
380 { delete _M_ptr; }
381
382 virtual void
383 _M_destroy() noexcept
384 { delete this; }
385
386 virtual void*
387 _M_get_deleter(const std::type_info&) noexcept
388 { return nullptr; }
389
390 _Sp_counted_ptr(const _Sp_counted_ptr&) = delete;
391 _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete;
392
393 private:
394 _Ptr _M_ptr;
395 };
396
397 template<>
398 inline void
399 _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() noexcept { }
400
401 template<>
402 inline void
403 _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() noexcept { }
404
405 template<>
406 inline void
407 _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { }
408
409 template<int _Nm, typename _Tp,
410 bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)>
411 struct _Sp_ebo_helper;
412
413 /// Specialization using EBO.
414 template<int _Nm, typename _Tp>
415 struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp
416 {
417 explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { }
418 explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { }
419
420 static _Tp&
421 _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); }
422 };
423
424 /// Specialization not using EBO.
425 template<int _Nm, typename _Tp>
426 struct _Sp_ebo_helper<_Nm, _Tp, false>
427 {
428 explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { }
429 explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { }
430
431 static _Tp&
432 _S_get(_Sp_ebo_helper& __eboh)
433 { return __eboh._M_tp; }
434
435 private:
436 _Tp _M_tp;
437 };
438
439 // Support for custom deleter and/or allocator
440 template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
441 class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
442 {
443 class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>
444 {
445 typedef _Sp_ebo_helper<0, _Deleter> _Del_base;
446 typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;
447
448 public:
449 _Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
450 : _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a)
451 { }
452
453 _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }
454 _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }
455
456 _Ptr _M_ptr;
457 };
458
459 public:
460 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>;
461
462 // __d(__p) must not throw.
463 _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept
464 : _M_impl(__p, std::move(__d), _Alloc()) { }
465
466 // __d(__p) must not throw.
467 _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
468 : _M_impl(__p, std::move(__d), __a) { }
469
470 ~_Sp_counted_deleter() noexcept { }
471
472 virtual void
473 _M_dispose() noexcept
474 { _M_impl._M_del()(_M_impl._M_ptr); }
475
476 virtual void
477 _M_destroy() noexcept
478 {
479 __allocator_type __a(_M_impl._M_alloc());
480 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
481 this->~_Sp_counted_deleter();
482 }
483
484 virtual void*
485 _M_get_deleter(const std::type_info& __ti) noexcept
486 {
487#if __cpp_rtti199711L
488 // _GLIBCXX_RESOLVE_LIB_DEFECTS
489 // 2400. shared_ptr's get_deleter() should use addressof()
490 return __ti == typeid(_Deleter)
491 ? std::__addressof(_M_impl._M_del())
492 : nullptr;
493#else
494 return nullptr;
495#endif
496 }
497
498 private:
499 _Impl _M_impl;
500 };
501
502 // helpers for make_shared / allocate_shared
503
504 struct _Sp_make_shared_tag
505 {
506 private:
507 template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
508 friend class _Sp_counted_ptr_inplace;
509
510 static const type_info&
511 _S_ti() noexcept _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
512 {
513 alignas(type_info) static constexpr char __tag[sizeof(type_info)] = { };
514 return reinterpret_cast<const type_info&>(__tag);
515 }
516
517 static bool _S_eq(const type_info&) noexcept;
518 };
519
520 template<typename _Alloc>
521 struct _Sp_alloc_shared_tag
522 {
523 const _Alloc& _M_a;
524 };
525
526 template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
527 class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>
528 {
529 class _Impl : _Sp_ebo_helper<0, _Alloc>
530 {
531 typedef _Sp_ebo_helper<0, _Alloc> _A_base;
532
533 public:
534 explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { }
535
536 _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); }
537
538 __gnu_cxx::__aligned_buffer<_Tp> _M_storage;
539 };
540
541 public:
542 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;
543
544 // Alloc parameter is not a reference so doesn't alias anything in __args
545 template<typename... _Args>
546 _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
547 : _M_impl(__a)
548 {
549 // _GLIBCXX_RESOLVE_LIB_DEFECTS
550 // 2070. allocate_shared should use allocator_traits<A>::construct
551 allocator_traits<_Alloc>::construct(__a, _M_ptr(),
11
Calling 'allocator_traits::construct'
24
Returning; memory was released via 3rd parameter
552 std::forward<_Args>(__args)...); // might throw
553 }
554
555 ~_Sp_counted_ptr_inplace() noexcept { }
556
557 virtual void
558 _M_dispose() noexcept
559 {
560 allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());
561 }
562
563 // Override because the allocator needs to know the dynamic type
564 virtual void
565 _M_destroy() noexcept
566 {
567 __allocator_type __a(_M_impl._M_alloc());
568 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
569 this->~_Sp_counted_ptr_inplace();
570 }
571
572 private:
573 friend class __shared_count<_Lp>; // To be able to call _M_ptr().
574
575 // No longer used, but code compiled against old libstdc++ headers
576 // might still call it from __shared_ptr ctor to get the pointer out.
577 virtual void*
578 _M_get_deleter(const std::type_info& __ti) noexcept override
579 {
580 auto __ptr = const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());
581 // Check for the fake type_info first, so we don't try to access it
582 // as a real type_info object. Otherwise, check if it's the real
583 // type_info for this class. With RTTI enabled we can check directly,
584 // or call a library function to do it.
585 if (&__ti == &_Sp_make_shared_tag::_S_ti()
586 ||
587#if __cpp_rtti199711L
588 __ti == typeid(_Sp_make_shared_tag)
589#else
590 _Sp_make_shared_tag::_S_eq(__ti)
591#endif
592 )
593 return __ptr;
594 return nullptr;
595 }
596
597 _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
598
599 _Impl _M_impl;
600 };
601
602 // The default deleter for shared_ptr<T[]> and shared_ptr<T[N]>.
603 struct __sp_array_delete
604 {
605 template<typename _Yp>
606 void operator()(_Yp* __p) const { delete[] __p; }
607 };
608
609 template<_Lock_policy _Lp>
610 class __shared_count
611 {
612 template<typename _Tp>
613 struct __not_alloc_shared_tag { using type = void; };
614
615 template<typename _Tp>
616 struct __not_alloc_shared_tag<_Sp_alloc_shared_tag<_Tp>> { };
617
618 public:
619 constexpr __shared_count() noexcept : _M_pi(0)
620 { }
621
622 template<typename _Ptr>
623 explicit
624 __shared_count(_Ptr __p) : _M_pi(0)
625 {
626 __trytry
627 {
628 _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
629 }
630 __catch(...)catch(...)
631 {
632 delete __p;
633 __throw_exception_againthrow;
634 }
635 }
636
637 template<typename _Ptr>
638 __shared_count(_Ptr __p, /* is_array = */ false_type)
639 : __shared_count(__p)
640 { }
641
642 template<typename _Ptr>
643 __shared_count(_Ptr __p, /* is_array = */ true_type)
644 : __shared_count(__p, __sp_array_delete{}, allocator<void>())
645 { }
646
647 template<typename _Ptr, typename _Deleter,
648 typename = typename __not_alloc_shared_tag<_Deleter>::type>
649 __shared_count(_Ptr __p, _Deleter __d)
650 : __shared_count(__p, std::move(__d), allocator<void>())
651 { }
652
653 template<typename _Ptr, typename _Deleter, typename _Alloc,
654 typename = typename __not_alloc_shared_tag<_Deleter>::type>
655 __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
656 {
657 typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
658 __trytry
659 {
660 typename _Sp_cd_type::__allocator_type __a2(__a);
661 auto __guard = std::__allocate_guarded(__a2);
662 _Sp_cd_type* __mem = __guard.get();
663 ::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));
664 _M_pi = __mem;
665 __guard = nullptr;
666 }
667 __catch(...)catch(...)
668 {
669 __d(__p); // Call _Deleter on __p.
670 __throw_exception_againthrow;
671 }
672 }
673
674 template<typename _Tp, typename _Alloc, typename... _Args>
675 __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a,
676 _Args&&... __args)
677 {
678 typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;
679 typename _Sp_cp_type::__allocator_type __a2(__a._M_a);
680 auto __guard = std::__allocate_guarded(__a2);
681 _Sp_cp_type* __mem = __guard.get();
682 auto __pi = ::new (__mem)
683 _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...);
10
Calling constructor for '_Sp_counted_ptr_inplace<SwFrameControl, std::allocator<SwFrameControl>, __gnu_cxx::_S_atomic>'
25
Returning from constructor for '_Sp_counted_ptr_inplace<SwFrameControl, std::allocator<SwFrameControl>, __gnu_cxx::_S_atomic>'
684 __guard = nullptr;
685 _M_pi = __pi;
686 __p = __pi->_M_ptr();
687 }
688
689#if _GLIBCXX_USE_DEPRECATED1
690#pragma GCC diagnostic push
691#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
692 // Special case for auto_ptr<_Tp> to provide the strong guarantee.
693 template<typename _Tp>
694 explicit
695 __shared_count(std::auto_ptr<_Tp>&& __r);
696#pragma GCC diagnostic pop
697#endif
698
699 // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
700 template<typename _Tp, typename _Del>
701 explicit
702 __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0)
703 {
704 // _GLIBCXX_RESOLVE_LIB_DEFECTS
705 // 2415. Inconsistency between unique_ptr and shared_ptr
706 if (__r.get() == nullptr)
707 return;
708
709 using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;
710 using _Del2 = typename conditional<is_reference<_Del>::value,
711 reference_wrapper<typename remove_reference<_Del>::type>,
712 _Del>::type;
713 using _Sp_cd_type
714 = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;
715 using _Alloc = allocator<_Sp_cd_type>;
716 using _Alloc_traits = allocator_traits<_Alloc>;
717 _Alloc __a;
718 _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);
719 _Alloc_traits::construct(__a, __mem, __r.release(),
720 __r.get_deleter()); // non-throwing
721 _M_pi = __mem;
722 }
723
724 // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
725 explicit __shared_count(const __weak_count<_Lp>& __r);
726
727 // Does not throw if __r._M_get_use_count() == 0, caller must check.
728 explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t);
729
730 ~__shared_count() noexcept
731 {
732 if (_M_pi != nullptr)
733 _M_pi->_M_release();
734 }
735
736 __shared_count(const __shared_count& __r) noexcept
737 : _M_pi(__r._M_pi)
738 {
739 if (_M_pi != 0)
740 _M_pi->_M_add_ref_copy();
741 }
742
743 __shared_count&
744 operator=(const __shared_count& __r) noexcept
745 {
746 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
747 if (__tmp != _M_pi)
748 {
749 if (__tmp != 0)
750 __tmp->_M_add_ref_copy();
751 if (_M_pi != 0)
752 _M_pi->_M_release();
753 _M_pi = __tmp;
754 }
755 return *this;
756 }
757
758 void
759 _M_swap(__shared_count& __r) noexcept
760 {
761 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
762 __r._M_pi = _M_pi;
763 _M_pi = __tmp;
764 }
765
766 long
767 _M_get_use_count() const noexcept
768 { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
769
770 bool
771 _M_unique() const noexcept
772 { return this->_M_get_use_count() == 1; }
773
774 void*
775 _M_get_deleter(const std::type_info& __ti) const noexcept
776 { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; }
777
778 bool
779 _M_less(const __shared_count& __rhs) const noexcept
780 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
781
782 bool
783 _M_less(const __weak_count<_Lp>& __rhs) const noexcept
784 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
785
786 // Friend function injected into enclosing namespace and found by ADL
787 friend inline bool
788 operator==(const __shared_count& __a, const __shared_count& __b) noexcept
789 { return __a._M_pi == __b._M_pi; }
790
791 private:
792 friend class __weak_count<_Lp>;
793
794 _Sp_counted_base<_Lp>* _M_pi;
795 };
796
797
798 template<_Lock_policy _Lp>
799 class __weak_count
800 {
801 public:
802 constexpr __weak_count() noexcept : _M_pi(nullptr)
803 { }
804
805 __weak_count(const __shared_count<_Lp>& __r) noexcept
806 : _M_pi(__r._M_pi)
807 {
808 if (_M_pi != nullptr)
809 _M_pi->_M_weak_add_ref();
810 }
811
812 __weak_count(const __weak_count& __r) noexcept
813 : _M_pi(__r._M_pi)
814 {
815 if (_M_pi != nullptr)
816 _M_pi->_M_weak_add_ref();
817 }
818
819 __weak_count(__weak_count&& __r) noexcept
820 : _M_pi(__r._M_pi)
821 { __r._M_pi = nullptr; }
822
823 ~__weak_count() noexcept
824 {
825 if (_M_pi != nullptr)
826 _M_pi->_M_weak_release();
827 }
828
829 __weak_count&
830 operator=(const __shared_count<_Lp>& __r) noexcept
831 {
832 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
833 if (__tmp != nullptr)
834 __tmp->_M_weak_add_ref();
835 if (_M_pi != nullptr)
836 _M_pi->_M_weak_release();
837 _M_pi = __tmp;
838 return *this;
839 }
840
841 __weak_count&
842 operator=(const __weak_count& __r) noexcept
843 {
844 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
845 if (__tmp != nullptr)
846 __tmp->_M_weak_add_ref();
847 if (_M_pi != nullptr)
848 _M_pi->_M_weak_release();
849 _M_pi = __tmp;
850 return *this;
851 }
852
853 __weak_count&
854 operator=(__weak_count&& __r) noexcept
855 {
856 if (_M_pi != nullptr)
857 _M_pi->_M_weak_release();
858 _M_pi = __r._M_pi;
859 __r._M_pi = nullptr;
860 return *this;
861 }
862
863 void
864 _M_swap(__weak_count& __r) noexcept
865 {
866 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
867 __r._M_pi = _M_pi;
868 _M_pi = __tmp;
869 }
870
871 long
872 _M_get_use_count() const noexcept
873 { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }
874
875 bool
876 _M_less(const __weak_count& __rhs) const noexcept
877 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
878
879 bool
880 _M_less(const __shared_count<_Lp>& __rhs) const noexcept
881 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
882
883 // Friend function injected into enclosing namespace and found by ADL
884 friend inline bool
885 operator==(const __weak_count& __a, const __weak_count& __b) noexcept
886 { return __a._M_pi == __b._M_pi; }
887
888 private:
889 friend class __shared_count<_Lp>;
890
891 _Sp_counted_base<_Lp>* _M_pi;
892 };
893
894 // Now that __weak_count is defined we can define this constructor:
895 template<_Lock_policy _Lp>
896 inline
897 __shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r)
898 : _M_pi(__r._M_pi)
899 {
900 if (_M_pi != nullptr)
901 _M_pi->_M_add_ref_lock();
902 else
903 __throw_bad_weak_ptr();
904 }
905
906 // Now that __weak_count is defined we can define this constructor:
907 template<_Lock_policy _Lp>
908 inline
909 __shared_count<_Lp>::
910 __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t)
911 : _M_pi(__r._M_pi)
912 {
913 if (_M_pi != nullptr)
914 if (!_M_pi->_M_add_ref_lock_nothrow())
915 _M_pi = nullptr;
916 }
917
918#define __cpp_lib_shared_ptr_arrays201611L 201611L
919
920 // Helper traits for shared_ptr of array:
921
922 // A pointer type Y* is said to be compatible with a pointer type T* when
923 // either Y* is convertible to T* or Y is U[N] and T is U cv [].
924 template<typename _Yp_ptr, typename _Tp_ptr>
925 struct __sp_compatible_with
926 : false_type
927 { };
928
929 template<typename _Yp, typename _Tp>
930 struct __sp_compatible_with<_Yp*, _Tp*>
931 : is_convertible<_Yp*, _Tp*>::type
932 { };
933
934 template<typename _Up, size_t _Nm>
935 struct __sp_compatible_with<_Up(*)[_Nm], _Up(*)[]>
936 : true_type
937 { };
938
939 template<typename _Up, size_t _Nm>
940 struct __sp_compatible_with<_Up(*)[_Nm], const _Up(*)[]>
941 : true_type
942 { };
943
944 template<typename _Up, size_t _Nm>
945 struct __sp_compatible_with<_Up(*)[_Nm], volatile _Up(*)[]>
946 : true_type
947 { };
948
949 template<typename _Up, size_t _Nm>
950 struct __sp_compatible_with<_Up(*)[_Nm], const volatile _Up(*)[]>
951 : true_type
952 { };
953
954 // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N].
955 template<typename _Up, size_t _Nm, typename _Yp, typename = void>
956 struct __sp_is_constructible_arrN
957 : false_type
958 { };
959
960 template<typename _Up, size_t _Nm, typename _Yp>
961 struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>>
962 : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type
963 { };
964
965 // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[].
966 template<typename _Up, typename _Yp, typename = void>
967 struct __sp_is_constructible_arr
968 : false_type
969 { };
970
971 template<typename _Up, typename _Yp>
972 struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>>
973 : is_convertible<_Yp(*)[], _Up(*)[]>::type
974 { };
975
976 // Trait to check if shared_ptr<T> can be constructed from Y*.
977 template<typename _Tp, typename _Yp>
978 struct __sp_is_constructible;
979
980 // When T is U[N], Y(*)[N] shall be convertible to T*;
981 template<typename _Up, size_t _Nm, typename _Yp>
982 struct __sp_is_constructible<_Up[_Nm], _Yp>
983 : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type
984 { };
985
986 // when T is U[], Y(*)[] shall be convertible to T*;
987 template<typename _Up, typename _Yp>
988 struct __sp_is_constructible<_Up[], _Yp>
989 : __sp_is_constructible_arr<_Up, _Yp>::type
990 { };
991
992 // otherwise, Y* shall be convertible to T*.
993 template<typename _Tp, typename _Yp>
994 struct __sp_is_constructible
995 : is_convertible<_Yp*, _Tp*>::type
996 { };
997
998
999 // Define operator* and operator-> for shared_ptr<T>.
1000 template<typename _Tp, _Lock_policy _Lp,
1001 bool = is_array<_Tp>::value, bool = is_void<_Tp>::value>
1002 class __shared_ptr_access
1003 {
1004 public:
1005 using element_type = _Tp;
1006
1007 element_type&
1008 operator*() const noexcept
1009 {
1010 __glibcxx_assert(_M_get() != nullptr);
1011 return *_M_get();
1012 }
1013
1014 element_type*
1015 operator->() const noexcept
1016 {
1017 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
1018 return _M_get();
1019 }
1020
1021 private:
1022 element_type*
1023 _M_get() const noexcept
1024 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
1025 };
1026
1027 // Define operator-> for shared_ptr<cv void>.
1028 template<typename _Tp, _Lock_policy _Lp>
1029 class __shared_ptr_access<_Tp, _Lp, false, true>
1030 {
1031 public:
1032 using element_type = _Tp;
1033
1034 element_type*
1035 operator->() const noexcept
1036 {
1037 auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get();
1038 _GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr);
1039 return __ptr;
1040 }
1041 };
1042
1043 // Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>.
1044 template<typename _Tp, _Lock_policy _Lp>
1045 class __shared_ptr_access<_Tp, _Lp, true, false>
1046 {
1047 public:
1048 using element_type = typename remove_extent<_Tp>::type;
1049
1050#if __cplusplus201703L <= 201402L
1051 [[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]]
1052 element_type&
1053 operator*() const noexcept
1054 {
1055 __glibcxx_assert(_M_get() != nullptr);
1056 return *_M_get();
1057 }
1058
1059 [[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]]
1060 element_type*
1061 operator->() const noexcept
1062 {
1063 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
1064 return _M_get();
1065 }
1066#endif
1067
1068 element_type&
1069 operator[](ptrdiff_t __i) const
1070 {
1071 __glibcxx_assert(_M_get() != nullptr);
1072 __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);
1073 return _M_get()[__i];
1074 }
1075
1076 private:
1077 element_type*
1078 _M_get() const noexcept
1079 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
1080 };
1081
1082 template<typename _Tp, _Lock_policy _Lp>
1083 class __shared_ptr
1084 : public __shared_ptr_access<_Tp, _Lp>
1085 {
1086 public:
1087 using element_type = typename remove_extent<_Tp>::type;
1088
1089 private:
1090 // Constraint for taking ownership of a pointer of type _Yp*:
1091 template<typename _Yp>
1092 using _SafeConv
1093 = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;
1094
1095 // Constraint for construction from shared_ptr and weak_ptr:
1096 template<typename _Yp, typename _Res = void>
1097 using _Compatible = typename
1098 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1099
1100 // Constraint for assignment from shared_ptr and weak_ptr:
1101 template<typename _Yp>
1102 using _Assignable = _Compatible<_Yp, __shared_ptr&>;
1103
1104 // Constraint for construction from unique_ptr:
1105 template<typename _Yp, typename _Del, typename _Res = void,
1106 typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer>
1107 using _UniqCompatible = typename enable_if<__and_<
1108 __sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*>
1109 >::value, _Res>::type;
1110
1111 // Constraint for assignment from unique_ptr:
1112 template<typename _Yp, typename _Del>
1113 using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;
1114
1115 public:
1116
1117#if __cplusplus201703L > 201402L
1118 using weak_type = __weak_ptr<_Tp, _Lp>;
1119#endif
1120
1121 constexpr __shared_ptr() noexcept
1122 : _M_ptr(0), _M_refcount()
1123 { }
1124
1125 template<typename _Yp, typename = _SafeConv<_Yp>>
1126 explicit
1127 __shared_ptr(_Yp* __p)
1128 : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type())
1129 {
1130 static_assert( !is_void<_Yp>::value, "incomplete type" );
1131 static_assert( sizeof(_Yp) > 0, "incomplete type" );
1132 _M_enable_shared_from_this_with(__p);
1133 }
1134
1135 template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>
1136 __shared_ptr(_Yp* __p, _Deleter __d)
1137 : _M_ptr(__p), _M_refcount(__p, std::move(__d))
1138 {
1139 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1140 "deleter expression d(p) is well-formed");
1141 _M_enable_shared_from_this_with(__p);
1142 }
1143
1144 template<typename _Yp, typename _Deleter, typename _Alloc,
1145 typename = _SafeConv<_Yp>>
1146 __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
1147 : _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a))
1148 {
1149 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1150 "deleter expression d(p) is well-formed");
1151 _M_enable_shared_from_this_with(__p);
1152 }
1153
1154 template<typename _Deleter>
1155 __shared_ptr(nullptr_t __p, _Deleter __d)
1156 : _M_ptr(0), _M_refcount(__p, std::move(__d))
1157 { }
1158
1159 template<typename _Deleter, typename _Alloc>
1160 __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
1161 : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a))
1162 { }
1163
1164 // Aliasing constructor
1165 template<typename _Yp>
1166 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
1167 element_type* __p) noexcept
1168 : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
1169 { }
1170
1171 // Aliasing constructor
1172 template<typename _Yp>
1173 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r,
1174 element_type* __p) noexcept
1175 : _M_ptr(__p), _M_refcount()
1176 {
1177 _M_refcount._M_swap(__r._M_refcount);
1178 __r._M_ptr = 0;
1179 }
1180
1181 __shared_ptr(const __shared_ptr&) noexcept = default;
1182 __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
1183 ~__shared_ptr() = default;
1184
1185 template<typename _Yp, typename = _Compatible<_Yp>>
1186 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1187 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1188 { }
1189
1190 __shared_ptr(__shared_ptr&& __r) noexcept
1191 : _M_ptr(__r._M_ptr), _M_refcount()
1192 {
1193 _M_refcount._M_swap(__r._M_refcount);
1194 __r._M_ptr = 0;
1195 }
1196
1197 template<typename _Yp, typename = _Compatible<_Yp>>
1198 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1199 : _M_ptr(__r._M_ptr), _M_refcount()
1200 {
1201 _M_refcount._M_swap(__r._M_refcount);
1202 __r._M_ptr = 0;
1203 }
1204
1205 template<typename _Yp, typename = _Compatible<_Yp>>
1206 explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r)
1207 : _M_refcount(__r._M_refcount) // may throw
1208 {
1209 // It is now safe to copy __r._M_ptr, as
1210 // _M_refcount(__r._M_refcount) did not throw.
1211 _M_ptr = __r._M_ptr;
1212 }
1213
1214 // If an exception is thrown this constructor has no effect.
1215 template<typename _Yp, typename _Del,
1216 typename = _UniqCompatible<_Yp, _Del>>
1217 __shared_ptr(unique_ptr<_Yp, _Del>&& __r)
1218 : _M_ptr(__r.get()), _M_refcount()
1219 {
1220 auto __raw = __to_address(__r.get());
1221 _M_refcount = __shared_count<_Lp>(std::move(__r));
1222 _M_enable_shared_from_this_with(__raw);
1223 }
1224
1225#if __cplusplus201703L <= 201402L && _GLIBCXX_USE_DEPRECATED1
1226 protected:
1227 // If an exception is thrown this constructor has no effect.
1228 template<typename _Tp1, typename _Del,
1229 typename enable_if<__and_<
1230 __not_<is_array<_Tp>>, is_array<_Tp1>,
1231 is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*>
1232 >::value, bool>::type = true>
1233 __shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete)
1234 : _M_ptr(__r.get()), _M_refcount()
1235 {
1236 auto __raw = __to_address(__r.get());
1237 _M_refcount = __shared_count<_Lp>(std::move(__r));
1238 _M_enable_shared_from_this_with(__raw);
1239 }
1240 public:
1241#endif
1242
1243#if _GLIBCXX_USE_DEPRECATED1
1244#pragma GCC diagnostic push
1245#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1246 // Postcondition: use_count() == 1 and __r.get() == 0
1247 template<typename _Yp, typename = _Compatible<_Yp>>
1248 __shared_ptr(auto_ptr<_Yp>&& __r);
1249#pragma GCC diagnostic pop
1250#endif
1251
1252 constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
1253
1254 template<typename _Yp>
1255 _Assignable<_Yp>
1256 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1257 {
1258 _M_ptr = __r._M_ptr;
1259 _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
1260 return *this;
1261 }
1262
1263#if _GLIBCXX_USE_DEPRECATED1
1264#pragma GCC diagnostic push
1265#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1266 template<typename _Yp>
1267 _Assignable<_Yp>
1268 operator=(auto_ptr<_Yp>&& __r)
1269 {
1270 __shared_ptr(std::move(__r)).swap(*this);
1271 return *this;
1272 }
1273#pragma GCC diagnostic pop
1274#endif
1275
1276 __shared_ptr&
1277 operator=(__shared_ptr&& __r) noexcept
1278 {
1279 __shared_ptr(std::move(__r)).swap(*this);
1280 return *this;
1281 }
1282
1283 template<class _Yp>
1284 _Assignable<_Yp>
1285 operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1286 {
1287 __shared_ptr(std::move(__r)).swap(*this);
1288 return *this;
1289 }
1290
1291 template<typename _Yp, typename _Del>
1292 _UniqAssignable<_Yp, _Del>
1293 operator=(unique_ptr<_Yp, _Del>&& __r)
1294 {
1295 __shared_ptr(std::move(__r)).swap(*this);
1296 return *this;
1297 }
1298
1299 void
1300 reset() noexcept
1301 { __shared_ptr().swap(*this); }
1302
1303 template<typename _Yp>
1304 _SafeConv<_Yp>
1305 reset(_Yp* __p) // _Yp must be complete.
1306 {
1307 // Catch self-reset errors.
1308 __glibcxx_assert(__p == 0 || __p != _M_ptr);
1309 __shared_ptr(__p).swap(*this);
1310 }
1311
1312 template<typename _Yp, typename _Deleter>
1313 _SafeConv<_Yp>
1314 reset(_Yp* __p, _Deleter __d)
1315 { __shared_ptr(__p, std::move(__d)).swap(*this); }
1316
1317 template<typename _Yp, typename _Deleter, typename _Alloc>
1318 _SafeConv<_Yp>
1319 reset(_Yp* __p, _Deleter __d, _Alloc __a)
1320 { __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); }
1321
1322 /// Return the stored pointer.
1323 element_type*
1324 get() const noexcept
1325 { return _M_ptr; }
1326
1327 /// Return true if the stored pointer is not null.
1328 explicit operator bool() const // never throws
1329 { return _M_ptr == 0 ? false : true; }
1330
1331 /// Return true if use_count() == 1.
1332 bool
1333 unique() const noexcept
1334 { return _M_refcount._M_unique(); }
1335
1336 /// If *this owns a pointer, return the number of owners, otherwise zero.
1337 long
1338 use_count() const noexcept
1339 { return _M_refcount._M_get_use_count(); }
1340
1341 /// Exchange both the owned pointer and the stored pointer.
1342 void
1343 swap(__shared_ptr<_Tp, _Lp>& __other) noexcept
1344 {
1345 std::swap(_M_ptr, __other._M_ptr);
1346 _M_refcount._M_swap(__other._M_refcount);
1347 }
1348
1349 /** @brief Define an ordering based on ownership.
1350 *
1351 * This function defines a strict weak ordering between two shared_ptr
1352 * or weak_ptr objects, such that one object is less than the other
1353 * unless they share ownership of the same pointer, or are both empty.
1354 * @{
1355 */
1356 template<typename _Tp1>
1357 bool
1358 owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1359 { return _M_refcount._M_less(__rhs._M_refcount); }
1360
1361 template<typename _Tp1>
1362 bool
1363 owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1364 { return _M_refcount._M_less(__rhs._M_refcount); }
1365 // @}
1366
1367 protected:
1368 // This constructor is non-standard, it is used by allocate_shared.
1369 template<typename _Alloc, typename... _Args>
1370 __shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
1371 : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
9
Calling constructor for '__shared_count<__gnu_cxx::_S_atomic>'
26
Returning from constructor for '__shared_count<__gnu_cxx::_S_atomic>'
1372 { _M_enable_shared_from_this_with(_M_ptr); }
1373
1374 template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,
1375 typename... _Args>
1376 friend __shared_ptr<_Tp1, _Lp1>
1377 __allocate_shared(const _Alloc& __a, _Args&&... __args);
1378
1379 // This constructor is used by __weak_ptr::lock() and
1380 // shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).
1381 __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
1382 : _M_refcount(__r._M_refcount, std::nothrow)
1383 {
1384 _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;
1385 }
1386
1387 friend class __weak_ptr<_Tp, _Lp>;
1388
1389 private:
1390
1391 template<typename _Yp>
1392 using __esft_base_t = decltype(__enable_shared_from_this_base(
1393 std::declval<const __shared_count<_Lp>&>(),
1394 std::declval<_Yp*>()));
1395
1396 // Detect an accessible and unambiguous enable_shared_from_this base.
1397 template<typename _Yp, typename = void>
1398 struct __has_esft_base
1399 : false_type { };
1400
1401 template<typename _Yp>
1402 struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
1403 : __not_<is_array<_Tp>> { }; // No enable shared_from_this for arrays
1404
1405 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1406 typename enable_if<__has_esft_base<_Yp2>::value>::type
1407 _M_enable_shared_from_this_with(_Yp* __p) noexcept
1408 {
1409 if (auto __base = __enable_shared_from_this_base(_M_refcount, __p))
1410 __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount);
1411 }
1412
1413 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1414 typename enable_if<!__has_esft_base<_Yp2>::value>::type
1415 _M_enable_shared_from_this_with(_Yp*) noexcept
1416 { }
1417
1418 void*
1419 _M_get_deleter(const std::type_info& __ti) const noexcept
1420 { return _M_refcount._M_get_deleter(__ti); }
1421
1422 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1423 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1424
1425 template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
1426 friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
1427
1428 template<typename _Del, typename _Tp1>
1429 friend _Del* get_deleter(const shared_ptr<_Tp1>&) noexcept;
1430
1431 element_type* _M_ptr; // Contained pointer.
1432 __shared_count<_Lp> _M_refcount; // Reference counter.
1433 };
1434
1435
1436 // 20.7.2.2.7 shared_ptr comparisons
1437 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1438 inline bool
1439 operator==(const __shared_ptr<_Tp1, _Lp>& __a,
1440 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1441 { return __a.get() == __b.get(); }
1442
1443 template<typename _Tp, _Lock_policy _Lp>
1444 inline bool
1445 operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1446 { return !__a; }
1447
1448#ifdef __cpp_lib_three_way_comparison
1449 template<typename _Tp, typename _Up, _Lock_policy _Lp>
1450 inline strong_ordering
1451 operator<=>(const __shared_ptr<_Tp, _Lp>& __a,
1452 const __shared_ptr<_Up, _Lp>& __b) noexcept
1453 { return compare_three_way()(__a.get(), __b.get()); }
1454
1455 template<typename _Tp, _Lock_policy _Lp>
1456 inline strong_ordering
1457 operator<=>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1458 {
1459 using pointer = typename __shared_ptr<_Tp, _Lp>::element_type*;
1460 return compare_three_way()(__a.get(), static_cast<pointer>(nullptr));
1461 }
1462#else
1463 template<typename _Tp, _Lock_policy _Lp>
1464 inline bool
1465 operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1466 { return !__a; }
1467
1468 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1469 inline bool
1470 operator!=(const __shared_ptr<_Tp1, _Lp>& __a,
1471 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1472 { return __a.get() != __b.get(); }
1473
1474 template<typename _Tp, _Lock_policy _Lp>
1475 inline bool
1476 operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1477 { return (bool)__a; }
1478
1479 template<typename _Tp, _Lock_policy _Lp>
1480 inline bool
1481 operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1482 { return (bool)__a; }
1483
1484 template<typename _Tp, typename _Up, _Lock_policy _Lp>
1485 inline bool
1486 operator<(const __shared_ptr<_Tp, _Lp>& __a,
1487 const __shared_ptr<_Up, _Lp>& __b) noexcept
1488 {
1489 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1490 using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type;
1491 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
1492 return less<_Vp>()(__a.get(), __b.get());
1493 }
1494
1495 template<typename _Tp, _Lock_policy _Lp>
1496 inline bool
1497 operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1498 {
1499 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1500 return less<_Tp_elt*>()(__a.get(), nullptr);
1501 }
1502
1503 template<typename _Tp, _Lock_policy _Lp>
1504 inline bool
1505 operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1506 {
1507 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1508 return less<_Tp_elt*>()(nullptr, __a.get());
1509 }
1510
1511 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1512 inline bool
1513 operator<=(const __shared_ptr<_Tp1, _Lp>& __a,
1514 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1515 { return !(__b < __a); }
1516
1517 template<typename _Tp, _Lock_policy _Lp>
1518 inline bool
1519 operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1520 { return !(nullptr < __a); }
1521
1522 template<typename _Tp, _Lock_policy _Lp>
1523 inline bool
1524 operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1525 { return !(__a < nullptr); }
1526
1527 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1528 inline bool
1529 operator>(const __shared_ptr<_Tp1, _Lp>& __a,
1530 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1531 { return (__b < __a); }
1532
1533 template<typename _Tp, _Lock_policy _Lp>
1534 inline bool
1535 operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1536 { return nullptr < __a; }
1537
1538 template<typename _Tp, _Lock_policy _Lp>
1539 inline bool
1540 operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1541 { return __a < nullptr; }
1542
1543 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1544 inline bool
1545 operator>=(const __shared_ptr<_Tp1, _Lp>& __a,
1546 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1547 { return !(__a < __b); }
1548
1549 template<typename _Tp, _Lock_policy _Lp>
1550 inline bool
1551 operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1552 { return !(__a < nullptr); }
1553
1554 template<typename _Tp, _Lock_policy _Lp>
1555 inline bool
1556 operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1557 { return !(nullptr < __a); }
1558#endif // three-way comparison
1559
1560 // 20.7.2.2.8 shared_ptr specialized algorithms.
1561 template<typename _Tp, _Lock_policy _Lp>
1562 inline void
1563 swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept
1564 { __a.swap(__b); }
1565
1566 // 20.7.2.2.9 shared_ptr casts
1567
1568 // The seemingly equivalent code:
1569 // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
1570 // will eventually result in undefined behaviour, attempting to
1571 // delete the same object twice.
1572 /// static_pointer_cast
1573 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1574 inline __shared_ptr<_Tp, _Lp>
1575 static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1576 {
1577 using _Sp = __shared_ptr<_Tp, _Lp>;
1578 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
1579 }
1580
1581 // The seemingly equivalent code:
1582 // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
1583 // will eventually result in undefined behaviour, attempting to
1584 // delete the same object twice.
1585 /// const_pointer_cast
1586 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1587 inline __shared_ptr<_Tp, _Lp>
1588 const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1589 {
1590 using _Sp = __shared_ptr<_Tp, _Lp>;
1591 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
1592 }
1593
1594 // The seemingly equivalent code:
1595 // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
1596 // will eventually result in undefined behaviour, attempting to
1597 // delete the same object twice.
1598 /// dynamic_pointer_cast
1599 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1600 inline __shared_ptr<_Tp, _Lp>
1601 dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1602 {
1603 using _Sp = __shared_ptr<_Tp, _Lp>;
1604 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
1605 return _Sp(__r, __p);
1606 return _Sp();
1607 }
1608
1609#if __cplusplus201703L > 201402L
1610 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1611 inline __shared_ptr<_Tp, _Lp>
1612 reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1613 {
1614 using _Sp = __shared_ptr<_Tp, _Lp>;
1615 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
1616 }
1617#endif
1618
1619 template<typename _Tp, _Lock_policy _Lp>
1620 class __weak_ptr
1621 {
1622 template<typename _Yp, typename _Res = void>
1623 using _Compatible = typename
1624 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1625
1626 // Constraint for assignment from shared_ptr and weak_ptr:
1627 template<typename _Yp>
1628 using _Assignable = _Compatible<_Yp, __weak_ptr&>;
1629
1630 public:
1631 using element_type = typename remove_extent<_Tp>::type;
1632
1633 constexpr __weak_ptr() noexcept
1634 : _M_ptr(nullptr), _M_refcount()
1635 { }
1636
1637 __weak_ptr(const __weak_ptr&) noexcept = default;
1638
1639 ~__weak_ptr() = default;
1640
1641 // The "obvious" converting constructor implementation:
1642 //
1643 // template<typename _Tp1>
1644 // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
1645 // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
1646 // { }
1647 //
1648 // has a serious problem.
1649 //
1650 // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
1651 // conversion may require access to *__r._M_ptr (virtual inheritance).
1652 //
1653 // It is not possible to avoid spurious access violations since
1654 // in multithreaded programs __r._M_ptr may be invalidated at any point.
1655 template<typename _Yp, typename = _Compatible<_Yp>>
1656 __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1657 : _M_refcount(__r._M_refcount)
1658 { _M_ptr = __r.lock().get(); }
1659
1660 template<typename _Yp, typename = _Compatible<_Yp>>
1661 __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1662 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1663 { }
1664
1665 __weak_ptr(__weak_ptr&& __r) noexcept
1666 : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
1667 { __r._M_ptr = nullptr; }
1668
1669 template<typename _Yp, typename = _Compatible<_Yp>>
1670 __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1671 : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
1672 { __r._M_ptr = nullptr; }
1673
1674 __weak_ptr&
1675 operator=(const __weak_ptr& __r) noexcept = default;
1676
1677 template<typename _Yp>
1678 _Assignable<_Yp>
1679 operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1680 {
1681 _M_ptr = __r.lock().get();
1682 _M_refcount = __r._M_refcount;
1683 return *this;
1684 }
1685
1686 template<typename _Yp>
1687 _Assignable<_Yp>
1688 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1689 {
1690 _M_ptr = __r._M_ptr;
1691 _M_refcount = __r._M_refcount;
1692 return *this;
1693 }
1694
1695 __weak_ptr&
1696 operator=(__weak_ptr&& __r) noexcept
1697 {
1698 _M_ptr = __r._M_ptr;
1699 _M_refcount = std::move(__r._M_refcount);
1700 __r._M_ptr = nullptr;
1701 return *this;
1702 }
1703
1704 template<typename _Yp>
1705 _Assignable<_Yp>
1706 operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1707 {
1708 _M_ptr = __r.lock().get();
1709 _M_refcount = std::move(__r._M_refcount);
1710 __r._M_ptr = nullptr;
1711 return *this;
1712 }
1713
1714 __shared_ptr<_Tp, _Lp>
1715 lock() const noexcept
1716 { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
1717
1718 long
1719 use_count() const noexcept
1720 { return _M_refcount._M_get_use_count(); }
1721
1722 bool
1723 expired() const noexcept
1724 { return _M_refcount._M_get_use_count() == 0; }
1725
1726 template<typename _Tp1>
1727 bool
1728 owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const noexcept
1729 { return _M_refcount._M_less(__rhs._M_refcount); }
1730
1731 template<typename _Tp1>
1732 bool
1733 owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept
1734 { return _M_refcount._M_less(__rhs._M_refcount); }
1735
1736 void
1737 reset() noexcept
1738 { __weak_ptr().swap(*this); }
1739
1740 void
1741 swap(__weak_ptr& __s) noexcept
1742 {
1743 std::swap(_M_ptr, __s._M_ptr);
1744 _M_refcount._M_swap(__s._M_refcount);
1745 }
1746
1747 private:
1748 // Used by __enable_shared_from_this.
1749 void
1750 _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept
1751 {
1752 if (use_count() == 0)
1753 {
1754 _M_ptr = __ptr;
1755 _M_refcount = __refcount;
1756 }
1757 }
1758
1759 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1760 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1761 friend class __enable_shared_from_this<_Tp, _Lp>;
1762 friend class enable_shared_from_this<_Tp>;
1763
1764 element_type* _M_ptr; // Contained pointer.
1765 __weak_count<_Lp> _M_refcount; // Reference counter.
1766 };
1767
1768 // 20.7.2.3.6 weak_ptr specialized algorithms.
1769 template<typename _Tp, _Lock_policy _Lp>
1770 inline void
1771 swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept
1772 { __a.swap(__b); }
1773
1774 template<typename _Tp, typename _Tp1>
1775 struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool>
1776 {
1777 bool
1778 operator()(const _Tp& __lhs, const _Tp& __rhs) const noexcept
1779 { return __lhs.owner_before(__rhs); }
1780
1781 bool
1782 operator()(const _Tp& __lhs, const _Tp1& __rhs) const noexcept
1783 { return __lhs.owner_before(__rhs); }
1784
1785 bool
1786 operator()(const _Tp1& __lhs, const _Tp& __rhs) const noexcept
1787 { return __lhs.owner_before(__rhs); }
1788 };
1789
1790 template<>
1791 struct _Sp_owner_less<void, void>
1792 {
1793 template<typename _Tp, typename _Up>
1794 auto
1795 operator()(const _Tp& __lhs, const _Up& __rhs) const noexcept
1796 -> decltype(__lhs.owner_before(__rhs))
1797 { return __lhs.owner_before(__rhs); }
1798
1799 using is_transparent = void;
1800 };
1801
1802 template<typename _Tp, _Lock_policy _Lp>
1803 struct owner_less<__shared_ptr<_Tp, _Lp>>
1804 : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>>
1805 { };
1806
1807 template<typename _Tp, _Lock_policy _Lp>
1808 struct owner_less<__weak_ptr<_Tp, _Lp>>
1809 : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>>
1810 { };
1811
1812
1813 template<typename _Tp, _Lock_policy _Lp>
1814 class __enable_shared_from_this
1815 {
1816 protected:
1817 constexpr __enable_shared_from_this() noexcept { }
1818
1819 __enable_shared_from_this(const __enable_shared_from_this&) noexcept { }
1820
1821 __enable_shared_from_this&
1822 operator=(const __enable_shared_from_this&) noexcept
1823 { return *this; }
1824
1825 ~__enable_shared_from_this() { }
1826
1827 public:
1828 __shared_ptr<_Tp, _Lp>
1829 shared_from_this()
1830 { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); }
1831
1832 __shared_ptr<const _Tp, _Lp>
1833 shared_from_this() const
1834 { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); }
1835
1836#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
1837 __weak_ptr<_Tp, _Lp>
1838 weak_from_this() noexcept
1839 { return this->_M_weak_this; }
1840
1841 __weak_ptr<const _Tp, _Lp>
1842 weak_from_this() const noexcept
1843 { return this->_M_weak_this; }
1844#endif
1845
1846 private:
1847 template<typename _Tp1>
1848 void
1849 _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept
1850 { _M_weak_this._M_assign(__p, __n); }
1851
1852 friend const __enable_shared_from_this*
1853 __enable_shared_from_this_base(const __shared_count<_Lp>&,
1854 const __enable_shared_from_this* __p)
1855 { return __p; }
1856
1857 template<typename, _Lock_policy>
1858 friend class __shared_ptr;
1859
1860 mutable __weak_ptr<_Tp, _Lp> _M_weak_this;
1861 };
1862
1863 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1864 typename _Alloc, typename... _Args>
1865 inline __shared_ptr<_Tp, _Lp>
1866 __allocate_shared(const _Alloc& __a, _Args&&... __args)
1867 {
1868 return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a},
1869 std::forward<_Args>(__args)...);
1870 }
1871
1872 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1873 typename... _Args>
1874 inline __shared_ptr<_Tp, _Lp>
1875 __make_shared(_Args&&... __args)
1876 {
1877 typedef typename std::remove_const<_Tp>::type _Tp_nc;
1878 return std::__allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(),
1879 std::forward<_Args>(__args)...);
1880 }
1881
1882 /// std::hash specialization for __shared_ptr.
1883 template<typename _Tp, _Lock_policy _Lp>
1884 struct hash<__shared_ptr<_Tp, _Lp>>
1885 : public __hash_base<size_t, __shared_ptr<_Tp, _Lp>>
1886 {
1887 size_t
1888 operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept
1889 {
1890 return hash<typename __shared_ptr<_Tp, _Lp>::element_type*>()(
1891 __s.get());
1892 }
1893 };
1894
1895_GLIBCXX_END_NAMESPACE_VERSION
1896} // namespace
1897
1898#endif // _SHARED_PTR_BASE_H

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/alloc_traits.h

1// Allocator traits -*- C++ -*-
2
3// Copyright (C) 2011-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/alloc_traits.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
28 */
29
30#ifndef _ALLOC_TRAITS_H1
31#define _ALLOC_TRAITS_H1 1
32
33#include <bits/stl_construct.h>
34#include <bits/memoryfwd.h>
35#if __cplusplus201703L >= 201103L
36# include <bits/allocator.h>
37# include <bits/ptr_traits.h>
38# include <ext/numeric_traits.h>
39#endif
40
41namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
42{
43_GLIBCXX_BEGIN_NAMESPACE_VERSION
44
45#if __cplusplus201703L >= 201103L
46#define __cpp_lib_allocator_traits_is_always_equal201411 201411
47
48 struct __allocator_traits_base
49 {
50 template<typename _Tp, typename _Up, typename = void>
51 struct __rebind : __replace_first_arg<_Tp, _Up> { };
52
53 template<typename _Tp, typename _Up>
54 struct __rebind<_Tp, _Up,
55 __void_t<typename _Tp::template rebind<_Up>::other>>
56 { using type = typename _Tp::template rebind<_Up>::other; };
57
58 protected:
59 template<typename _Tp>
60 using __pointer = typename _Tp::pointer;
61 template<typename _Tp>
62 using __c_pointer = typename _Tp::const_pointer;
63 template<typename _Tp>
64 using __v_pointer = typename _Tp::void_pointer;
65 template<typename _Tp>
66 using __cv_pointer = typename _Tp::const_void_pointer;
67 template<typename _Tp>
68 using __pocca = typename _Tp::propagate_on_container_copy_assignment;
69 template<typename _Tp>
70 using __pocma = typename _Tp::propagate_on_container_move_assignment;
71 template<typename _Tp>
72 using __pocs = typename _Tp::propagate_on_container_swap;
73 template<typename _Tp>
74 using __equal = typename _Tp::is_always_equal;
75 };
76
77 template<typename _Alloc, typename _Up>
78 using __alloc_rebind
79 = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
80
81 /**
82 * @brief Uniform interface to all allocator types.
83 * @ingroup allocators
84 */
85 template<typename _Alloc>
86 struct allocator_traits : __allocator_traits_base
87 {
88 /// The allocator type
89 typedef _Alloc allocator_type;
90 /// The allocated type
91 typedef typename _Alloc::value_type value_type;
92
93 /**
94 * @brief The allocator's pointer type.
95 *
96 * @c Alloc::pointer if that type exists, otherwise @c value_type*
97 */
98 using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
99
100 private:
101 // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
102 template<template<typename> class _Func, typename _Tp, typename = void>
103 struct _Ptr
104 {
105 using type = typename pointer_traits<pointer>::template rebind<_Tp>;
106 };
107
108 template<template<typename> class _Func, typename _Tp>
109 struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
110 {
111 using type = _Func<_Alloc>;
112 };
113
114 // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
115 template<typename _A2, typename _PtrT, typename = void>
116 struct _Diff
117 { using type = typename pointer_traits<_PtrT>::difference_type; };
118
119 template<typename _A2, typename _PtrT>
120 struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
121 { using type = typename _A2::difference_type; };
122
123 // Select _A2::size_type or make_unsigned<_DiffT>::type
124 template<typename _A2, typename _DiffT, typename = void>
125 struct _Size : make_unsigned<_DiffT> { };
126
127 template<typename _A2, typename _DiffT>
128 struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
129 { using type = typename _A2::size_type; };
130
131 public:
132 /**
133 * @brief The allocator's const pointer type.
134 *
135 * @c Alloc::const_pointer if that type exists, otherwise
136 * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
137 */
138 using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
139
140 /**
141 * @brief The allocator's void pointer type.
142 *
143 * @c Alloc::void_pointer if that type exists, otherwise
144 * <tt> pointer_traits<pointer>::rebind<void> </tt>
145 */
146 using void_pointer = typename _Ptr<__v_pointer, void>::type;
147
148 /**
149 * @brief The allocator's const void pointer type.
150 *
151 * @c Alloc::const_void_pointer if that type exists, otherwise
152 * <tt> pointer_traits<pointer>::rebind<const void> </tt>
153 */
154 using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
155
156 /**
157 * @brief The allocator's difference type
158 *
159 * @c Alloc::difference_type if that type exists, otherwise
160 * <tt> pointer_traits<pointer>::difference_type </tt>
161 */
162 using difference_type = typename _Diff<_Alloc, pointer>::type;
163
164 /**
165 * @brief The allocator's size type
166 *
167 * @c Alloc::size_type if that type exists, otherwise
168 * <tt> make_unsigned<difference_type>::type </tt>
169 */
170 using size_type = typename _Size<_Alloc, difference_type>::type;
171
172 /**
173 * @brief How the allocator is propagated on copy assignment
174 *
175 * @c Alloc::propagate_on_container_copy_assignment if that type exists,
176 * otherwise @c false_type
177 */
178 using propagate_on_container_copy_assignment
179 = __detected_or_t<false_type, __pocca, _Alloc>;
180
181 /**
182 * @brief How the allocator is propagated on move assignment
183 *
184 * @c Alloc::propagate_on_container_move_assignment if that type exists,
185 * otherwise @c false_type
186 */
187 using propagate_on_container_move_assignment
188 = __detected_or_t<false_type, __pocma, _Alloc>;
189
190 /**
191 * @brief How the allocator is propagated on swap
192 *
193 * @c Alloc::propagate_on_container_swap if that type exists,
194 * otherwise @c false_type
195 */
196 using propagate_on_container_swap
197 = __detected_or_t<false_type, __pocs, _Alloc>;
198
199 /**
200 * @brief Whether all instances of the allocator type compare equal.
201 *
202 * @c Alloc::is_always_equal if that type exists,
203 * otherwise @c is_empty<Alloc>::type
204 */
205 using is_always_equal
206 = __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
207
208 template<typename _Tp>
209 using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
210 template<typename _Tp>
211 using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
212
213 private:
214 template<typename _Alloc2>
215 static constexpr auto
216 _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
217 -> decltype(__a.allocate(__n, __hint))
218 { return __a.allocate(__n, __hint); }
219
220 template<typename _Alloc2>
221 static constexpr pointer
222 _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
223 { return __a.allocate(__n); }
224
225 template<typename _Tp, typename... _Args>
226 struct __construct_helper
227 {
228 template<typename _Alloc2,
229 typename = decltype(std::declval<_Alloc2*>()->construct(
230 std::declval<_Tp*>(), std::declval<_Args>()...))>
231 static true_type __test(int);
232
233 template<typename>
234 static false_type __test(...);
235
236 using type = decltype(__test<_Alloc>(0));
237 };
238
239 template<typename _Tp, typename... _Args>
240 using __has_construct
241 = typename __construct_helper<_Tp, _Args...>::type;
242
243 template<typename _Tp, typename... _Args>
244 static _GLIBCXX14_CONSTEXPRconstexpr _Require<__has_construct<_Tp, _Args...>>
245 _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
246 noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
247 { __a.construct(__p, std::forward<_Args>(__args)...); }
248
249 template<typename _Tp, typename... _Args>
250 static _GLIBCXX14_CONSTEXPRconstexpr
251 _Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
252 is_constructible<_Tp, _Args...>>>
253 _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
254 noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value)
255 {
256#if __cplusplus201703L <= 201703L
257 ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
258#else
259 std::construct_at(__p, std::forward<_Args>(__args)...);
260#endif
261 }
262
263 template<typename _Alloc2, typename _Tp>
264 static _GLIBCXX14_CONSTEXPRconstexpr auto
265 _S_destroy(_Alloc2& __a, _Tp* __p, int)
266 noexcept(noexcept(__a.destroy(__p)))
267 -> decltype(__a.destroy(__p))
268 { __a.destroy(__p); }
269
270 template<typename _Alloc2, typename _Tp>
271 static _GLIBCXX14_CONSTEXPRconstexpr void
272 _S_destroy(_Alloc2&, _Tp* __p, ...)
273 noexcept(std::is_nothrow_destructible<_Tp>::value)
274 { std::_Destroy(__p); }
275
276 template<typename _Alloc2>
277 static constexpr auto
278 _S_max_size(_Alloc2& __a, int)
279 -> decltype(__a.max_size())
280 { return __a.max_size(); }
281
282 template<typename _Alloc2>
283 static constexpr size_type
284 _S_max_size(_Alloc2&, ...)
285 {
286 // _GLIBCXX_RESOLVE_LIB_DEFECTS
287 // 2466. allocator_traits::max_size() default behavior is incorrect
288 return __gnu_cxx::__numeric_traits<size_type>::__max
289 / sizeof(value_type);
290 }
291
292 template<typename _Alloc2>
293 static constexpr auto
294 _S_select(_Alloc2& __a, int)
295 -> decltype(__a.select_on_container_copy_construction())
296 { return __a.select_on_container_copy_construction(); }
297
298 template<typename _Alloc2>
299 static constexpr _Alloc2
300 _S_select(_Alloc2& __a, ...)
301 { return __a; }
302
303 public:
304
305 /**
306 * @brief Allocate memory.
307 * @param __a An allocator.
308 * @param __n The number of objects to allocate space for.
309 *
310 * Calls @c a.allocate(n)
311 */
312 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
313 allocate(_Alloc& __a, size_type __n)
314 { return __a.allocate(__n); }
315
316 /**
317 * @brief Allocate memory.
318 * @param __a An allocator.
319 * @param __n The number of objects to allocate space for.
320 * @param __hint Aid to locality.
321 * @return Memory of suitable size and alignment for @a n objects
322 * of type @c value_type
323 *
324 * Returns <tt> a.allocate(n, hint) </tt> if that expression is
325 * well-formed, otherwise returns @c a.allocate(n)
326 */
327 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
328 allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
329 { return _S_allocate(__a, __n, __hint, 0); }
330
331 /**
332 * @brief Deallocate memory.
333 * @param __a An allocator.
334 * @param __p Pointer to the memory to deallocate.
335 * @param __n The number of objects space was allocated for.
336 *
337 * Calls <tt> a.deallocate(p, n) </tt>
338 */
339 static _GLIBCXX20_CONSTEXPR void
340 deallocate(_Alloc& __a, pointer __p, size_type __n)
341 { __a.deallocate(__p, __n); }
342
343 /**
344 * @brief Construct an object of type @a _Tp
345 * @param __a An allocator.
346 * @param __p Pointer to memory of suitable size and alignment for Tp
347 * @param __args Constructor arguments.
348 *
349 * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
350 * if that expression is well-formed, otherwise uses placement-new
351 * to construct an object of type @a _Tp at location @a __p from the
352 * arguments @a __args...
353 */
354 template<typename _Tp, typename... _Args>
355 static _GLIBCXX20_CONSTEXPR auto
356 construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
357 noexcept(noexcept(_S_construct(__a, __p,
358 std::forward<_Args>(__args)...)))
359 -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
360 { _S_construct(__a, __p, std::forward<_Args>(__args)...); }
361
362 /**
363 * @brief Destroy an object of type @a _Tp
364 * @param __a An allocator.
365 * @param __p Pointer to the object to destroy
366 *
367 * Calls @c __a.destroy(__p) if that expression is well-formed,
368 * otherwise calls @c __p->~_Tp()
369 */
370 template<typename _Tp>
371 static _GLIBCXX20_CONSTEXPR void
372 destroy(_Alloc& __a, _Tp* __p)
373 noexcept(noexcept(_S_destroy(__a, __p, 0)))
374 { _S_destroy(__a, __p, 0); }
375
376 /**
377 * @brief The maximum supported allocation size
378 * @param __a An allocator.
379 * @return @c __a.max_size() or @c numeric_limits<size_type>::max()
380 *
381 * Returns @c __a.max_size() if that expression is well-formed,
382 * otherwise returns @c numeric_limits<size_type>::max()
383 */
384 static _GLIBCXX20_CONSTEXPR size_type
385 max_size(const _Alloc& __a) noexcept
386 { return _S_max_size(__a, 0); }
387
388 /**
389 * @brief Obtain an allocator to use when copying a container.
390 * @param __rhs An allocator.
391 * @return @c __rhs.select_on_container_copy_construction() or @a __rhs
392 *
393 * Returns @c __rhs.select_on_container_copy_construction() if that
394 * expression is well-formed, otherwise returns @a __rhs
395 */
396 static _GLIBCXX20_CONSTEXPR _Alloc
397 select_on_container_copy_construction(const _Alloc& __rhs)
398 { return _S_select(__rhs, 0); }
399 };
400
401#if __cplusplus201703L > 201703L
402# define __cpp_lib_constexpr_dynamic_alloc 201907L
403#endif
404
405 /// Partial specialization for std::allocator.
406 template<typename _Tp>
407 struct allocator_traits<allocator<_Tp>>
408 {
409 /// The allocator type
410 using allocator_type = allocator<_Tp>;
411
412 /// The allocated type
413 using value_type = _Tp;
414
415 /// The allocator's pointer type.
416 using pointer = _Tp*;
417
418 /// The allocator's const pointer type.
419 using const_pointer = const _Tp*;
420
421 /// The allocator's void pointer type.
422 using void_pointer = void*;
423
424 /// The allocator's const void pointer type.
425 using const_void_pointer = const void*;
426
427 /// The allocator's difference type
428 using difference_type = std::ptrdiff_t;
429
430 /// The allocator's size type
431 using size_type = std::size_t;
432
433 /// How the allocator is propagated on copy assignment
434 using propagate_on_container_copy_assignment = false_type;
435
436 /// How the allocator is propagated on move assignment
437 using propagate_on_container_move_assignment = true_type;
438
439 /// How the allocator is propagated on swap
440 using propagate_on_container_swap = false_type;
441
442 /// Whether all instances of the allocator type compare equal.
443 using is_always_equal = true_type;
444
445 template<typename _Up>
446 using rebind_alloc = allocator<_Up>;
447
448 template<typename _Up>
449 using rebind_traits = allocator_traits<allocator<_Up>>;
450
451 /**
452 * @brief Allocate memory.
453 * @param __a An allocator.
454 * @param __n The number of objects to allocate space for.
455 *
456 * Calls @c a.allocate(n)
457 */
458 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
459 allocate(allocator_type& __a, size_type __n)
460 { return __a.allocate(__n); }
461
462 /**
463 * @brief Allocate memory.
464 * @param __a An allocator.
465 * @param __n The number of objects to allocate space for.
466 * @param __hint Aid to locality.
467 * @return Memory of suitable size and alignment for @a n objects
468 * of type @c value_type
469 *
470 * Returns <tt> a.allocate(n, hint) </tt>
471 */
472 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
473 allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
474 {
475#if __cplusplus201703L <= 201703L
476 return __a.allocate(__n, __hint);
477#else
478 return __a.allocate(__n);
479#endif
480 }
481
482 /**
483 * @brief Deallocate memory.
484 * @param __a An allocator.
485 * @param __p Pointer to the memory to deallocate.
486 * @param __n The number of objects space was allocated for.
487 *
488 * Calls <tt> a.deallocate(p, n) </tt>
489 */
490 static _GLIBCXX20_CONSTEXPR void
491 deallocate(allocator_type& __a, pointer __p, size_type __n)
492 { __a.deallocate(__p, __n); }
493
494 /**
495 * @brief Construct an object of type `_Up`
496 * @param __a An allocator.
497 * @param __p Pointer to memory of suitable size and alignment for
498 * an object of type `_Up`.
499 * @param __args Constructor arguments.
500 *
501 * Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
502 * in C++11, C++14 and C++17. Changed in C++20 to call
503 * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
504 */
505 template<typename _Up, typename... _Args>
506 static _GLIBCXX20_CONSTEXPR void
507 construct(allocator_type& __a __attribute__((__unused__)), _Up* __p,
508 _Args&&... __args)
509 noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
510 {
511#if __cplusplus201703L <= 201703L
512 __a.construct(__p, std::forward<_Args>(__args)...);
12
Calling 'new_allocator::construct'
23
Returning; memory was released via 2nd parameter
513#else
514 std::construct_at(__p, std::forward<_Args>(__args)...);
515#endif
516 }
517
518 /**
519 * @brief Destroy an object of type @a _Up
520 * @param __a An allocator.
521 * @param __p Pointer to the object to destroy
522 *
523 * Calls @c __a.destroy(__p).
524 */
525 template<typename _Up>
526 static _GLIBCXX20_CONSTEXPR void
527 destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p)
528 noexcept(is_nothrow_destructible<_Up>::value)
529 {
530#if __cplusplus201703L <= 201703L
531 __a.destroy(__p);
532#else
533 std::destroy_at(__p);
534#endif
535 }
536
537 /**
538 * @brief The maximum supported allocation size
539 * @param __a An allocator.
540 * @return @c __a.max_size()
541 */
542 static _GLIBCXX20_CONSTEXPR size_type
543 max_size(const allocator_type& __a __attribute__((__unused__))) noexcept
544 {
545#if __cplusplus201703L <= 201703L
546 return __a.max_size();
547#else
548 return size_t(-1) / sizeof(value_type);
549#endif
550 }
551
552 /**
553 * @brief Obtain an allocator to use when copying a container.
554 * @param __rhs An allocator.
555 * @return @c __rhs
556 */
557 static _GLIBCXX20_CONSTEXPR allocator_type
558 select_on_container_copy_construction(const allocator_type& __rhs)
559 { return __rhs; }
560 };
561
562#if __cplusplus201703L < 201703L
563 template<typename _Alloc>
564 inline void
565 __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
566 { __one = __two; }
567
568 template<typename _Alloc>
569 inline void
570 __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
571 { }
572#endif
573
574 template<typename _Alloc>
575 _GLIBCXX14_CONSTEXPRconstexpr inline void
576 __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
577 {
578 typedef allocator_traits<_Alloc> __traits;
579 typedef typename __traits::propagate_on_container_copy_assignment __pocca;
580#if __cplusplus201703L >= 201703L
581 if constexpr (__pocca::value)
582 __one = __two;
583#else
584 __do_alloc_on_copy(__one, __two, __pocca());
585#endif
586 }
587
588 template<typename _Alloc>
589 constexpr _Alloc
590 __alloc_on_copy(const _Alloc& __a)
591 {
592 typedef allocator_traits<_Alloc> __traits;
593 return __traits::select_on_container_copy_construction(__a);
594 }
595
596#if __cplusplus201703L < 201703L
597 template<typename _Alloc>
598 inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
599 { __one = std::move(__two); }
600
601 template<typename _Alloc>
602 inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
603 { }
604#endif
605
606 template<typename _Alloc>
607 _GLIBCXX14_CONSTEXPRconstexpr inline void
608 __alloc_on_move(_Alloc& __one, _Alloc& __two)
609 {
610 typedef allocator_traits<_Alloc> __traits;
611 typedef typename __traits::propagate_on_container_move_assignment __pocma;
612#if __cplusplus201703L >= 201703L
613 if constexpr (__pocma::value)
614 __one = std::move(__two);
615#else
616 __do_alloc_on_move(__one, __two, __pocma());
617#endif
618 }
619
620#if __cplusplus201703L < 201703L
621 template<typename _Alloc>
622 inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
623 {
624 using std::swap;
625 swap(__one, __two);
626 }
627
628 template<typename _Alloc>
629 inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
630 { }
631#endif
632
633 template<typename _Alloc>
634 _GLIBCXX14_CONSTEXPRconstexpr inline void
635 __alloc_on_swap(_Alloc& __one, _Alloc& __two)
636 {
637 typedef allocator_traits<_Alloc> __traits;
638 typedef typename __traits::propagate_on_container_swap __pocs;
639#if __cplusplus201703L >= 201703L
640 if constexpr (__pocs::value)
641 {
642 using std::swap;
643 swap(__one, __two);
644 }
645#else
646 __do_alloc_on_swap(__one, __two, __pocs());
647#endif
648 }
649
650 template<typename _Alloc, typename _Tp,
651 typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
652 typename = void>
653 struct __is_alloc_insertable_impl
654 : false_type
655 { };
656
657 template<typename _Alloc, typename _Tp, typename _ValueT>
658 struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
659 __void_t<decltype(allocator_traits<_Alloc>::construct(
660 std::declval<_Alloc&>(), std::declval<_ValueT*>(),
661 std::declval<_Tp>()))>>
662 : true_type
663 { };
664
665 // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
666 // (might be wrong if _Alloc::construct exists but is not constrained,
667 // i.e. actually trying to use it would still be invalid. Use with caution.)
668 template<typename _Alloc>
669 struct __is_copy_insertable
670 : __is_alloc_insertable_impl<_Alloc,
671 typename _Alloc::value_type const&>::type
672 { };
673
674 // std::allocator<_Tp> just requires CopyConstructible
675 template<typename _Tp>
676 struct __is_copy_insertable<allocator<_Tp>>
677 : is_copy_constructible<_Tp>
678 { };
679
680 // true if _Alloc::value_type is MoveInsertable into containers using _Alloc
681 // (might be wrong if _Alloc::construct exists but is not constrained,
682 // i.e. actually trying to use it would still be invalid. Use with caution.)
683 template<typename _Alloc>
684 struct __is_move_insertable
685 : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
686 { };
687
688 // std::allocator<_Tp> just requires MoveConstructible
689 template<typename _Tp>
690 struct __is_move_insertable<allocator<_Tp>>
691 : is_move_constructible<_Tp>
692 { };
693
694 // Trait to detect Allocator-like types.
695 template<typename _Alloc, typename = void>
696 struct __is_allocator : false_type { };
697
698 template<typename _Alloc>
699 struct __is_allocator<_Alloc,
700 __void_t<typename _Alloc::value_type,
701 decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
702 : true_type { };
703
704 template<typename _Alloc>
705 using _RequireAllocator
706 = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
707
708 template<typename _Alloc>
709 using _RequireNotAllocator
710 = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
711#endif // C++11
712
713 /**
714 * Destroy a range of objects using the supplied allocator. For
715 * non-default allocators we do not optimize away invocation of
716 * destroy() even if _Tp has a trivial destructor.
717 */
718
719 template<typename _ForwardIterator, typename _Allocator>
720 void
721 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
722 _Allocator& __alloc)
723 {
724 for (; __first != __last; ++__first)
725#if __cplusplus201703L < 201103L
726 __alloc.destroy(std::__addressof(*__first));
727#else
728 allocator_traits<_Allocator>::destroy(__alloc,
729 std::__addressof(*__first));
730#endif
731 }
732
733 template<typename _ForwardIterator, typename _Tp>
734 inline void
735 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
736 allocator<_Tp>&)
737 {
738 _Destroy(__first, __last);
739 }
740
741_GLIBCXX_END_NAMESPACE_VERSION
742} // namespace std
743#endif // _ALLOC_TRAITS_H

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/ext/new_allocator.h

1// Allocator that wraps operator new -*- C++ -*-
2
3// Copyright (C) 2001-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file ext/new_allocator.h
26 * This file is a GNU extension to the Standard C++ Library.
27 */
28
29#ifndef _NEW_ALLOCATOR_H1
30#define _NEW_ALLOCATOR_H1 1
31
32#include <bits/c++config.h>
33#include <new>
34#include <bits/functexcept.h>
35#include <bits/move.h>
36#if __cplusplus201703L >= 201103L
37#include <type_traits>
38#endif
39
40namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
41{
42_GLIBCXX_BEGIN_NAMESPACE_VERSION
43
44 /**
45 * @brief An allocator that uses global new, as per [20.4].
46 * @ingroup allocators
47 *
48 * This is precisely the allocator defined in the C++ Standard.
49 * - all allocation calls operator new
50 * - all deallocation calls operator delete
51 *
52 * @tparam _Tp Type of allocated object.
53 */
54 template<typename _Tp>
55 class new_allocator
56 {
57 public:
58 typedef _Tp value_type;
59 typedef std::size_t size_type;
60 typedef std::ptrdiff_t difference_type;
61#if __cplusplus201703L <= 201703L
62 typedef _Tp* pointer;
63 typedef const _Tp* const_pointer;
64 typedef _Tp& reference;
65 typedef const _Tp& const_reference;
66
67 template<typename _Tp1>
68 struct rebind
69 { typedef new_allocator<_Tp1> other; };
70#endif
71
72#if __cplusplus201703L >= 201103L
73 // _GLIBCXX_RESOLVE_LIB_DEFECTS
74 // 2103. propagate_on_container_move_assignment
75 typedef std::true_type propagate_on_container_move_assignment;
76#endif
77
78 _GLIBCXX20_CONSTEXPR
79 new_allocator() _GLIBCXX_USE_NOEXCEPTnoexcept { }
80
81 _GLIBCXX20_CONSTEXPR
82 new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPTnoexcept { }
83
84 template<typename _Tp1>
85 _GLIBCXX20_CONSTEXPR
86 new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPTnoexcept { }
87
88#if __cplusplus201703L <= 201703L
89 ~new_allocator() _GLIBCXX_USE_NOEXCEPTnoexcept { }
90
91 pointer
92 address(reference __x) const _GLIBCXX_NOEXCEPTnoexcept
93 { return std::__addressof(__x); }
94
95 const_pointer
96 address(const_reference __x) const _GLIBCXX_NOEXCEPTnoexcept
97 { return std::__addressof(__x); }
98#endif
99
100 // NB: __n is permitted to be 0. The C++ standard says nothing
101 // about what the return value is when __n == 0.
102 _GLIBCXX_NODISCARD[[__nodiscard__]] _Tp*
103 allocate(size_type __n, const void* = static_cast<const void*>(0))
104 {
105 if (__n > this->_M_max_size())
106 std::__throw_bad_alloc();
107
108#if __cpp_aligned_new201606L
109 if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__16UL)
110 {
111 std::align_val_t __al = std::align_val_t(alignof(_Tp));
112 return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al));
113 }
114#endif
115 return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
116 }
117
118 // __p is not permitted to be a null pointer.
119 void
120 deallocate(_Tp* __p, size_type __t)
121 {
122#if __cpp_aligned_new201606L
123 if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__16UL)
124 {
125 ::operator delete(__p,
126# if __cpp_sized_deallocation
127 __t * sizeof(_Tp),
128# endif
129 std::align_val_t(alignof(_Tp)));
130 return;
131 }
132#endif
133 ::operator delete(__p
134#if __cpp_sized_deallocation
135 , __t * sizeof(_Tp)
136#endif
137 );
138 }
139
140#if __cplusplus201703L <= 201703L
141 size_type
142 max_size() const _GLIBCXX_USE_NOEXCEPTnoexcept
143 { return _M_max_size(); }
144
145#if __cplusplus201703L >= 201103L
146 template<typename _Up, typename... _Args>
147 void
148 construct(_Up* __p, _Args&&... __args)
149 noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
150 { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
13
Calling implicit destructor for 'VclPtr<vcl::Window>'
14
Calling '~Reference'
21
Returning from '~Reference'
22
Returning from destructor for 'VclPtr<vcl::Window>'
151
152 template<typename _Up>
153 void
154 destroy(_Up* __p)
155 noexcept(std::is_nothrow_destructible<_Up>::value)
156 { __p->~_Up(); }
157#else
158 // _GLIBCXX_RESOLVE_LIB_DEFECTS
159 // 402. wrong new expression in [some_] allocator::construct
160 void
161 construct(pointer __p, const _Tp& __val)
162 { ::new((void *)__p) _Tp(__val); }
163
164 void
165 destroy(pointer __p) { __p->~_Tp(); }
166#endif
167#endif // ! C++20
168
169 template<typename _Up>
170 friend _GLIBCXX20_CONSTEXPR bool
171 operator==(const new_allocator&, const new_allocator<_Up>&)
172 _GLIBCXX_NOTHROWnoexcept
173 { return true; }
174
175#if __cpp_impl_three_way_comparison < 201907L
176 template<typename _Up>
177 friend _GLIBCXX20_CONSTEXPR bool
178 operator!=(const new_allocator&, const new_allocator<_Up>&)
179 _GLIBCXX_NOTHROWnoexcept
180 { return false; }
181#endif
182
183 private:
184 _GLIBCXX_CONSTEXPRconstexpr size_type
185 _M_max_size() const _GLIBCXX_USE_NOEXCEPTnoexcept
186 {
187#if __PTRDIFF_MAX__9223372036854775807L < __SIZE_MAX__18446744073709551615UL
188 return std::size_t(__PTRDIFF_MAX__9223372036854775807L) / sizeof(_Tp);
189#else
190 return std::size_t(-1) / sizeof(_Tp);
191#endif
192 }
193 };
194
195_GLIBCXX_END_NAMESPACE_VERSION
196} // namespace
197
198#endif

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody
14.1
Field 'm_pBody' is non-null
32.1
Field 'm_pBody' is non-null
14.1
Field 'm_pBody' is non-null
32.1
Field 'm_pBody' is non-null
14.1
Field 'm_pBody' is non-null
32.1
Field 'm_pBody' is non-null
14.1
Field 'm_pBody' is non-null
32.1
Field 'm_pBody' is non-null
14.1
Field 'm_pBody' is non-null
32.1
Field 'm_pBody' is non-null
14.1
Field 'm_pBody' is non-null
32.1
Field 'm_pBody' is non-null
14.1
Field 'm_pBody' is non-null
32.1
Field 'm_pBody' is non-null
14.1
Field 'm_pBody' is non-null
32.1
Field 'm_pBody' is non-null
)
15
Taking true branch
33
Taking true branch
113 m_pBody->release();
16
Calling 'VclReferenceBase::release'
20
Returning; memory was released
34
Use of memory after it is freed
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
17
Assuming the condition is true
18
Taking true branch
40 delete this;
19
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif