1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <comphelper/interfacecontainer2.hxx>
23 #include <osl/diagnose.h>
24 #include <osl/mutex.hxx>
28 #include <com/sun/star/lang/XEventListener.hpp>
32 using namespace com::sun::star::uno
;
33 using namespace com::sun::star::lang
;
38 OInterfaceIteratorHelper2::OInterfaceIteratorHelper2( OInterfaceContainerHelper2
& rCont_
)
40 bIsList( rCont_
.bIsList
)
42 MutexGuard
aGuard( rCont
.rMutex
);
44 // worst case, two iterators at the same time
45 rCont
.copyAndResetInUse();
50 nRemain
= aData
.pAsVector
->size();
52 else if( aData
.pAsInterface
)
54 aData
.pAsInterface
->acquire();
61 OInterfaceIteratorHelper2::~OInterfaceIteratorHelper2()
65 MutexGuard
aGuard( rCont
.rMutex
);
66 // bResetInUse protect the iterator against recursion
67 bShared
= aData
.pAsVector
== rCont
.aData
.pAsVector
&& rCont
.bIsList
;
70 OSL_ENSURE( rCont
.bInUse
, "OInterfaceContainerHelper2 must be in use" );
78 // Sequence owned by the iterator
79 delete aData
.pAsVector
;
80 else if( aData
.pAsInterface
)
81 // Interface is acquired by the iterator
82 aData
.pAsInterface
->release();
86 XInterface
* OInterfaceIteratorHelper2::next()
92 return (*aData
.pAsVector
)[nRemain
].get();
93 else if( aData
.pAsInterface
)
94 return aData
.pAsInterface
;
100 void OInterfaceIteratorHelper2::remove()
104 OSL_ASSERT( nRemain
>= 0 &&
105 nRemain
< static_cast<sal_Int32
>(aData
.pAsVector
->size()) );
106 rCont
.removeInterface( (*aData
.pAsVector
)[nRemain
] );
110 OSL_ASSERT( 0 == nRemain
);
111 rCont
.removeInterface( aData
.pAsInterface
);
115 OInterfaceContainerHelper2::OInterfaceContainerHelper2( Mutex
& rMutex_
)
122 OInterfaceContainerHelper2::~OInterfaceContainerHelper2()
124 OSL_ENSURE( !bInUse
, "~OInterfaceContainerHelper2 but is in use" );
126 delete aData
.pAsVector
;
127 else if( aData
.pAsInterface
)
128 aData
.pAsInterface
->release();
131 sal_Int32
OInterfaceContainerHelper2::getLength() const
133 MutexGuard
aGuard( rMutex
);
135 return aData
.pAsVector
->size();
136 else if( aData
.pAsInterface
)
141 std::vector
< Reference
<XInterface
> > OInterfaceContainerHelper2::getElements() const
143 std::vector
< Reference
<XInterface
> > rVec
;
144 MutexGuard
aGuard( rMutex
);
146 rVec
= *aData
.pAsVector
;
147 else if( aData
.pAsInterface
)
149 rVec
.emplace_back( aData
.pAsInterface
);
154 void OInterfaceContainerHelper2::copyAndResetInUse()
156 OSL_ENSURE( bInUse
, "OInterfaceContainerHelper2 not in use" );
159 // this should be the worst case. If an iterator is active
160 // and a new Listener is added.
162 aData
.pAsVector
= new std::vector
< Reference
< XInterface
> >( *aData
.pAsVector
);
163 else if( aData
.pAsInterface
)
164 aData
.pAsInterface
->acquire();
170 sal_Int32
OInterfaceContainerHelper2::addInterface( const Reference
<XInterface
> & rListener
)
172 OSL_ASSERT( rListener
.is() );
173 MutexGuard
aGuard( rMutex
);
179 aData
.pAsVector
->push_back( rListener
);
180 return aData
.pAsVector
->size();
182 else if( aData
.pAsInterface
)
184 std::vector
< Reference
< XInterface
> > * pVec
= new std::vector
< Reference
< XInterface
> >( 2 );
185 (*pVec
)[0] = aData
.pAsInterface
;
186 (*pVec
)[1] = rListener
;
187 aData
.pAsInterface
->release();
188 aData
.pAsVector
= pVec
;
194 aData
.pAsInterface
= rListener
.get();
196 rListener
->acquire();
201 sal_Int32
OInterfaceContainerHelper2::removeInterface( const Reference
<XInterface
> & rListener
)
203 OSL_ASSERT( rListener
.is() );
204 MutexGuard
aGuard( rMutex
);
210 // It is not valid to compare the pointer directly, but it's faster.
211 auto it
= std::find_if(aData
.pAsVector
->begin(), aData
.pAsVector
->end(),
212 [&rListener
](const css::uno::Reference
<css::uno::XInterface
>& rItem
) {
213 return rItem
.get() == rListener
.get(); });
215 // interface not found, use the correct compare method
216 if (it
== aData
.pAsVector
->end())
217 it
= std::find(aData
.pAsVector
->begin(), aData
.pAsVector
->end(), rListener
);
219 if (it
!= aData
.pAsVector
->end())
220 aData
.pAsVector
->erase(it
);
222 if( aData
.pAsVector
->size() == 1 )
224 XInterface
* p
= (*aData
.pAsVector
)[0].get();
226 delete aData
.pAsVector
;
227 aData
.pAsInterface
= p
;
232 return aData
.pAsVector
->size();
234 else if( aData
.pAsInterface
&& Reference
<XInterface
>( aData
.pAsInterface
) == rListener
)
236 aData
.pAsInterface
->release();
237 aData
.pAsInterface
= nullptr;
239 return aData
.pAsInterface
? 1 : 0;
242 void OInterfaceContainerHelper2::disposeAndClear( const EventObject
& rEvt
)
244 ClearableMutexGuard
aGuard( rMutex
);
245 OInterfaceIteratorHelper2
aIt( *this );
246 // Release container, in case new entries come while disposing
247 OSL_ENSURE( !bIsList
|| bInUse
, "OInterfaceContainerHelper2 not in use" );
248 if( !bIsList
&& aData
.pAsInterface
)
249 aData
.pAsInterface
->release();
250 // set the member to null, use the iterator to delete the values
251 aData
.pAsInterface
= nullptr;
255 while( aIt
.hasMoreElements() )
259 Reference
<XEventListener
> xLst( aIt
.next(), UNO_QUERY
);
261 xLst
->disposing( rEvt
);
263 catch ( RuntimeException
& )
265 // be robust, if e.g. a remote bridge has disposed already.
266 // there is no way to delegate the error to the caller :o(.
272 void OInterfaceContainerHelper2::clear()
274 ClearableMutexGuard
aGuard( rMutex
);
275 OInterfaceIteratorHelper2
aIt( *this );
276 // Release container, in case new entries come while disposing
277 OSL_ENSURE( !bIsList
|| bInUse
, "OInterfaceContainerHelper2 not in use" );
278 if( !bIsList
&& aData
.pAsInterface
)
279 aData
.pAsInterface
->release();
280 // set the member to null, use the iterator to delete the values
281 aData
.pAsInterface
= nullptr;
284 // release mutex before aIt destructor call
291 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */