/src/libreoffice/cppuhelper/source/interfacecontainer.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | |
21 | | #include <cppuhelper/interfacecontainer.hxx> |
22 | | #include <cppuhelper/propshlp.hxx> |
23 | | #include <comphelper/sequence.hxx> |
24 | | |
25 | | #include <o3tl/safeint.hxx> |
26 | | #include <osl/diagnose.h> |
27 | | #include <osl/mutex.hxx> |
28 | | #include <sal/log.hxx> |
29 | | |
30 | | #include <memory> |
31 | | |
32 | | #include <com/sun/star/lang/XEventListener.hpp> |
33 | | |
34 | | |
35 | | using namespace osl; |
36 | | using namespace com::sun::star::uno; |
37 | | using namespace com::sun::star::lang; |
38 | | |
39 | | namespace cppu |
40 | | { |
41 | | |
42 | | OInterfaceIteratorHelper::OInterfaceIteratorHelper( OInterfaceContainerHelper & rCont_ ) |
43 | 31.4k | : rCont( rCont_ ) |
44 | 31.4k | { |
45 | 31.4k | MutexGuard aGuard( rCont.rMutex ); |
46 | 31.4k | if( rCont.bInUse ) |
47 | | // worst case, two iterators at the same time |
48 | 0 | rCont.copyAndResetInUse(); |
49 | 31.4k | bIsList = rCont_.bIsList; |
50 | 31.4k | aData = rCont_.aData; |
51 | 31.4k | if( bIsList ) |
52 | 10.6k | { |
53 | 10.6k | rCont.bInUse = true; |
54 | 10.6k | nRemain = aData.pAsVector->size(); |
55 | 10.6k | } |
56 | 20.8k | else if( aData.pAsInterface ) |
57 | 0 | { |
58 | 0 | aData.pAsInterface->acquire(); |
59 | 0 | nRemain = 1; |
60 | 0 | } |
61 | 20.8k | else |
62 | 20.8k | nRemain = 0; |
63 | 31.4k | } |
64 | | |
65 | | OInterfaceIteratorHelper::~OInterfaceIteratorHelper() |
66 | 31.4k | { |
67 | 31.4k | bool bShared; |
68 | 31.4k | { |
69 | 31.4k | MutexGuard aGuard( rCont.rMutex ); |
70 | | // bResetInUse protect the iterator against recursion |
71 | 31.4k | bShared = aData.pAsVector == rCont.aData.pAsVector && rCont.bIsList; |
72 | 31.4k | if( bShared ) |
73 | 0 | { |
74 | 0 | OSL_ENSURE( rCont.bInUse, "OInterfaceContainerHelper must be in use" ); |
75 | 0 | rCont.bInUse = false; |
76 | 0 | } |
77 | 31.4k | } |
78 | | |
79 | 31.4k | if( !bShared ) |
80 | 31.4k | { |
81 | 31.4k | if( bIsList ) |
82 | | // Sequence owned by the iterator |
83 | 10.6k | delete aData.pAsVector; |
84 | 20.8k | else if( aData.pAsInterface ) |
85 | | // Interface is acquired by the iterator |
86 | 0 | aData.pAsInterface->release(); |
87 | 31.4k | } |
88 | 31.4k | } |
89 | | |
90 | | XInterface * OInterfaceIteratorHelper::next() |
91 | 21.3k | { |
92 | 21.3k | if( nRemain ) |
93 | 21.3k | { |
94 | 21.3k | nRemain--; |
95 | 21.3k | if( bIsList ) |
96 | | // typecase to const,so the getArray method is faster |
97 | 21.3k | return (*aData.pAsVector)[nRemain].get(); |
98 | 0 | if( aData.pAsInterface ) |
99 | 0 | return aData.pAsInterface; |
100 | 0 | } |
101 | | // exception |
102 | 0 | return nullptr; |
103 | 21.3k | } |
104 | | |
105 | | void OInterfaceIteratorHelper::remove() |
106 | 0 | { |
107 | 0 | if( bIsList ) |
108 | 0 | { |
109 | 0 | OSL_ASSERT( nRemain >= 0 && |
110 | 0 | o3tl::make_unsigned(nRemain) < aData.pAsVector->size() ); |
111 | 0 | XInterface * p = (*aData.pAsVector)[nRemain].get(); |
112 | 0 | rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >( &p ) ); |
113 | 0 | } |
114 | 0 | else |
115 | 0 | { |
116 | 0 | OSL_ASSERT( 0 == nRemain ); |
117 | 0 | rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >(&aData.pAsInterface)); |
118 | 0 | } |
119 | 0 | } |
120 | | |
121 | | OInterfaceContainerHelper::OInterfaceContainerHelper( Mutex & rMutex_ ) |
122 | 31.6k | : rMutex( rMutex_ ) |
123 | 31.6k | , bInUse( false ) |
124 | 31.6k | , bIsList( false ) |
125 | 31.6k | { |
126 | 31.6k | } |
127 | | |
128 | | OInterfaceContainerHelper::~OInterfaceContainerHelper() |
129 | 31.4k | { |
130 | 31.4k | OSL_ENSURE( !bInUse, "~OInterfaceContainerHelper but is in use" ); |
131 | 31.4k | if( bIsList ) |
132 | 0 | delete aData.pAsVector; |
133 | 31.4k | else if( aData.pAsInterface ) |
134 | 0 | aData.pAsInterface->release(); |
135 | 31.4k | } |
136 | | |
137 | | sal_Int32 OInterfaceContainerHelper::getLength() const |
138 | 0 | { |
139 | 0 | MutexGuard aGuard( rMutex ); |
140 | 0 | if( bIsList ) |
141 | 0 | return aData.pAsVector->size(); |
142 | 0 | if( aData.pAsInterface ) |
143 | 0 | return 1; |
144 | 0 | return 0; |
145 | 0 | } |
146 | | |
147 | | Sequence< Reference<XInterface> > OInterfaceContainerHelper::getElements() const |
148 | 0 | { |
149 | 0 | MutexGuard aGuard( rMutex ); |
150 | 0 | if( bIsList ) |
151 | 0 | return comphelper::containerToSequence(*aData.pAsVector); |
152 | 0 | if( aData.pAsInterface ) |
153 | 0 | { |
154 | 0 | Reference<XInterface> x( aData.pAsInterface ); |
155 | 0 | return Sequence< Reference< XInterface > >( &x, 1 ); |
156 | 0 | } |
157 | 0 | return Sequence< Reference< XInterface > >(); |
158 | 0 | } |
159 | | |
160 | | void OInterfaceContainerHelper::copyAndResetInUse() |
161 | 0 | { |
162 | 0 | OSL_ENSURE( bInUse, "OInterfaceContainerHelper not in use" ); |
163 | 0 | if( bInUse ) |
164 | 0 | { |
165 | | // this should be the worst case. If an iterator is active |
166 | | // and a new Listener is added. |
167 | 0 | if( bIsList ) |
168 | 0 | aData.pAsVector= new std::vector< Reference< XInterface > >( *aData.pAsVector ); |
169 | 0 | else if( aData.pAsInterface ) |
170 | 0 | aData.pAsInterface->acquire(); |
171 | |
|
172 | 0 | bInUse = false; |
173 | 0 | } |
174 | 0 | } |
175 | | |
176 | | sal_Int32 OInterfaceContainerHelper::addInterface( const Reference<XInterface> & rListener ) |
177 | 52.9k | { |
178 | 52.9k | SAL_WARN_IF( !rListener.is(), "cppuhelper", "rListener is empty" ); |
179 | 52.9k | MutexGuard aGuard( rMutex ); |
180 | 52.9k | if( bInUse ) |
181 | 0 | copyAndResetInUse(); |
182 | | |
183 | 52.9k | if( bIsList ) |
184 | 10.6k | { |
185 | 10.6k | aData.pAsVector->push_back(rListener); |
186 | 10.6k | return aData.pAsVector->size(); |
187 | 10.6k | } |
188 | 42.2k | if( aData.pAsInterface ) |
189 | 10.6k | { |
190 | 10.6k | Reference<XInterface> tmp(aData.pAsInterface); |
191 | 10.6k | aData.pAsInterface->release(); |
192 | 10.6k | aData.pAsVector = new std::vector<Reference<XInterface>>(2); |
193 | 10.6k | (*aData.pAsVector)[0] = std::move(tmp); |
194 | 10.6k | (*aData.pAsVector)[1] = rListener; |
195 | 10.6k | bIsList = true; |
196 | 10.6k | return 2; |
197 | 10.6k | } |
198 | 31.6k | aData.pAsInterface = rListener.get(); |
199 | 31.6k | if( rListener.is() ) |
200 | 31.6k | rListener->acquire(); |
201 | 31.6k | return 1; |
202 | 42.2k | } |
203 | | |
204 | | sal_Int32 OInterfaceContainerHelper::removeInterface( const Reference<XInterface> & rListener ) |
205 | 31.4k | { |
206 | 31.4k | SAL_WARN_IF( !rListener.is(), "cppuhelper", "rListener is empty" ); |
207 | 31.4k | MutexGuard aGuard( rMutex ); |
208 | 31.4k | if( bInUse ) |
209 | 0 | copyAndResetInUse(); |
210 | | |
211 | 31.4k | if( bIsList ) |
212 | 10.6k | { |
213 | | // It is not valid to compare the pointer directly, but it's faster. |
214 | 10.6k | auto findIt = std::find_if(aData.pAsVector->begin(), aData.pAsVector->end(), |
215 | 10.6k | [&](const Reference<XInterface>& r) |
216 | 10.6k | { return r.get() == rListener.get(); }); |
217 | 10.6k | if (findIt != aData.pAsVector->end()) |
218 | 10.6k | { |
219 | 10.6k | aData.pAsVector->erase(findIt); |
220 | 10.6k | } |
221 | 0 | else |
222 | 0 | { |
223 | | // interface not found, use the correct compare method |
224 | 0 | for( auto it = aData.pAsVector->begin(); it != aData.pAsVector->end(); ++it ) |
225 | 0 | { |
226 | 0 | if( *it == rListener ) |
227 | 0 | { |
228 | 0 | aData.pAsVector->erase(it); |
229 | 0 | break; |
230 | 0 | } |
231 | 0 | } |
232 | 0 | } |
233 | | |
234 | 10.6k | if( aData.pAsVector->size() == 1 ) |
235 | 0 | { |
236 | 0 | XInterface * p = (*aData.pAsVector)[0].get(); |
237 | 0 | p->acquire(); |
238 | 0 | delete aData.pAsVector; |
239 | 0 | aData.pAsInterface = p; |
240 | 0 | bIsList = false; |
241 | 0 | return 1; |
242 | 0 | } |
243 | 10.6k | return aData.pAsVector->size(); |
244 | 10.6k | } |
245 | 20.8k | if( aData.pAsInterface && Reference<XInterface>( aData.pAsInterface ) == rListener ) |
246 | 20.8k | { |
247 | 20.8k | aData.pAsInterface->release(); |
248 | 20.8k | aData.pAsInterface = nullptr; |
249 | 20.8k | } |
250 | 20.8k | return aData.pAsInterface ? 1 : 0; |
251 | 31.4k | } |
252 | | |
253 | | void OInterfaceContainerHelper::disposeAndClear( const EventObject & rEvt ) |
254 | 31.4k | { |
255 | 31.4k | ClearableMutexGuard aGuard( rMutex ); |
256 | 31.4k | OInterfaceIteratorHelper aIt( *this ); |
257 | | // Release container, in case new entries come while disposing |
258 | 31.4k | OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" ); |
259 | 31.4k | if( !bIsList && aData.pAsInterface ) |
260 | 0 | aData.pAsInterface->release(); |
261 | | // set the member to null, use the iterator to delete the values |
262 | 31.4k | aData.pAsInterface = nullptr; |
263 | 31.4k | bIsList = false; |
264 | 31.4k | bInUse = false; |
265 | 31.4k | aGuard.clear(); |
266 | 52.7k | while( aIt.hasMoreElements() ) |
267 | 21.3k | { |
268 | 21.3k | try |
269 | 21.3k | { |
270 | 21.3k | Reference<XEventListener > xLst( aIt.next(), UNO_QUERY ); |
271 | 21.3k | if( xLst.is() ) |
272 | 21.3k | xLst->disposing( rEvt ); |
273 | 21.3k | } |
274 | 21.3k | catch ( RuntimeException & ) |
275 | 21.3k | { |
276 | | // be robust, if e.g. a remote bridge has disposed already. |
277 | | // there is no way to delegate the error to the caller :o(. |
278 | 0 | } |
279 | 21.3k | } |
280 | 31.4k | } |
281 | | |
282 | | |
283 | | void OInterfaceContainerHelper::clear() |
284 | 0 | { |
285 | 0 | MutexGuard aGuard( rMutex ); |
286 | | // Release container, in case new entries come while disposing |
287 | 0 | OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" ); |
288 | 0 | if (bInUse) |
289 | 0 | copyAndResetInUse(); |
290 | 0 | if (bIsList) |
291 | 0 | delete aData.pAsVector; |
292 | 0 | else if (aData.pAsInterface) |
293 | 0 | aData.pAsInterface->release(); |
294 | 0 | aData.pAsInterface = nullptr; |
295 | 0 | bIsList = false; |
296 | 0 | } |
297 | | |
298 | | // specialized class for type |
299 | | |
300 | | typedef std::vector< std::pair < Type , void* > > t_type2ptr; |
301 | | |
302 | | OMultiTypeInterfaceContainerHelper::OMultiTypeInterfaceContainerHelper( Mutex & rMutex_ ) |
303 | 3.78M | : rMutex( rMutex_ ) |
304 | 3.78M | { |
305 | 3.78M | m_pMap = new t_type2ptr; |
306 | 3.78M | } |
307 | | |
308 | | OMultiTypeInterfaceContainerHelper::~OMultiTypeInterfaceContainerHelper() |
309 | 3.77M | { |
310 | 3.77M | t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap); |
311 | | |
312 | 3.77M | for (auto& rItem : *pMap) |
313 | 31.4k | { |
314 | 31.4k | delete static_cast<OInterfaceContainerHelper*>(rItem.second); |
315 | 31.4k | rItem.second = nullptr; |
316 | 31.4k | } |
317 | 3.77M | delete pMap; |
318 | 3.77M | } |
319 | | |
320 | | Sequence< Type > OMultiTypeInterfaceContainerHelper::getContainedTypes() const |
321 | 0 | { |
322 | 0 | t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap); |
323 | 0 | t_type2ptr::size_type nSize; |
324 | |
|
325 | 0 | ::osl::MutexGuard aGuard( rMutex ); |
326 | 0 | nSize = pMap->size(); |
327 | 0 | if( nSize ) |
328 | 0 | { |
329 | 0 | css::uno::Sequence< Type > aInterfaceTypes( nSize ); |
330 | 0 | Type * pArray = aInterfaceTypes.getArray(); |
331 | |
|
332 | 0 | sal_Int32 i = 0; |
333 | 0 | for (const auto& rItem : *pMap) |
334 | 0 | { |
335 | | // are interfaces added to this container? |
336 | 0 | if( static_cast<OInterfaceContainerHelper*>(rItem.second)->getLength() ) |
337 | | // yes, put the type in the array |
338 | 0 | pArray[i++] = rItem.first; |
339 | 0 | } |
340 | 0 | if( static_cast<t_type2ptr::size_type>(i) != nSize ) { |
341 | | // may be empty container, reduce the sequence to the right size |
342 | 0 | aInterfaceTypes = css::uno::Sequence< Type >( pArray, i ); |
343 | 0 | } |
344 | 0 | return aInterfaceTypes; |
345 | 0 | } |
346 | 0 | return css::uno::Sequence< Type >(); |
347 | 0 | } |
348 | | |
349 | | static t_type2ptr::iterator findType(t_type2ptr *pMap, const Type & rKey ) |
350 | 988k | { |
351 | 988k | return std::find_if(pMap->begin(), pMap->end(), |
352 | 988k | [&rKey](const t_type2ptr::value_type& rItem) { return rItem.first == rKey; }); |
353 | 988k | } |
354 | | |
355 | | OInterfaceContainerHelper * OMultiTypeInterfaceContainerHelper::getContainer( const Type & rKey ) const |
356 | 904k | { |
357 | 904k | ::osl::MutexGuard aGuard( rMutex ); |
358 | | |
359 | 904k | t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap); |
360 | 904k | t_type2ptr::iterator iter = findType( pMap, rKey ); |
361 | 904k | if( iter != pMap->end() ) |
362 | 0 | return static_cast<OInterfaceContainerHelper*>((*iter).second); |
363 | 904k | return nullptr; |
364 | 904k | } |
365 | | |
366 | | sal_Int32 OMultiTypeInterfaceContainerHelper::addInterface( |
367 | | const Type & rKey, const Reference< XInterface > & rListener ) |
368 | 52.9k | { |
369 | 52.9k | ::osl::MutexGuard aGuard( rMutex ); |
370 | 52.9k | t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap); |
371 | 52.9k | t_type2ptr::iterator iter = findType( pMap, rKey ); |
372 | 52.9k | if( iter == pMap->end() ) |
373 | 31.6k | { |
374 | 31.6k | OInterfaceContainerHelper * pLC = new OInterfaceContainerHelper( rMutex ); |
375 | 31.6k | pMap->push_back(std::pair<Type, void*>(rKey, pLC)); |
376 | 31.6k | return pLC->addInterface( rListener ); |
377 | 31.6k | } |
378 | 21.3k | return static_cast<OInterfaceContainerHelper*>((*iter).second)->addInterface( rListener ); |
379 | 52.9k | } |
380 | | |
381 | | sal_Int32 OMultiTypeInterfaceContainerHelper::removeInterface( |
382 | | const Type & rKey, const Reference< XInterface > & rListener ) |
383 | 31.4k | { |
384 | 31.4k | ::osl::MutexGuard aGuard( rMutex ); |
385 | | |
386 | | // search container with id nUik |
387 | 31.4k | t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap); |
388 | 31.4k | t_type2ptr::iterator iter = findType( pMap, rKey ); |
389 | | // container found? |
390 | 31.4k | if( iter != pMap->end() ) |
391 | 31.4k | return static_cast<OInterfaceContainerHelper*>((*iter).second)->removeInterface( rListener ); |
392 | | |
393 | | // no container with this id. Always return 0 |
394 | 0 | return 0; |
395 | 31.4k | } |
396 | | |
397 | | void OMultiTypeInterfaceContainerHelper::disposeAndClear( const EventObject & rEvt ) |
398 | 3.74M | { |
399 | 3.74M | t_type2ptr::size_type nSize = 0; |
400 | 3.74M | std::unique_ptr<OInterfaceContainerHelper *[]> ppListenerContainers; |
401 | 3.74M | { |
402 | 3.74M | ::osl::MutexGuard aGuard( rMutex ); |
403 | 3.74M | t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap); |
404 | 3.74M | nSize = pMap->size(); |
405 | 3.74M | if( nSize ) |
406 | 31.4k | { |
407 | 31.4k | typedef OInterfaceContainerHelper* ppp; |
408 | 31.4k | ppListenerContainers.reset(new ppp[nSize]); |
409 | | //ppListenerContainers = new (ListenerContainer*)[nSize]; |
410 | | |
411 | 31.4k | t_type2ptr::size_type i = 0; |
412 | 31.4k | for (const auto& rItem : *pMap) |
413 | 31.4k | { |
414 | 31.4k | ppListenerContainers[i++] = static_cast<OInterfaceContainerHelper*>(rItem.second); |
415 | 31.4k | } |
416 | 31.4k | } |
417 | 3.74M | } |
418 | | |
419 | | // create a copy, because do not fire event in a guarded section |
420 | 3.74M | for( t_type2ptr::size_type i = 0; |
421 | 3.77M | i < nSize; i++ ) |
422 | 31.4k | { |
423 | 31.4k | if( ppListenerContainers[i] ) |
424 | 31.4k | ppListenerContainers[i]->disposeAndClear( rEvt ); |
425 | 31.4k | } |
426 | 3.74M | } |
427 | | |
428 | | void OMultiTypeInterfaceContainerHelper::clear() |
429 | 0 | { |
430 | 0 | ::osl::MutexGuard aGuard( rMutex ); |
431 | 0 | t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap); |
432 | |
|
433 | 0 | for (auto& rItem : *pMap) |
434 | 0 | { |
435 | 0 | static_cast<OInterfaceContainerHelper*>(rItem.second)->clear(); |
436 | 0 | } |
437 | 0 | } |
438 | | |
439 | | // specialized class for long |
440 | | |
441 | | typedef std::vector< std::pair < sal_Int32 , void* > > t_long2ptr; |
442 | | |
443 | | static t_long2ptr::iterator findLong(t_long2ptr *pMap, sal_Int32 nKey ) |
444 | 0 | { |
445 | 0 | return std::find_if(pMap->begin(), pMap->end(), |
446 | 0 | [&nKey](const t_long2ptr::value_type& rItem) { return rItem.first == nKey; }); |
447 | 0 | } |
448 | | |
449 | | OMultiTypeInterfaceContainerHelperInt32::OMultiTypeInterfaceContainerHelperInt32( Mutex & rMutex_ ) |
450 | 7.33M | : m_pMap( nullptr ) |
451 | 7.33M | , rMutex( rMutex_ ) |
452 | 7.33M | { |
453 | | // delay pMap allocation until necessary. |
454 | 7.33M | } |
455 | | |
456 | | OMultiTypeInterfaceContainerHelperInt32::~OMultiTypeInterfaceContainerHelperInt32() |
457 | 7.32M | { |
458 | 7.32M | if (!m_pMap) |
459 | 7.32M | return; |
460 | | |
461 | 0 | t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap); |
462 | |
|
463 | 0 | for (auto& rItem : *pMap) |
464 | 0 | { |
465 | 0 | delete static_cast<OInterfaceContainerHelper*>(rItem.second); |
466 | 0 | rItem.second = nullptr; |
467 | 0 | } |
468 | 0 | delete pMap; |
469 | 0 | } |
470 | | |
471 | | Sequence< sal_Int32 > OMultiTypeInterfaceContainerHelperInt32::getContainedTypes() const |
472 | 0 | { |
473 | 0 | t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap); |
474 | 0 | t_long2ptr::size_type nSize; |
475 | |
|
476 | 0 | ::osl::MutexGuard aGuard( rMutex ); |
477 | 0 | nSize = pMap ? pMap->size() : 0; |
478 | 0 | if( nSize ) |
479 | 0 | { |
480 | 0 | css::uno::Sequence< sal_Int32 > aInterfaceTypes( nSize ); |
481 | 0 | sal_Int32 * pArray = aInterfaceTypes.getArray(); |
482 | |
|
483 | 0 | sal_Int32 i = 0; |
484 | 0 | for (const auto& rItem : *pMap) |
485 | 0 | { |
486 | | // are interfaces added to this container? |
487 | 0 | if( static_cast<OInterfaceContainerHelper*>(rItem.second)->getLength() ) |
488 | | // yes, put the type in the array |
489 | 0 | pArray[i++] = rItem.first; |
490 | 0 | } |
491 | 0 | if( static_cast<t_long2ptr::size_type>(i) != nSize ) { |
492 | | // may be empty container, reduce the sequence to the right size |
493 | 0 | aInterfaceTypes = css::uno::Sequence< sal_Int32 >( pArray, i ); |
494 | 0 | } |
495 | 0 | return aInterfaceTypes; |
496 | 0 | } |
497 | 0 | return css::uno::Sequence< sal_Int32 >(); |
498 | 0 | } |
499 | | |
500 | | OInterfaceContainerHelper * OMultiTypeInterfaceContainerHelperInt32::getContainer( const sal_Int32 & rKey ) const |
501 | 446k | { |
502 | 446k | ::osl::MutexGuard aGuard( rMutex ); |
503 | | |
504 | 446k | if (!m_pMap) |
505 | 446k | return nullptr; |
506 | 0 | t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap); |
507 | 0 | t_long2ptr::iterator iter = findLong( pMap, rKey ); |
508 | 0 | if( iter != pMap->end() ) |
509 | 0 | return static_cast<OInterfaceContainerHelper*>((*iter).second); |
510 | 0 | return nullptr; |
511 | 0 | } |
512 | | |
513 | | sal_Int32 OMultiTypeInterfaceContainerHelperInt32::addInterface( |
514 | | const sal_Int32 & rKey, const Reference< XInterface > & rListener ) |
515 | 0 | { |
516 | 0 | ::osl::MutexGuard aGuard( rMutex ); |
517 | 0 | if (!m_pMap) |
518 | 0 | m_pMap = new t_long2ptr; |
519 | 0 | t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap); |
520 | 0 | t_long2ptr::iterator iter = findLong( pMap, rKey ); |
521 | 0 | if( iter == pMap->end() ) |
522 | 0 | { |
523 | 0 | OInterfaceContainerHelper * pLC = new OInterfaceContainerHelper( rMutex ); |
524 | 0 | pMap->push_back(std::pair< sal_Int32, void* >(rKey, pLC)); |
525 | 0 | return pLC->addInterface( rListener ); |
526 | 0 | } |
527 | 0 | return static_cast<OInterfaceContainerHelper*>((*iter).second)->addInterface( rListener ); |
528 | 0 | } |
529 | | |
530 | | sal_Int32 OMultiTypeInterfaceContainerHelperInt32::removeInterface( |
531 | | const sal_Int32 & rKey, const Reference< XInterface > & rListener ) |
532 | 0 | { |
533 | 0 | ::osl::MutexGuard aGuard( rMutex ); |
534 | |
|
535 | 0 | if (!m_pMap) |
536 | 0 | return 0; |
537 | | // search container with id nUik |
538 | 0 | t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap); |
539 | 0 | t_long2ptr::iterator iter = findLong( pMap, rKey ); |
540 | | // container found? |
541 | 0 | if( iter != pMap->end() ) |
542 | 0 | return static_cast<OInterfaceContainerHelper*>((*iter).second)->removeInterface( rListener ); |
543 | | |
544 | | // no container with this id. Always return 0 |
545 | 0 | return 0; |
546 | 0 | } |
547 | | |
548 | | void OMultiTypeInterfaceContainerHelperInt32::disposeAndClear( const EventObject & rEvt ) |
549 | 7.26M | { |
550 | 7.26M | t_long2ptr::size_type nSize = 0; |
551 | 7.26M | std::unique_ptr<OInterfaceContainerHelper *[]> ppListenerContainers; |
552 | 7.26M | { |
553 | 7.26M | ::osl::MutexGuard aGuard( rMutex ); |
554 | 7.26M | if (!m_pMap) |
555 | 7.26M | return; |
556 | | |
557 | 0 | t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap); |
558 | 0 | nSize = pMap->size(); |
559 | 0 | if( nSize ) |
560 | 0 | { |
561 | 0 | typedef OInterfaceContainerHelper* ppp; |
562 | 0 | ppListenerContainers.reset(new ppp[nSize]); |
563 | |
|
564 | 0 | t_long2ptr::size_type i = 0; |
565 | 0 | for (const auto& rItem : *pMap) |
566 | 0 | { |
567 | 0 | ppListenerContainers[i++] = static_cast<OInterfaceContainerHelper*>(rItem.second); |
568 | 0 | } |
569 | 0 | } |
570 | 0 | } |
571 | | |
572 | | // create a copy, because do not fire event in a guarded section |
573 | 0 | for( t_long2ptr::size_type i = 0; |
574 | 0 | i < nSize; i++ ) |
575 | 0 | { |
576 | 0 | if( ppListenerContainers[i] ) |
577 | 0 | ppListenerContainers[i]->disposeAndClear( rEvt ); |
578 | 0 | } |
579 | 0 | } |
580 | | |
581 | | void OMultiTypeInterfaceContainerHelperInt32::clear() |
582 | 0 | { |
583 | 0 | ::osl::MutexGuard aGuard( rMutex ); |
584 | 0 | if (!m_pMap) |
585 | 0 | return; |
586 | 0 | t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap); |
587 | |
|
588 | 0 | for (auto& rItem : *pMap) |
589 | 0 | { |
590 | 0 | static_cast<OInterfaceContainerHelper*>(rItem.second)->clear(); |
591 | 0 | } |
592 | 0 | } |
593 | | |
594 | | } |
595 | | |
596 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |