Bug Summary

File:home/maarten/src/libreoffice/core/framework/source/uiconfiguration/imagemanagerimpl.cxx
Warning:line 730, column 22
Called C++ object pointer is null

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 imagemanagerimpl.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 -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 FWK_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/framework/source/inc -I /home/maarten/src/libreoffice/core/framework/inc -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -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/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/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/framework/source/uiconfiguration/imagemanagerimpl.cxx

/home/maarten/src/libreoffice/core/framework/source/uiconfiguration/imagemanagerimpl.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 * 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#include "imagemanagerimpl.hxx"
21#include <xml/imagesconfiguration.hxx>
22#include <uiconfiguration/imagetype.hxx>
23#include <uiconfiguration/graphicnameaccess.hxx>
24
25#include <properties.h>
26
27#include <com/sun/star/frame/theUICommandDescription.hpp>
28#include <com/sun/star/ui/ConfigurationEvent.hpp>
29#include <com/sun/star/lang/DisposedException.hpp>
30#include <com/sun/star/lang/IllegalAccessException.hpp>
31#include <com/sun/star/beans/XPropertySet.hpp>
32#include <com/sun/star/beans/PropertyValue.hpp>
33#include <com/sun/star/embed/ElementModes.hpp>
34#include <com/sun/star/embed/InvalidStorageException.hpp>
35#include <com/sun/star/embed/StorageWrappedTargetException.hpp>
36#include <com/sun/star/io/IOException.hpp>
37#include <com/sun/star/io/XStream.hpp>
38#include <com/sun/star/ui/ImageType.hpp>
39#include <vcl/graph.hxx>
40#include <vcl/svapp.hxx>
41#include <o3tl/enumrange.hxx>
42#include <osl/mutex.hxx>
43#include <comphelper/sequence.hxx>
44#include <unotools/ucbstreamhelper.hxx>
45#include <vcl/pngread.hxx>
46#include <vcl/pngwrite.hxx>
47#include <rtl/instance.hxx>
48#include <memory>
49
50using ::com::sun::star::uno::Sequence;
51using ::com::sun::star::uno::XInterface;
52using ::com::sun::star::uno::RuntimeException;
53using ::com::sun::star::uno::UNO_QUERY;
54using ::com::sun::star::uno::Any;
55using ::com::sun::star::graphic::XGraphic;
56using namespace ::com::sun::star;
57using namespace ::com::sun::star::io;
58using namespace ::com::sun::star::embed;
59using namespace ::com::sun::star::lang;
60using namespace ::com::sun::star::container;
61using namespace ::com::sun::star::beans;
62using namespace ::com::sun::star::ui;
63using namespace ::cppu;
64
65const sal_Int16 MAX_IMAGETYPE_VALUE = css::ui::ImageType::SIZE_32;
66
67const char IMAGE_FOLDER[] = "images";
68const char BITMAPS_FOLDER[] = "Bitmaps";
69
70const o3tl::enumarray<vcl::ImageType, const char*> IMAGELIST_XML_FILE =
71{
72 "sc_imagelist.xml",
73 "lc_imagelist.xml",
74 "xc_imagelist.xml"
75};
76
77const o3tl::enumarray<vcl::ImageType, const char*> BITMAP_FILE_NAMES =
78{
79 "sc_userimages.png",
80 "lc_userimages.png",
81 "xc_userimages.png"
82};
83
84namespace framework
85{
86
87static GlobalImageList* pGlobalImageList = nullptr;
88
89namespace
90{
91 class theGlobalImageListMutex
92 : public rtl::Static<osl::Mutex, theGlobalImageListMutex> {};
93}
94
95static osl::Mutex& getGlobalImageListMutex()
96{
97 return theGlobalImageListMutex::get();
98}
99
100static GlobalImageList* getGlobalImageList( const uno::Reference< uno::XComponentContext >& rxContext )
101{
102 osl::MutexGuard guard( getGlobalImageListMutex() );
103
104 if ( pGlobalImageList == nullptr )
105 pGlobalImageList = new GlobalImageList( rxContext );
106
107 return pGlobalImageList;
108}
109
110CmdImageList::CmdImageList( const uno::Reference< uno::XComponentContext >& rxContext, const OUString& aModuleIdentifier ) :
111 m_bInitialized(false),
112 m_aModuleIdentifier( aModuleIdentifier ),
113 m_xContext( rxContext )
114{
115}
116
117CmdImageList::~CmdImageList()
118{
119}
120
121void CmdImageList::initialize()
122{
123 if (m_bInitialized)
124 return;
125
126 const OUString aCommandImageList(UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDIMAGELIST"private:resource/image/commandimagelist");
127
128 Sequence<OUString> aCommandImageSeq;
129 uno::Reference<XNameAccess> xCommandDesc = frame::theUICommandDescription::get(m_xContext);
130
131 if (!m_aModuleIdentifier.isEmpty())
132 {
133 // If we have a module identifier - use to retrieve the command image name list from it.
134 // Otherwise we will use the global command image list
135 try
136 {
137 xCommandDesc->getByName(m_aModuleIdentifier) >>= xCommandDesc;
138 if (xCommandDesc.is())
139 xCommandDesc->getByName(aCommandImageList) >>= aCommandImageSeq;
140 }
141 catch (const NoSuchElementException&)
142 {
143 // Module unknown we will work with an empty command image list!
144 return;
145 }
146 }
147
148 if (xCommandDesc.is())
149 {
150 try
151 {
152 xCommandDesc->getByName(aCommandImageList) >>= aCommandImageSeq;
153 }
154 catch (const NoSuchElementException&)
155 {
156 }
157 catch (const WrappedTargetException&)
158 {
159 }
160 }
161
162 m_aResolver.registerCommands(aCommandImageSeq);
163
164 m_bInitialized = true;
165}
166
167
168Image CmdImageList::getImageFromCommandURL(vcl::ImageType nImageType, const OUString& rCommandURL)
169{
170 initialize();
171 return m_aResolver.getImageFromCommandURL(nImageType, rCommandURL);
172}
173
174bool CmdImageList::hasImage(vcl::ImageType /*nImageType*/, const OUString& rCommandURL)
175{
176 initialize();
177 return m_aResolver.hasImage(rCommandURL);
178}
179
180std::vector<OUString>& CmdImageList::getImageCommandNames()
181{
182 return m_aResolver.getCommandNames();
183}
184
185GlobalImageList::GlobalImageList( const uno::Reference< uno::XComponentContext >& rxContext ) :
186 CmdImageList( rxContext, OUString() )
187{
188}
189
190GlobalImageList::~GlobalImageList()
191{
192 osl::MutexGuard guard( getGlobalImageListMutex() );
193 // remove global pointer as we destroy the object now
194 pGlobalImageList = nullptr;
195}
196
197Image GlobalImageList::getImageFromCommandURL( vcl::ImageType nImageType, const OUString& rCommandURL )
198{
199 osl::MutexGuard guard( getGlobalImageListMutex() );
200 return CmdImageList::getImageFromCommandURL( nImageType, rCommandURL );
201}
202
203bool GlobalImageList::hasImage( vcl::ImageType nImageType, const OUString& rCommandURL )
204{
205 osl::MutexGuard guard( getGlobalImageListMutex() );
206 return CmdImageList::hasImage( nImageType, rCommandURL );
207}
208
209::std::vector< OUString >& GlobalImageList::getImageCommandNames()
210{
211 osl::MutexGuard guard( getGlobalImageListMutex() );
212 return CmdImageList::getImageCommandNames();
213}
214
215static bool implts_checkAndScaleGraphic( uno::Reference< XGraphic >& rOutGraphic, const uno::Reference< XGraphic >& rInGraphic, vcl::ImageType nImageType )
216{
217 if ( !rInGraphic.is() )
218 {
219 rOutGraphic = uno::Reference<graphic::XGraphic>();
220 return false;
221 }
222
223 static const o3tl::enumarray<vcl::ImageType, Size> BITMAP_SIZE =
224 {
225 Size(16, 16), Size(24, 24), Size(32, 32)
226 };
227
228 // Check size and scale it
229 Graphic aImage(rInGraphic);
230 if (BITMAP_SIZE[nImageType] != aImage.GetSizePixel())
231 {
232 BitmapEx aBitmap = aImage.GetBitmapEx();
233 aBitmap.Scale(BITMAP_SIZE[nImageType]);
234 aImage = Graphic(aBitmap);
235 rOutGraphic = aImage.GetXGraphic();
236 }
237 else
238 rOutGraphic = rInGraphic;
239
240 return true;
241}
242
243static vcl::ImageType implts_convertImageTypeToIndex( sal_Int16 nImageType )
244{
245 if (nImageType & css::ui::ImageType::SIZE_LARGE)
246 return vcl::ImageType::Size26;
247 else if (nImageType & css::ui::ImageType::SIZE_32)
248 return vcl::ImageType::Size32;
249 else
250 return vcl::ImageType::Size16;
251}
252
253ImageList* ImageManagerImpl::implts_getUserImageList( vcl::ImageType nImageType )
254{
255 SolarMutexGuard g;
256 if ( !m_pUserImageList[nImageType] )
10
Taking false branch
257 implts_loadUserImages( nImageType, m_xUserImageStorage, m_xUserBitmapsStorage );
258
259 return m_pUserImageList[nImageType].get();
11
Value assigned to field 'm_bUseGlobal', which participates in a condition later
260}
261
262void ImageManagerImpl::implts_initialize()
263{
264 // Initialize the top-level structures with the storage data
265 if ( !m_xUserConfigStorage.is() )
266 return;
267
268 long nModes = m_bReadOnly ? ElementModes::READ : ElementModes::READWRITE;
269
270 try
271 {
272 m_xUserImageStorage = m_xUserConfigStorage->openStorageElement( IMAGE_FOLDER,
273 nModes );
274 if ( m_xUserImageStorage.is() )
275 {
276 m_xUserBitmapsStorage = m_xUserImageStorage->openStorageElement( BITMAPS_FOLDER,
277 nModes );
278 }
279 }
280 catch ( const css::container::NoSuchElementException& )
281 {
282 }
283 catch ( const css::embed::InvalidStorageException& )
284 {
285 }
286 catch ( const css::lang::IllegalArgumentException& )
287 {
288 }
289 catch ( const css::io::IOException& )
290 {
291 }
292 catch ( const css::embed::StorageWrappedTargetException& )
293 {
294 }
295}
296
297void ImageManagerImpl::implts_loadUserImages(
298 vcl::ImageType nImageType,
299 const uno::Reference< XStorage >& xUserImageStorage,
300 const uno::Reference< XStorage >& xUserBitmapsStorage )
301{
302 SolarMutexGuard g;
303
304 if ( xUserImageStorage.is() && xUserBitmapsStorage.is() )
305 {
306 try
307 {
308 uno::Reference< XStream > xStream = xUserImageStorage->openStreamElement( OUString::createFromAscii( IMAGELIST_XML_FILE[nImageType] ),
309 ElementModes::READ );
310 uno::Reference< XInputStream > xInputStream = xStream->getInputStream();
311
312 ImageItemDescriptorList aUserImageListInfo;
313 ImagesConfiguration::LoadImages( m_xContext,
314 xInputStream,
315 aUserImageListInfo );
316 if ( !aUserImageListInfo.empty() )
317 {
318 sal_Int32 nCount = aUserImageListInfo.size();
319 std::vector< OUString > aUserImagesVector;
320 aUserImagesVector.reserve(nCount);
321 for ( sal_Int32 i=0; i < nCount; i++ )
322 {
323 const ImageItemDescriptor& rItem = aUserImageListInfo[i];
324 aUserImagesVector.push_back( rItem.aCommandURL );
325 }
326
327 uno::Reference< XStream > xBitmapStream = xUserBitmapsStorage->openStreamElement(
328 OUString::createFromAscii( BITMAP_FILE_NAMES[nImageType] ),
329 ElementModes::READ );
330
331 if ( xBitmapStream.is() )
332 {
333 BitmapEx aUserBitmap;
334 {
335 std::unique_ptr<SvStream> pSvStream(utl::UcbStreamHelper::CreateStream( xBitmapStream ));
336 vcl::PNGReader aPngReader( *pSvStream );
337 aUserBitmap = aPngReader.Read();
338 }
339
340 // Delete old image list and create a new one from the read bitmap
341 m_pUserImageList[nImageType].reset(new ImageList());
342 m_pUserImageList[nImageType]->InsertFromHorizontalStrip
343 ( aUserBitmap, aUserImagesVector );
344 return;
345 }
346 }
347 }
348 catch ( const css::container::NoSuchElementException& )
349 {
350 }
351 catch ( const css::embed::InvalidStorageException& )
352 {
353 }
354 catch ( const css::lang::IllegalArgumentException& )
355 {
356 }
357 catch ( const css::io::IOException& )
358 {
359 }
360 catch ( const css::embed::StorageWrappedTargetException& )
361 {
362 }
363 }
364
365 // Destroy old image list - create a new empty one
366 m_pUserImageList[nImageType].reset(new ImageList);
367}
368
369bool ImageManagerImpl::implts_storeUserImages(
370 vcl::ImageType nImageType,
371 const uno::Reference< XStorage >& xUserImageStorage,
372 const uno::Reference< XStorage >& xUserBitmapsStorage )
373{
374 SolarMutexGuard g;
375
376 if ( m_bModified )
377 {
378 ImageList* pImageList = implts_getUserImageList( nImageType );
379 if ( pImageList->GetImageCount() > 0 )
380 {
381 ImageItemDescriptorList aUserImageListInfo;
382
383 for ( sal_uInt16 i=0; i < pImageList->GetImageCount(); i++ )
384 {
385 ImageItemDescriptor aItem;
386 aItem.aCommandURL = pImageList->GetImageName( i );
387 aUserImageListInfo.push_back( aItem );
388 }
389
390 uno::Reference< XTransactedObject > xTransaction;
391 uno::Reference< XOutputStream > xOutputStream;
392 uno::Reference< XStream > xStream = xUserImageStorage->openStreamElement( OUString::createFromAscii( IMAGELIST_XML_FILE[nImageType] ),
393 ElementModes::WRITE|ElementModes::TRUNCATE );
394 if ( xStream.is() )
395 {
396 uno::Reference< XStream > xBitmapStream =
397 xUserBitmapsStorage->openStreamElement( OUString::createFromAscii( BITMAP_FILE_NAMES[nImageType] ),
398 ElementModes::WRITE|ElementModes::TRUNCATE );
399 if ( xBitmapStream.is() )
400 {
401 {
402 std::unique_ptr<SvStream> pSvStream(utl::UcbStreamHelper::CreateStream( xBitmapStream ));
403 vcl::PNGWriter aPngWriter( pImageList->GetAsHorizontalStrip() );
404 aPngWriter.Write( *pSvStream );
405 }
406
407 // Commit user bitmaps storage
408 xTransaction.set( xUserBitmapsStorage, UNO_QUERY );
409 if ( xTransaction.is() )
410 xTransaction->commit();
411 }
412
413 xOutputStream = xStream->getOutputStream();
414 if ( xOutputStream.is() )
415 ImagesConfiguration::StoreImages( m_xContext, xOutputStream, aUserImageListInfo );
416
417 // Commit user image storage
418 xTransaction.set( xUserImageStorage, UNO_QUERY );
419 if ( xTransaction.is() )
420 xTransaction->commit();
421 }
422
423 return true;
424 }
425 else
426 {
427 // Remove the streams from the storage, if we have no data. We have to catch
428 // the NoSuchElementException as it can be possible that there is no stream at all!
429 try
430 {
431 xUserImageStorage->removeElement( OUString::createFromAscii( IMAGELIST_XML_FILE[nImageType] ));
432 }
433 catch ( const css::container::NoSuchElementException& )
434 {
435 }
436
437 try
438 {
439 xUserBitmapsStorage->removeElement( OUString::createFromAscii( BITMAP_FILE_NAMES[nImageType] ));
440 }
441 catch ( const css::container::NoSuchElementException& )
442 {
443 }
444
445 uno::Reference< XTransactedObject > xTransaction;
446
447 // Commit user image storage
448 xTransaction.set( xUserImageStorage, UNO_QUERY );
449 if ( xTransaction.is() )
450 xTransaction->commit();
451
452 // Commit user bitmaps storage
453 xTransaction.set( xUserBitmapsStorage, UNO_QUERY );
454 if ( xTransaction.is() )
455 xTransaction->commit();
456
457 return true;
458 }
459 }
460
461 return false;
462}
463
464const rtl::Reference< GlobalImageList >& ImageManagerImpl::implts_getGlobalImageList()
465{
466 SolarMutexGuard g;
467
468 if ( !m_pGlobalImageList.is() )
469 m_pGlobalImageList = getGlobalImageList( m_xContext );
470 return m_pGlobalImageList;
471}
472
473CmdImageList* ImageManagerImpl::implts_getDefaultImageList()
474{
475 SolarMutexGuard g;
476
477 if ( !m_pDefaultImageList )
478 m_pDefaultImageList.reset(new CmdImageList( m_xContext, m_aModuleIdentifier ));
479
480 return m_pDefaultImageList.get();
481}
482
483ImageManagerImpl::ImageManagerImpl( const uno::Reference< uno::XComponentContext >& rxContext,::cppu::OWeakObject* pOwner,bool _bUseGlobal ) :
484 m_xContext( rxContext )
485 , m_pOwner(pOwner)
486 , m_aResourceString( "private:resource/images/moduleimages" )
487 , m_aListenerContainer( m_mutex )
488 , m_bUseGlobal(_bUseGlobal)
489 , m_bReadOnly( true )
490 , m_bInitialized( false )
491 , m_bModified( false )
492 , m_bDisposed( false )
493{
494 for ( vcl::ImageType n : o3tl::enumrange<vcl::ImageType>() )
495 {
496 m_pUserImageList[n] = nullptr;
497 m_bUserImageListModified[n] = false;
498 }
499}
500
501ImageManagerImpl::~ImageManagerImpl()
502{
503 clear();
504}
505
506void ImageManagerImpl::dispose()
507{
508 uno::Reference< uno::XInterface > xOwner(m_pOwner);
509 css::lang::EventObject aEvent( xOwner );
510 m_aListenerContainer.disposeAndClear( aEvent );
511
512 {
513 SolarMutexGuard g;
514 m_xUserConfigStorage.clear();
515 m_xUserImageStorage.clear();
516 m_xUserRootCommit.clear();
517 m_bModified = false;
518 m_bDisposed = true;
519
520 // delete user and default image list on dispose
521 for (auto& n : m_pUserImageList)
522 {
523 n.reset();
524 }
525 m_pDefaultImageList.reset();
526 }
527
528}
529void ImageManagerImpl::addEventListener( const uno::Reference< XEventListener >& xListener )
530{
531 {
532 SolarMutexGuard g;
533
534 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
535 if ( m_bDisposed )
536 throw DisposedException();
537 }
538
539 m_aListenerContainer.addInterface( cppu::UnoType<XEventListener>::get(), xListener );
540}
541
542void ImageManagerImpl::removeEventListener( const uno::Reference< XEventListener >& xListener )
543{
544 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
545 m_aListenerContainer.removeInterface( cppu::UnoType<XEventListener>::get(), xListener );
546}
547
548// XInitialization
549void ImageManagerImpl::initialize( const Sequence< Any >& aArguments )
550{
551 SolarMutexGuard g;
552
553 if ( m_bInitialized )
554 return;
555
556 for ( const Any& rArg : aArguments )
557 {
558 PropertyValue aPropValue;
559 if ( rArg >>= aPropValue )
560 {
561 if ( aPropValue.Name == "UserConfigStorage" )
562 {
563 aPropValue.Value >>= m_xUserConfigStorage;
564 }
565 else if ( aPropValue.Name == "ModuleIdentifier" )
566 {
567 aPropValue.Value >>= m_aModuleIdentifier;
568 }
569 else if ( aPropValue.Name == "UserRootCommit" )
570 {
571 aPropValue.Value >>= m_xUserRootCommit;
572 }
573 }
574 }
575
576 if ( m_xUserConfigStorage.is() )
577 {
578 uno::Reference< XPropertySet > xPropSet( m_xUserConfigStorage, UNO_QUERY );
579 if ( xPropSet.is() )
580 {
581 long nOpenMode = 0;
582 if ( xPropSet->getPropertyValue("OpenMode") >>= nOpenMode )
583 m_bReadOnly = !( nOpenMode & ElementModes::WRITE );
584 }
585 }
586
587 implts_initialize();
588
589 m_bInitialized = true;
590}
591
592// XImageManagerImpl
593void ImageManagerImpl::reset()
594{
595 SolarMutexGuard g;
596
597 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
598 if ( m_bDisposed )
599 throw DisposedException();
600
601 std::vector< OUString > aUserImageNames;
602
603 for ( vcl::ImageType i : o3tl::enumrange<vcl::ImageType>() )
604 {
605 aUserImageNames.clear();
606 ImageList* pImageList = implts_getUserImageList(i);
607 pImageList->GetImageNames( aUserImageNames );
608
609 Sequence< OUString > aRemoveList( comphelper::containerToSequence(aUserImageNames) );
610
611 // Remove images
612 removeImages( sal_Int16( i ), aRemoveList );
613 m_bUserImageListModified[i] = true;
614 }
615
616 m_bModified = true;
617}
618
619Sequence< OUString > ImageManagerImpl::getAllImageNames( ::sal_Int16 nImageType )
620{
621 SolarMutexGuard g;
622
623 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
624 if ( m_bDisposed )
625 throw DisposedException();
626
627 ImageNameMap aImageCmdNameMap;
628
629 vcl::ImageType nIndex = implts_convertImageTypeToIndex( nImageType );
630
631 sal_uInt32 i( 0 );
632 if ( m_bUseGlobal )
633 {
634 rtl::Reference< GlobalImageList > rGlobalImageList = implts_getGlobalImageList();
635
636 const std::vector< OUString >& rGlobalImageNameVector = rGlobalImageList->getImageCommandNames();
637 const sal_uInt32 nGlobalCount = rGlobalImageNameVector.size();
638 for ( i = 0; i < nGlobalCount; i++ )
639 aImageCmdNameMap.emplace( rGlobalImageNameVector[i], true );
640
641 const std::vector< OUString >& rModuleImageNameVector = implts_getDefaultImageList()->getImageCommandNames();
642 const sal_uInt32 nModuleCount = rModuleImageNameVector.size();
643 for ( i = 0; i < nModuleCount; i++ )
644 aImageCmdNameMap.emplace( rModuleImageNameVector[i], true );
645 }
646
647 ImageList* pImageList = implts_getUserImageList(nIndex);
648 std::vector< OUString > rUserImageNames;
649 pImageList->GetImageNames( rUserImageNames );
650 const sal_uInt32 nUserCount = rUserImageNames.size();
651 for ( i = 0; i < nUserCount; i++ )
652 aImageCmdNameMap.emplace( rUserImageNames[i], true );
653
654 return comphelper::mapKeysToSequence( aImageCmdNameMap );
655}
656
657bool ImageManagerImpl::hasImage( ::sal_Int16 nImageType, const OUString& aCommandURL )
658{
659 SolarMutexGuard g;
660
661 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
662 if ( m_bDisposed )
663 throw DisposedException();
664
665 if (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE ))
666 throw IllegalArgumentException();
667
668 vcl::ImageType nIndex = implts_convertImageTypeToIndex( nImageType );
669 if ( m_bUseGlobal && implts_getGlobalImageList()->hasImage( nIndex, aCommandURL ))
670 return true;
671 else
672 {
673 if ( m_bUseGlobal && implts_getDefaultImageList()->hasImage( nIndex, aCommandURL ))
674 return true;
675 else
676 {
677 // User layer
678 ImageList* pImageList = implts_getUserImageList(nIndex);
679 if ( pImageList )
680 return ( pImageList->GetImagePos( aCommandURL ) != IMAGELIST_IMAGE_NOTFOUND(sal_uInt16(0xFFFF)) );
681 }
682 }
683
684 return false;
685}
686
687namespace
688{
689 css::uno::Reference< css::graphic::XGraphic > GetXGraphic(const Image &rImage)
690 {
691 return Graphic(rImage).GetXGraphic();
692 }
693}
694
695Sequence< uno::Reference< XGraphic > > ImageManagerImpl::getImages(
696 ::sal_Int16 nImageType,
697 const Sequence< OUString >& aCommandURLSequence )
698{
699 SolarMutexGuard g;
700
701 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
702 if ( m_bDisposed )
1
Assuming field 'm_bDisposed' is false
2
Taking false branch
703 throw DisposedException();
704
705 if (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE ))
3
Assuming 'nImageType' is >= 0
4
Assuming 'nImageType' is <= 'MAX_IMAGETYPE_VALUE'
5
Taking false branch
706 throw IllegalArgumentException();
707
708 Sequence< uno::Reference< XGraphic > > aGraphSeq( aCommandURLSequence.getLength() );
709
710 vcl::ImageType nIndex = implts_convertImageTypeToIndex( nImageType );
711 rtl::Reference< GlobalImageList > rGlobalImageList;
712 CmdImageList* pDefaultImageList = nullptr;
6
'pDefaultImageList' initialized to a null pointer value
713 if ( m_bUseGlobal )
7
Assuming field 'm_bUseGlobal' is false
8
Taking false branch
714 {
715 rGlobalImageList = implts_getGlobalImageList();
716 pDefaultImageList = implts_getDefaultImageList();
717 }
718 ImageList* pUserImageList = implts_getUserImageList(nIndex);
9
Calling 'ImageManagerImpl::implts_getUserImageList'
12
Returning from 'ImageManagerImpl::implts_getUserImageList'
719
720 // We have to search our image list in the following order:
721 // 1. user image list (read/write)
722 // 2. module image list (read)
723 // 3. global image list (read)
724 sal_Int32 n = 0;
725 for ( const OUString& rURL : aCommandURLSequence )
13
Assuming '__begin1' is not equal to '__end1'
726 {
727 Image aImage = pUserImageList->GetImage( rURL );
728 if ( !aImage && m_bUseGlobal )
14
Calling 'Image::operator!'
21
Returning from 'Image::operator!'
22
Assuming field 'm_bUseGlobal' is true
23
Taking true branch
729 {
730 aImage = pDefaultImageList->getImageFromCommandURL( nIndex, rURL );
24
Called C++ object pointer is null
731 if ( !aImage )
732 aImage = rGlobalImageList->getImageFromCommandURL( nIndex, rURL );
733 }
734
735 aGraphSeq[n++] = GetXGraphic(aImage);
736 }
737
738 return aGraphSeq;
739}
740
741void ImageManagerImpl::replaceImages(
742 ::sal_Int16 nImageType,
743 const Sequence< OUString >& aCommandURLSequence,
744 const Sequence< uno::Reference< XGraphic > >& aGraphicsSequence )
745{
746 GraphicNameAccess* pInsertedImages( nullptr );
747 GraphicNameAccess* pReplacedImages( nullptr );
748
749 {
750 SolarMutexGuard g;
751
752 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
753 if ( m_bDisposed )
754 throw DisposedException();
755
756 if (( aCommandURLSequence.getLength() != aGraphicsSequence.getLength() ) ||
757 (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE )))
758 throw IllegalArgumentException();
759
760 if ( m_bReadOnly )
761 throw IllegalAccessException();
762
763 vcl::ImageType nIndex = implts_convertImageTypeToIndex( nImageType );
764 ImageList* pImageList = implts_getUserImageList(nIndex);
765
766 uno::Reference< XGraphic > xGraphic;
767 for ( sal_Int32 i = 0; i < aCommandURLSequence.getLength(); i++ )
768 {
769 // Check size and scale. If we don't have any graphics ignore it
770 if ( !implts_checkAndScaleGraphic( xGraphic, aGraphicsSequence[i], nIndex ))
771 continue;
772
773 sal_uInt16 nPos = pImageList->GetImagePos( aCommandURLSequence[i] );
774 if ( nPos == IMAGELIST_IMAGE_NOTFOUND(sal_uInt16(0xFFFF)) )
775 {
776 pImageList->AddImage(aCommandURLSequence[i], Image(xGraphic));
777 if ( !pInsertedImages )
778 pInsertedImages = new GraphicNameAccess();
779 pInsertedImages->addElement( aCommandURLSequence[i], xGraphic );
780 }
781 else
782 {
783 pImageList->ReplaceImage(aCommandURLSequence[i], Image(xGraphic));
784 if ( !pReplacedImages )
785 pReplacedImages = new GraphicNameAccess();
786 pReplacedImages->addElement( aCommandURLSequence[i], xGraphic );
787 }
788 }
789
790 if (( pInsertedImages != nullptr ) || ( pReplacedImages != nullptr ))
791 {
792 m_bModified = true;
793 m_bUserImageListModified[nIndex] = true;
794 }
795 }
796
797 uno::Reference< uno::XInterface > xOwner(m_pOwner);
798 // Notify listeners
799 if ( pInsertedImages != nullptr )
800 {
801 ConfigurationEvent aInsertEvent;
802 aInsertEvent.aInfo <<= nImageType;
803 aInsertEvent.Accessor <<= xOwner;
804 aInsertEvent.Source = xOwner;
805 aInsertEvent.ResourceURL = m_aResourceString;
806 aInsertEvent.Element <<= uno::Reference< XNameAccess >(
807 static_cast< OWeakObject *>( pInsertedImages ), UNO_QUERY );
808 implts_notifyContainerListener( aInsertEvent, NotifyOp_Insert );
809 }
810 if ( pReplacedImages != nullptr )
811 {
812 ConfigurationEvent aReplaceEvent;
813 aReplaceEvent.aInfo <<= nImageType;
814 aReplaceEvent.Accessor <<= xOwner;
815 aReplaceEvent.Source = xOwner;
816 aReplaceEvent.ResourceURL = m_aResourceString;
817 aReplaceEvent.ReplacedElement = Any();
818 aReplaceEvent.Element <<= uno::Reference< XNameAccess >(
819 static_cast< OWeakObject *>( pReplacedImages ), UNO_QUERY );
820 implts_notifyContainerListener( aReplaceEvent, NotifyOp_Replace );
821 }
822}
823
824void ImageManagerImpl::removeImages( ::sal_Int16 nImageType, const Sequence< OUString >& aCommandURLSequence )
825{
826 GraphicNameAccess* pRemovedImages( nullptr );
827 GraphicNameAccess* pReplacedImages( nullptr );
828
829 {
830 SolarMutexGuard g;
831
832 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
833 if ( m_bDisposed )
834 throw DisposedException();
835
836 if (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE ))
837 throw IllegalArgumentException();
838
839 if ( m_bReadOnly )
840 throw IllegalAccessException();
841
842 vcl::ImageType nIndex = implts_convertImageTypeToIndex( nImageType );
843 rtl::Reference< GlobalImageList > rGlobalImageList;
844 CmdImageList* pDefaultImageList = nullptr;
845 if ( m_bUseGlobal )
846 {
847 rGlobalImageList = implts_getGlobalImageList();
848 pDefaultImageList = implts_getDefaultImageList();
849 }
850 ImageList* pImageList = implts_getUserImageList(nIndex);
851 uno::Reference<XGraphic> xEmptyGraphic;
852
853 for ( const OUString& rURL : aCommandURLSequence )
854 {
855 sal_uInt16 nPos = pImageList->GetImagePos( rURL );
856 if ( nPos != IMAGELIST_IMAGE_NOTFOUND(sal_uInt16(0xFFFF)) )
857 {
858 sal_uInt16 nId = pImageList->GetImageId( nPos );
859 pImageList->RemoveImage( nId );
860
861 if ( m_bUseGlobal )
862 {
863 // Check, if we have an image in our module/global image list. If we find one =>
864 // this is a replace instead of a remove operation!
865 Image aNewImage = pDefaultImageList->getImageFromCommandURL( nIndex, rURL );
866 if ( !aNewImage )
867 aNewImage = rGlobalImageList->getImageFromCommandURL( nIndex, rURL );
868 if ( !aNewImage )
869 {
870 if ( !pRemovedImages )
871 pRemovedImages = new GraphicNameAccess();
872 pRemovedImages->addElement( rURL, xEmptyGraphic );
873 }
874 else
875 {
876 if ( !pReplacedImages )
877 pReplacedImages = new GraphicNameAccess();
878 pReplacedImages->addElement(rURL, GetXGraphic(aNewImage));
879 }
880 } // if ( m_bUseGlobal )
881 else
882 {
883 if ( !pRemovedImages )
884 pRemovedImages = new GraphicNameAccess();
885 pRemovedImages->addElement( rURL, xEmptyGraphic );
886 }
887 }
888 }
889
890 if (( pReplacedImages != nullptr ) || ( pRemovedImages != nullptr ))
891 {
892 m_bModified = true;
893 m_bUserImageListModified[nIndex] = true;
894 }
895 }
896
897 // Notify listeners
898 uno::Reference< uno::XInterface > xOwner(m_pOwner);
899 if ( pRemovedImages != nullptr )
900 {
901 ConfigurationEvent aRemoveEvent;
902 aRemoveEvent.aInfo <<= nImageType;
903 aRemoveEvent.Accessor <<= xOwner;
904 aRemoveEvent.Source = xOwner;
905 aRemoveEvent.ResourceURL = m_aResourceString;
906 aRemoveEvent.Element <<= uno::Reference< XNameAccess >(
907 static_cast< OWeakObject *>( pRemovedImages ), UNO_QUERY );
908 implts_notifyContainerListener( aRemoveEvent, NotifyOp_Remove );
909 }
910 if ( pReplacedImages != nullptr )
911 {
912 ConfigurationEvent aReplaceEvent;
913 aReplaceEvent.aInfo <<= nImageType;
914 aReplaceEvent.Accessor <<= xOwner;
915 aReplaceEvent.Source = xOwner;
916 aReplaceEvent.ResourceURL = m_aResourceString;
917 aReplaceEvent.ReplacedElement = Any();
918 aReplaceEvent.Element <<= uno::Reference< XNameAccess >(
919 static_cast< OWeakObject *>( pReplacedImages ), UNO_QUERY );
920 implts_notifyContainerListener( aReplaceEvent, NotifyOp_Replace );
921 }
922}
923
924void ImageManagerImpl::insertImages( ::sal_Int16 nImageType, const Sequence< OUString >& aCommandURLSequence, const Sequence< uno::Reference< XGraphic > >& aGraphicSequence )
925{
926 replaceImages(nImageType,aCommandURLSequence,aGraphicSequence);
927}
928
929// XUIConfigurationPersistence
930void ImageManagerImpl::reload()
931{
932 SolarMutexClearableGuard aGuard;
933
934 if ( m_bDisposed )
935 throw DisposedException();
936
937 CommandMap aOldUserCmdImageSet;
938 std::vector< OUString > aNewUserCmdImageSet;
939
940 if ( !m_bModified )
941 return;
942
943 for ( vcl::ImageType i : o3tl::enumrange<vcl::ImageType>() )
944 {
945 if ( !m_bDisposed && m_bUserImageListModified[i] )
946 {
947 std::vector< OUString > aOldUserCmdImageVector;
948 ImageList* pImageList = implts_getUserImageList(i);
949 pImageList->GetImageNames( aOldUserCmdImageVector );
950
951 // Fill hash map to speed up search afterwards
952 sal_uInt32 j( 0 );
953 const sal_uInt32 nOldCount = aOldUserCmdImageVector.size();
954 for ( j = 0; j < nOldCount; j++ )
955 aOldUserCmdImageSet.emplace( aOldUserCmdImageVector[j], false );
956
957 // Attention: This can make the old image list pointer invalid!
958 implts_loadUserImages( i, m_xUserImageStorage, m_xUserBitmapsStorage );
959 pImageList = implts_getUserImageList(i);
960 pImageList->GetImageNames( aNewUserCmdImageSet );
961
962 GraphicNameAccess* pInsertedImages( nullptr );
963 GraphicNameAccess* pReplacedImages( nullptr );
964 GraphicNameAccess* pRemovedImages( nullptr );
965
966 for (auto const& newUserCmdImage : aNewUserCmdImageSet)
967 {
968 CommandMap::iterator pIter = aOldUserCmdImageSet.find(newUserCmdImage);
969 if ( pIter != aOldUserCmdImageSet.end() )
970 {
971 pIter->second = true; // mark entry as replaced
972 if ( !pReplacedImages )
973 pReplacedImages = new GraphicNameAccess();
974 pReplacedImages->addElement( newUserCmdImage,
975 GetXGraphic(pImageList->GetImage(newUserCmdImage)) );
976 }
977 else
978 {
979 if ( !pInsertedImages )
980 pInsertedImages = new GraphicNameAccess();
981 pInsertedImages->addElement( newUserCmdImage,
982 GetXGraphic(pImageList->GetImage(newUserCmdImage)) );
983 }
984 }
985
986 // Search map for unmarked entries => they have been removed from the user list
987 // through this reload operation.
988 // We have to search the module and global image list!
989 rtl::Reference< GlobalImageList > rGlobalImageList;
990 CmdImageList* pDefaultImageList = nullptr;
991 if ( m_bUseGlobal )
992 {
993 rGlobalImageList = implts_getGlobalImageList();
994 pDefaultImageList = implts_getDefaultImageList();
995 }
996 uno::Reference<XGraphic> xEmptyGraphic;
997 for (auto const& oldUserCmdImage : aOldUserCmdImageSet)
998 {
999 if ( !oldUserCmdImage.second )
1000 {
1001 if ( m_bUseGlobal )
1002 {
1003 Image aImage = pDefaultImageList->getImageFromCommandURL( i, oldUserCmdImage.first );
1004 if ( !aImage )
1005 aImage = rGlobalImageList->getImageFromCommandURL( i, oldUserCmdImage.first );
1006
1007 if ( !aImage )
1008 {
1009 // No image in the module/global image list => remove user image
1010 if ( !pRemovedImages )
1011 pRemovedImages = new GraphicNameAccess();
1012 pRemovedImages->addElement( oldUserCmdImage.first, xEmptyGraphic );
1013 }
1014 else
1015 {
1016 // Image has been found in the module/global image list => replace user image
1017 if ( !pReplacedImages )
1018 pReplacedImages = new GraphicNameAccess();
1019 pReplacedImages->addElement(oldUserCmdImage.first, GetXGraphic(aImage));
1020 }
1021 } // if ( m_bUseGlobal )
1022 else
1023 {
1024 // No image in the user image list => remove user image
1025 if ( !pRemovedImages )
1026 pRemovedImages = new GraphicNameAccess();
1027 pRemovedImages->addElement( oldUserCmdImage.first, xEmptyGraphic );
1028 }
1029 }
1030 }
1031
1032 aGuard.clear();
1033
1034 // Now notify our listeners. Unlock mutex to prevent deadlocks
1035 uno::Reference< uno::XInterface > xOwner(m_pOwner);
1036 if ( pInsertedImages != nullptr )
1037 {
1038 ConfigurationEvent aInsertEvent;
1039 aInsertEvent.aInfo <<=static_cast<sal_uInt16>(i);
1040 aInsertEvent.Accessor <<= xOwner;
1041 aInsertEvent.Source = xOwner;
1042 aInsertEvent.ResourceURL = m_aResourceString;
1043 aInsertEvent.Element <<= uno::Reference< XNameAccess >(
1044 static_cast< OWeakObject *>( pInsertedImages ), UNO_QUERY );
1045 implts_notifyContainerListener( aInsertEvent, NotifyOp_Insert );
1046 }
1047 if ( pReplacedImages != nullptr )
1048 {
1049 ConfigurationEvent aReplaceEvent;
1050 aReplaceEvent.aInfo <<= static_cast<sal_uInt16>(i);
1051 aReplaceEvent.Accessor <<= xOwner;
1052 aReplaceEvent.Source = xOwner;
1053 aReplaceEvent.ResourceURL = m_aResourceString;
1054 aReplaceEvent.ReplacedElement = Any();
1055 aReplaceEvent.Element <<= uno::Reference< XNameAccess >(
1056 static_cast< OWeakObject *>( pReplacedImages ), UNO_QUERY );
1057 implts_notifyContainerListener( aReplaceEvent, NotifyOp_Replace );
1058 }
1059 if ( pRemovedImages != nullptr )
1060 {
1061 ConfigurationEvent aRemoveEvent;
1062 aRemoveEvent.aInfo <<= static_cast<sal_uInt16>(i);
1063 aRemoveEvent.Accessor <<= xOwner;
1064 aRemoveEvent.Source = xOwner;
1065 aRemoveEvent.ResourceURL = m_aResourceString;
1066 aRemoveEvent.Element <<= uno::Reference< XNameAccess >(
1067 static_cast< OWeakObject *>( pRemovedImages ), UNO_QUERY );
1068 implts_notifyContainerListener( aRemoveEvent, NotifyOp_Remove );
1069 }
1070
1071 aGuard.clear();
1072 }
1073 }
1074}
1075
1076void ImageManagerImpl::store()
1077{
1078 SolarMutexGuard g;
1079
1080 if ( m_bDisposed )
1081 throw DisposedException();
1082
1083 if ( !m_bModified )
1084 return;
1085
1086 bool bWritten( false );
1087 for ( vcl::ImageType i : o3tl::enumrange<vcl::ImageType>() )
1088 {
1089 bool bSuccess = implts_storeUserImages(i, m_xUserImageStorage, m_xUserBitmapsStorage );
1090 if ( bSuccess )
1091 bWritten = true;
1092 m_bUserImageListModified[i] = false;
1093 }
1094
1095 if ( bWritten &&
1096 m_xUserConfigStorage.is() )
1097 {
1098 uno::Reference< XTransactedObject > xUserConfigStorageCommit( m_xUserConfigStorage, UNO_QUERY );
1099 if ( xUserConfigStorageCommit.is() )
1100 xUserConfigStorageCommit->commit();
1101 if ( m_xUserRootCommit.is() )
1102 m_xUserRootCommit->commit();
1103 }
1104
1105 m_bModified = false;
1106}
1107
1108void ImageManagerImpl::storeToStorage( const uno::Reference< XStorage >& Storage )
1109{
1110 SolarMutexGuard g;
1111
1112 if ( m_bDisposed )
1113 throw DisposedException();
1114
1115 if ( !(m_bModified && Storage.is()) )
1116 return;
1117
1118 long nModes = ElementModes::READWRITE;
1119
1120 uno::Reference< XStorage > xUserImageStorage = Storage->openStorageElement( IMAGE_FOLDER,
1121 nModes );
1122 if ( !xUserImageStorage.is() )
1123 return;
1124
1125 uno::Reference< XStorage > xUserBitmapsStorage = xUserImageStorage->openStorageElement( BITMAPS_FOLDER,
1126 nModes );
1127 for ( vcl::ImageType i : o3tl::enumrange<vcl::ImageType>() )
1128 {
1129 implts_getUserImageList(i);
1130 implts_storeUserImages( i, xUserImageStorage, xUserBitmapsStorage );
1131 }
1132
1133 uno::Reference< XTransactedObject > xTransaction( Storage, UNO_QUERY );
1134 if ( xTransaction.is() )
1135 xTransaction->commit();
1136}
1137
1138bool ImageManagerImpl::isModified() const
1139{
1140 SolarMutexGuard g;
1141 return m_bModified;
1142}
1143
1144bool ImageManagerImpl::isReadOnly() const
1145{
1146 SolarMutexGuard g;
1147 return m_bReadOnly;
1148}
1149// XUIConfiguration
1150void ImageManagerImpl::addConfigurationListener( const uno::Reference< css::ui::XUIConfigurationListener >& xListener )
1151{
1152 {
1153 SolarMutexGuard g;
1154
1155 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1156 if ( m_bDisposed )
1157 throw DisposedException();
1158 }
1159
1160 m_aListenerContainer.addInterface( cppu::UnoType<XUIConfigurationListener>::get(), xListener );
1161}
1162
1163void ImageManagerImpl::removeConfigurationListener( const uno::Reference< css::ui::XUIConfigurationListener >& xListener )
1164{
1165 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1166 m_aListenerContainer.removeInterface( cppu::UnoType<XUIConfigurationListener>::get(), xListener );
1167}
1168
1169void ImageManagerImpl::implts_notifyContainerListener( const ConfigurationEvent& aEvent, NotifyOp eOp )
1170{
1171 ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer(
1172 cppu::UnoType<css::ui::XUIConfigurationListener>::get());
1173 if ( pContainer == nullptr )
1174 return;
1175
1176 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
1177 while ( pIterator.hasMoreElements() )
1178 {
1179 try
1180 {
1181 switch ( eOp )
1182 {
1183 case NotifyOp_Replace:
1184 static_cast< css::ui::XUIConfigurationListener*>(pIterator.next())->elementReplaced( aEvent );
1185 break;
1186 case NotifyOp_Insert:
1187 static_cast< css::ui::XUIConfigurationListener*>(pIterator.next())->elementInserted( aEvent );
1188 break;
1189 case NotifyOp_Remove:
1190 static_cast< css::ui::XUIConfigurationListener*>(pIterator.next())->elementRemoved( aEvent );
1191 break;
1192 }
1193 }
1194 catch( const css::uno::RuntimeException& )
1195 {
1196 pIterator.remove();
1197 }
1198 }
1199}
1200void ImageManagerImpl::clear()
1201{
1202 SolarMutexGuard g;
1203
1204 for (auto & n : m_pUserImageList)
1205 {
1206 n.reset();
1207 }
1208}
1209} // namespace framework
1210
1211/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/image.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_IMAGE_HXX
21#define INCLUDED_VCL_IMAGE_HXX
22
23#include <vcl/dllapi.h>
24#include <tools/gen.hxx>
25#include <vcl/bitmapex.hxx>
26#include <vcl/outdev.hxx>
27
28#include <memory>
29
30class ImplImage;
31
32namespace com::sun::star::graphic { class XGraphic; }
33namespace com::sun::star::uno { template <class interface_type> class Reference; }
34
35#define IMAGELIST_IMAGE_NOTFOUND(sal_uInt16(0xFFFF)) (sal_uInt16(0xFFFF))
36
37enum class StockImage { Yes };
38
39class SAL_WARN_UNUSED__attribute__((warn_unused)) VCL_DLLPUBLIC__attribute__ ((visibility("default"))) Image
40{
41 friend class ::OutputDevice;
42public:
43 Image();
44 explicit Image(BitmapEx const & rBitmapEx);
45 explicit Image(css::uno::Reference<css::graphic::XGraphic> const & rxGraphic);
46 explicit Image(OUString const & rPNGFileUrl);
47 explicit Image(StockImage, OUString const & rPNGFilePath);
48
49 Size GetSizePixel() const;
50 BitmapEx GetBitmapEx() const;
51
52 bool operator!() const
53 {
54 return !mpImplData;
15
Calling '__shared_ptr::operator bool'
19
Returning from '__shared_ptr::operator bool'
20
Returning the value 1, which participates in a condition later
55 }
56 bool operator==(const Image& rImage) const;
57 bool operator!=(const Image& rImage) const
58 {
59 return !(Image::operator==(rImage));
60 }
61
62 OUString GetStock() const;
63
64 void Draw(OutputDevice* pOutDev, const Point& rPos, DrawImageFlags nStyle, const Size* pSize = nullptr);
65
66private:
67
68 std::shared_ptr<ImplImage> mpImplData;
69
70 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) void ImplInit(BitmapEx const & rBmpEx);
71};
72
73#endif // INCLUDED_VCL_IMAGE_HXX
74
75/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/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(),
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)...);
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; }
16
Assuming field '_M_ptr' is equal to null
17
'?' condition is true
18
Returning zero, which participates in a condition later
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)...)
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