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
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
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 | |
50 | using ::com::sun::star::uno::Sequence; |
51 | using ::com::sun::star::uno::XInterface; |
52 | using ::com::sun::star::uno::RuntimeException; |
53 | using ::com::sun::star::uno::UNO_QUERY; |
54 | using ::com::sun::star::uno::Any; |
55 | using ::com::sun::star::graphic::XGraphic; |
56 | using namespace ::com::sun::star; |
57 | using namespace ::com::sun::star::io; |
58 | using namespace ::com::sun::star::embed; |
59 | using namespace ::com::sun::star::lang; |
60 | using namespace ::com::sun::star::container; |
61 | using namespace ::com::sun::star::beans; |
62 | using namespace ::com::sun::star::ui; |
63 | using namespace ::cppu; |
64 | |
65 | const sal_Int16 MAX_IMAGETYPE_VALUE = css::ui::ImageType::SIZE_32; |
66 | |
67 | const char IMAGE_FOLDER[] = "images"; |
68 | const char BITMAPS_FOLDER[] = "Bitmaps"; |
69 | |
70 | const o3tl::enumarray<vcl::ImageType, const char*> IMAGELIST_XML_FILE = |
71 | { |
72 | "sc_imagelist.xml", |
73 | "lc_imagelist.xml", |
74 | "xc_imagelist.xml" |
75 | }; |
76 | |
77 | const o3tl::enumarray<vcl::ImageType, const char*> BITMAP_FILE_NAMES = |
78 | { |
79 | "sc_userimages.png", |
80 | "lc_userimages.png", |
81 | "xc_userimages.png" |
82 | }; |
83 | |
84 | namespace framework |
85 | { |
86 | |
87 | static GlobalImageList* pGlobalImageList = nullptr; |
88 | |
89 | namespace |
90 | { |
91 | class theGlobalImageListMutex |
92 | : public rtl::Static<osl::Mutex, theGlobalImageListMutex> {}; |
93 | } |
94 | |
95 | static osl::Mutex& getGlobalImageListMutex() |
96 | { |
97 | return theGlobalImageListMutex::get(); |
98 | } |
99 | |
100 | static 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 | |
110 | CmdImageList::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 | |
117 | CmdImageList::~CmdImageList() |
118 | { |
119 | } |
120 | |
121 | void CmdImageList::initialize() |
122 | { |
123 | if (m_bInitialized) |
124 | return; |
125 | |
126 | const OUString aCommandImageList(UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDIMAGELIST); |
127 | |
128 | Sequence<OUString> aCommandImageSeq; |
129 | uno::Reference<XNameAccess> xCommandDesc = frame::theUICommandDescription::get(m_xContext); |
130 | |
131 | if (!m_aModuleIdentifier.isEmpty()) |
132 | { |
133 | |
134 | |
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 | |
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 | |
168 | Image CmdImageList::getImageFromCommandURL(vcl::ImageType nImageType, const OUString& rCommandURL) |
169 | { |
170 | initialize(); |
171 | return m_aResolver.getImageFromCommandURL(nImageType, rCommandURL); |
172 | } |
173 | |
174 | bool CmdImageList::hasImage(vcl::ImageType , const OUString& rCommandURL) |
175 | { |
176 | initialize(); |
177 | return m_aResolver.hasImage(rCommandURL); |
178 | } |
179 | |
180 | std::vector<OUString>& CmdImageList::getImageCommandNames() |
181 | { |
182 | return m_aResolver.getCommandNames(); |
183 | } |
184 | |
185 | GlobalImageList::GlobalImageList( const uno::Reference< uno::XComponentContext >& rxContext ) : |
186 | CmdImageList( rxContext, OUString() ) |
187 | { |
188 | } |
189 | |
190 | GlobalImageList::~GlobalImageList() |
191 | { |
192 | osl::MutexGuard guard( getGlobalImageListMutex() ); |
193 | |
194 | pGlobalImageList = nullptr; |
195 | } |
196 | |
197 | Image GlobalImageList::getImageFromCommandURL( vcl::ImageType nImageType, const OUString& rCommandURL ) |
198 | { |
199 | osl::MutexGuard guard( getGlobalImageListMutex() ); |
200 | return CmdImageList::getImageFromCommandURL( nImageType, rCommandURL ); |
201 | } |
202 | |
203 | bool 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 | |
215 | static 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 | |
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 | |
243 | static 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 | |
253 | ImageList* ImageManagerImpl::implts_getUserImageList( vcl::ImageType nImageType ) |
254 | { |
255 | SolarMutexGuard g; |
256 | if ( !m_pUserImageList[nImageType] ) |
| |
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 | |
262 | void ImageManagerImpl::implts_initialize() |
263 | { |
264 | |
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 | |
297 | void 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 | |
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 | |
366 | m_pUserImageList[nImageType].reset(new ImageList); |
367 | } |
368 | |
369 | bool 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 | |
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 | |
418 | xTransaction.set( xUserImageStorage, UNO_QUERY ); |
419 | if ( xTransaction.is() ) |
420 | xTransaction->commit(); |
421 | } |
422 | |
423 | return true; |
424 | } |
425 | else |
426 | { |
427 | |
428 | |
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 | |
448 | xTransaction.set( xUserImageStorage, UNO_QUERY ); |
449 | if ( xTransaction.is() ) |
450 | xTransaction->commit(); |
451 | |
452 | |
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 | |
464 | const 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 | |
473 | CmdImageList* 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 | |
483 | ImageManagerImpl::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 | |
501 | ImageManagerImpl::~ImageManagerImpl() |
502 | { |
503 | clear(); |
504 | } |
505 | |
506 | void 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 | |
521 | for (auto& n : m_pUserImageList) |
522 | { |
523 | n.reset(); |
524 | } |
525 | m_pDefaultImageList.reset(); |
526 | } |
527 | |
528 | } |
529 | void ImageManagerImpl::addEventListener( const uno::Reference< XEventListener >& xListener ) |
530 | { |
531 | { |
532 | SolarMutexGuard g; |
533 | |
534 | |
535 | if ( m_bDisposed ) |
536 | throw DisposedException(); |
537 | } |
538 | |
539 | m_aListenerContainer.addInterface( cppu::UnoType<XEventListener>::get(), xListener ); |
540 | } |
541 | |
542 | void ImageManagerImpl::removeEventListener( const uno::Reference< XEventListener >& xListener ) |
543 | { |
544 | |
545 | m_aListenerContainer.removeInterface( cppu::UnoType<XEventListener>::get(), xListener ); |
546 | } |
547 | |
548 | |
549 | void 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 | |
593 | void ImageManagerImpl::reset() |
594 | { |
595 | SolarMutexGuard g; |
596 | |
597 | |
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 | |
612 | removeImages( sal_Int16( i ), aRemoveList ); |
613 | m_bUserImageListModified[i] = true; |
614 | } |
615 | |
616 | m_bModified = true; |
617 | } |
618 | |
619 | Sequence< OUString > ImageManagerImpl::getAllImageNames( ::sal_Int16 nImageType ) |
620 | { |
621 | SolarMutexGuard g; |
622 | |
623 | |
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 | |
657 | bool ImageManagerImpl::hasImage( ::sal_Int16 nImageType, const OUString& aCommandURL ) |
658 | { |
659 | SolarMutexGuard g; |
660 | |
661 | |
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 | |
678 | ImageList* pImageList = implts_getUserImageList(nIndex); |
679 | if ( pImageList ) |
680 | return ( pImageList->GetImagePos( aCommandURL ) != IMAGELIST_IMAGE_NOTFOUND ); |
681 | } |
682 | } |
683 | |
684 | return false; |
685 | } |
686 | |
687 | namespace |
688 | { |
689 | css::uno::Reference< css::graphic::XGraphic > GetXGraphic(const Image &rImage) |
690 | { |
691 | return Graphic(rImage).GetXGraphic(); |
692 | } |
693 | } |
694 | |
695 | Sequence< uno::Reference< XGraphic > > ImageManagerImpl::getImages( |
696 | ::sal_Int16 nImageType, |
697 | const Sequence< OUString >& aCommandURLSequence ) |
698 | { |
699 | SolarMutexGuard g; |
700 | |
701 | |
702 | if ( m_bDisposed ) |
| 1 | Assuming field 'm_bDisposed' is false | |
|
| |
703 | throw DisposedException(); |
704 | |
705 | if (( nImageType < 0 ) || ( nImageType > MAX_IMAGETYPE_VALUE )) |
| 3 | | Assuming 'nImageType' is >= 0 | |
|
| 4 | | Assuming 'nImageType' is <= 'MAX_IMAGETYPE_VALUE' | |
|
| |
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 | |
|
| |
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 | |
721 | |
722 | |
723 | |
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 | |
|
| |
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 | |
741 | void 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 | |
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 | |
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 ) |
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 | |
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 | |
824 | void 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 | |
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 ) |
857 | { |
858 | sal_uInt16 nId = pImageList->GetImageId( nPos ); |
859 | pImageList->RemoveImage( nId ); |
860 | |
861 | if ( m_bUseGlobal ) |
862 | { |
863 | |
864 | |
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 | } |
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 | |
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 | |
924 | void ImageManagerImpl::insertImages( ::sal_Int16 nImageType, const Sequence< OUString >& aCommandURLSequence, const Sequence< uno::Reference< XGraphic > >& aGraphicSequence ) |
925 | { |
926 | replaceImages(nImageType,aCommandURLSequence,aGraphicSequence); |
927 | } |
928 | |
929 | |
930 | void 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 | |
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 | |
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; |
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 | |
987 | |
988 | |
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 | |
1010 | if ( !pRemovedImages ) |
1011 | pRemovedImages = new GraphicNameAccess(); |
1012 | pRemovedImages->addElement( oldUserCmdImage.first, xEmptyGraphic ); |
1013 | } |
1014 | else |
1015 | { |
1016 | |
1017 | if ( !pReplacedImages ) |
1018 | pReplacedImages = new GraphicNameAccess(); |
1019 | pReplacedImages->addElement(oldUserCmdImage.first, GetXGraphic(aImage)); |
1020 | } |
1021 | } |
1022 | else |
1023 | { |
1024 | |
1025 | if ( !pRemovedImages ) |
1026 | pRemovedImages = new GraphicNameAccess(); |
1027 | pRemovedImages->addElement( oldUserCmdImage.first, xEmptyGraphic ); |
1028 | } |
1029 | } |
1030 | } |
1031 | |
1032 | aGuard.clear(); |
1033 | |
1034 | |
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 | |
1076 | void 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 | |
1108 | void 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 | |
1138 | bool ImageManagerImpl::isModified() const |
1139 | { |
1140 | SolarMutexGuard g; |
1141 | return m_bModified; |
1142 | } |
1143 | |
1144 | bool ImageManagerImpl::isReadOnly() const |
1145 | { |
1146 | SolarMutexGuard g; |
1147 | return m_bReadOnly; |
1148 | } |
1149 | |
1150 | void ImageManagerImpl::addConfigurationListener( const uno::Reference< css::ui::XUIConfigurationListener >& xListener ) |
1151 | { |
1152 | { |
1153 | SolarMutexGuard g; |
1154 | |
1155 | |
1156 | if ( m_bDisposed ) |
1157 | throw DisposedException(); |
1158 | } |
1159 | |
1160 | m_aListenerContainer.addInterface( cppu::UnoType<XUIConfigurationListener>::get(), xListener ); |
1161 | } |
1162 | |
1163 | void ImageManagerImpl::removeConfigurationListener( const uno::Reference< css::ui::XUIConfigurationListener >& xListener ) |
1164 | { |
1165 | |
1166 | m_aListenerContainer.removeInterface( cppu::UnoType<XUIConfigurationListener>::get(), xListener ); |
1167 | } |
1168 | |
1169 | void 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 | } |
1200 | void ImageManagerImpl::clear() |
1201 | { |
1202 | SolarMutexGuard g; |
1203 | |
1204 | for (auto & n : m_pUserImageList) |
1205 | { |
1206 | n.reset(); |
1207 | } |
1208 | } |
1209 | } |
1210 | |
1211 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | #ifndef _SHARED_PTR_BASE_H |
50 | #define _SHARED_PTR_BASE_H 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 __cplusplus > 201703L |
58 | # include <compare> |
59 | #endif |
60 | |
61 | namespace std _GLIBCXX_VISIBILITY(default) |
62 | { |
63 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
64 | |
65 | #if _GLIBCXX_USE_DEPRECATED |
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 | |
74 | |
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 | |
85 | inline void |
86 | __throw_bad_weak_ptr() |
87 | { _GLIBCXX_THROW_OR_ABORT(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 | |
96 | template<_Lock_policy _Lp> |
97 | class _Mutex_base |
98 | { |
99 | protected: |
100 | |
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 | |
110 | |
111 | |
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 | |
128 | |
129 | virtual void |
130 | _M_dispose() noexcept = 0; |
131 | |
132 | |
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 | |
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 | |
160 | |
161 | |
162 | |
163 | if (_Mutex_base<_Lp>::_S_need_barriers) |
164 | { |
165 | __atomic_thread_fence (__ATOMIC_ACQ_REL); |
166 | } |
167 | |
168 | |
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 | |
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 | |
194 | |
195 | __atomic_thread_fence (__ATOMIC_ACQ_REL); |
196 | } |
197 | _M_destroy(); |
198 | } |
199 | } |
200 | |
201 | long |
202 | _M_get_use_count() const noexcept |
203 | { |
204 | |
205 | |
206 | return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED); |
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; |
214 | _Atomic_word _M_weak_count; |
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 | |
246 | _Atomic_word __count = _M_get_use_count(); |
247 | do |
248 | { |
249 | if (__count == 0) |
250 | __throw_bad_weak_ptr(); |
251 | |
252 | |
253 | } |
254 | while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1, |
255 | true, __ATOMIC_ACQ_REL, |
256 | __ATOMIC_RELAXED)); |
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 | |
290 | _Atomic_word __count = _M_get_use_count(); |
291 | do |
292 | { |
293 | if (__count == 0) |
294 | return false; |
295 | |
296 | |
297 | } |
298 | while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1, |
299 | true, __ATOMIC_ACQ_REL, |
300 | __ATOMIC_RELAXED)); |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
463 | _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept |
464 | : _M_impl(__p, std::move(__d), _Alloc()) { } |
465 | |
466 | |
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_rtti |
488 | |
489 | |
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 | |
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) |
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 | |
545 | template<typename... _Args> |
546 | _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args) |
547 | : _M_impl(__a) |
548 | { |
549 | |
550 | |
551 | allocator_traits<_Alloc>::construct(__a, _M_ptr(), |
552 | std::forward<_Args>(__args)...); |
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 | |
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>; |
574 | |
575 | |
576 | |
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 | |
582 | |
583 | |
584 | |
585 | if (&__ti == &_Sp_make_shared_tag::_S_ti() |
586 | || |
587 | #if __cpp_rtti |
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 | |
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 | __try |
627 | { |
628 | _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p); |
629 | } |
630 | __catch(...) |
631 | { |
632 | delete __p; |
633 | __throw_exception_again; |
634 | } |
635 | } |
636 | |
637 | template<typename _Ptr> |
638 | __shared_count(_Ptr __p, false_type) |
639 | : __shared_count(__p) |
640 | { } |
641 | |
642 | template<typename _Ptr> |
643 | __shared_count(_Ptr __p, 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 | __try |
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(...) |
668 | { |
669 | __d(__p); |
670 | __throw_exception_again; |
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_DEPRECATED |
690 | #pragma GCC diagnostic push |
691 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
692 | |
693 | template<typename _Tp> |
694 | explicit |
695 | __shared_count(std::auto_ptr<_Tp>&& __r); |
696 | #pragma GCC diagnostic pop |
697 | #endif |
698 | |
699 | |
700 | template<typename _Tp, typename _Del> |
701 | explicit |
702 | __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0) |
703 | { |
704 | |
705 | |
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()); |
721 | _M_pi = __mem; |
722 | } |
723 | |
724 | |
725 | explicit __shared_count(const __weak_count<_Lp>& __r); |
726 | |
727 | |
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 | |
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 | |
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 | |
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 | |
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_arrays 201611L |
919 | |
920 | |
921 | |
922 | |
923 | |
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 | |
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 | |
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 | |
977 | template<typename _Tp, typename _Yp> |
978 | struct __sp_is_constructible; |
979 | |
980 | |
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 | |
987 | template<typename _Up, typename _Yp> |
988 | struct __sp_is_constructible<_Up[], _Yp> |
989 | : __sp_is_constructible_arr<_Up, _Yp>::type |
990 | { }; |
991 | |
992 | |
993 | template<typename _Tp, typename _Yp> |
994 | struct __sp_is_constructible |
995 | : is_convertible<_Yp*, _Tp*>::type |
996 | { }; |
997 | |
998 | |
999 | |
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 | |
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 | |
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 __cplusplus <= 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 | |
1091 | template<typename _Yp> |
1092 | using _SafeConv |
1093 | = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type; |
1094 | |
1095 | |
1096 | template<typename _Yp, typename _Res = void> |
1097 | using _Compatible = typename |
1098 | enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type; |
1099 | |
1100 | |
1101 | template<typename _Yp> |
1102 | using _Assignable = _Compatible<_Yp, __shared_ptr&>; |
1103 | |
1104 | |
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 | |
1112 | template<typename _Yp, typename _Del> |
1113 | using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>; |
1114 | |
1115 | public: |
1116 | |
1117 | #if __cplusplus > 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 | |
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) |
1169 | { } |
1170 | |
1171 | |
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) |
1208 | { |
1209 | |
1210 | |
1211 | _M_ptr = __r._M_ptr; |
1212 | } |
1213 | |
1214 | |
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 __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED |
1226 | protected: |
1227 | |
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_DEPRECATED |
1244 | #pragma GCC diagnostic push |
1245 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
1246 | |
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; |
1260 | return *this; |
1261 | } |
1262 | |
1263 | #if _GLIBCXX_USE_DEPRECATED |
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) |
1306 | { |
1307 | |
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 | |
1323 | element_type* |
1324 | get() const noexcept |
1325 | { return _M_ptr; } |
1326 | |
1327 | |
1328 | explicit operator bool() const |
1329 | { return _M_ptr == 0 ? false : true; } |
| 16 | | Assuming field '_M_ptr' is equal to null | |
|
| |
| 18 | | Returning zero, which participates in a condition later | |
|
1330 | |
1331 | |
1332 | bool |
1333 | unique() const noexcept |
1334 | { return _M_refcount._M_unique(); } |
1335 | |
1336 | |
1337 | long |
1338 | use_count() const noexcept |
1339 | { return _M_refcount._M_get_use_count(); } |
1340 | |
1341 | |
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 | |
1350 | |
1351 | |
1352 | |
1353 | |
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 | |
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 | |
1380 | |
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 | |
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>> { }; |
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; |
1432 | __shared_count<_Lp> _M_refcount; |
1433 | }; |
1434 | |
1435 | |
1436 | |
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 | |
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 | |
1567 | |
1568 | |
1569 | |
1570 | |
1571 | |
1572 | |
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 | |
1582 | |
1583 | |
1584 | |
1585 | |
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 | |
1595 | |
1596 | |
1597 | |
1598 | |
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 __cplusplus > 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 | |
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 | |
1642 | |
1643 | |
1644 | |
1645 | |
1646 | |
1647 | |
1648 | |
1649 | |
1650 | |
1651 | |
1652 | |
1653 | |
1654 | |
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 | |
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; |
1765 | __weak_count<_Lp> _M_refcount; |
1766 | }; |
1767 | |
1768 | |
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 __cplusplus > 201402L || !defined(__STRICT_ANSI__) // 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 | |
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 | } |
1897 | |
1898 | #endif // _SHARED_PTR_BASE_H |