summaryrefslogtreecommitdiff
path: root/cppuhelper/inc/cppuhelper/interfacecontainer.h
diff options
context:
space:
mode:
Diffstat (limited to 'cppuhelper/inc/cppuhelper/interfacecontainer.h')
-rw-r--r--cppuhelper/inc/cppuhelper/interfacecontainer.h617
1 files changed, 617 insertions, 0 deletions
diff --git a/cppuhelper/inc/cppuhelper/interfacecontainer.h b/cppuhelper/inc/cppuhelper/interfacecontainer.h
new file mode 100644
index 000000000000..ee57127a4fca
--- /dev/null
+++ b/cppuhelper/inc/cppuhelper/interfacecontainer.h
@@ -0,0 +1,617 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CPPUHELPER_INTERFACECONTAINER_H_
+#define _CPPUHELPER_INTERFACECONTAINER_H_
+
+#include <vector>
+#include <osl/mutex.hxx>
+#include <rtl/alloc.h>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/XInterface.hpp>
+#ifndef _COM_SUN_STAR_LANG_EVENTOBJECT_HXX_
+#include <com/sun/star/lang/EventObject.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HXX_
+#include "com/sun/star/lang/DisposedException.hpp"
+#endif
+
+/** */ //for docpp
+namespace cppu
+{
+
+namespace detail {
+
+ union element_alias
+ {
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > > *pAsSequence;
+ ::com::sun::star::uno::XInterface * pAsInterface;
+ element_alias() : pAsInterface(0) {}
+ };
+
+}
+
+//===================================================================
+class OInterfaceContainerHelper;
+/**
+ This is the iterator of a InterfaceContainerHelper. Typically
+ one constructs an instance on the stack for one firing session.
+ It is not allowed to assign or copy an instance of this class.
+
+ @see OInterfaceContainerHelper
+ */
+class OInterfaceIteratorHelper
+{
+public:
+ /**
+ Create an iterator over the elements of the container. The iterator
+ copies the elements of the conatainer. A change to the container
+ during the lifetime of an iterator is allowed and does not
+ affect the iterator-instance. The iterator and the container take cares
+ themself for concurrent access, no additional guarding is necessary.
+
+ Remark: The copy is on demand. The iterator copy the elements only if the container
+ change the contents. It is not allowed to destroy the container as long
+ as an iterator exist.
+
+ @param rCont the container of the elements.
+ */
+ OInterfaceIteratorHelper( OInterfaceContainerHelper & rCont ) SAL_THROW( () );
+
+ /**
+ Releases the connection to the container.
+ */
+ ~OInterfaceIteratorHelper() SAL_THROW( () );
+
+ /** Return sal_True, if there are more elements in the iterator. */
+ sal_Bool SAL_CALL hasMoreElements() const SAL_THROW( () )
+ { return nRemain != 0; }
+ /** Return the next element of the iterator. Calling this method if
+ hasMoreElements() has returned sal_False, is an error. Cast the
+ returned pointer to the
+ */
+ ::com::sun::star::uno::XInterface * SAL_CALL next() SAL_THROW( () );
+
+ /** Removes the current element (the last one returned by next())
+ from the underlying container. Calling this method before
+ next() has been called or calling it twice with no next()
+ inbetween is an error.
+ */
+ void SAL_CALL remove() SAL_THROW( () );
+
+private:
+ OInterfaceContainerHelper & rCont;
+ sal_Bool bIsList;
+
+ detail::element_alias aData;
+
+ sal_Int32 nRemain;
+
+ OInterfaceIteratorHelper( const OInterfaceIteratorHelper & ) SAL_THROW( () );
+ OInterfaceIteratorHelper & operator = ( const OInterfaceIteratorHelper & ) SAL_THROW( () );
+};
+
+//===================================================================
+/**
+ A container of interfaces. To access the elements use an iterator.
+ This implementation is thread save.
+
+ @see OInterfaceIteratorHelper
+ */
+class OInterfaceContainerHelper
+{
+public:
+ // these are here to force memory de/allocation to sal lib.
+ inline static void * SAL_CALL operator new( size_t nSize ) SAL_THROW( () )
+ { return ::rtl_allocateMemory( nSize ); }
+ inline static void SAL_CALL operator delete( void * pMem ) SAL_THROW( () )
+ { ::rtl_freeMemory( pMem ); }
+ inline static void * SAL_CALL operator new( size_t, void * pMem ) SAL_THROW( () )
+ { return pMem; }
+ inline static void SAL_CALL operator delete( void *, void * ) SAL_THROW( () )
+ {}
+
+ /**
+ Create an interface container.
+
+ @param rMutex the mutex to protect multi thread access.
+ The lifetime must be longer than the lifetime
+ of this object.
+ */
+ OInterfaceContainerHelper( ::osl::Mutex & rMutex ) SAL_THROW( () );
+ /**
+ Release all interfaces. All iterators must be destroyed before
+ the container is destructed.
+ */
+ ~OInterfaceContainerHelper() SAL_THROW( () );
+ /**
+ Return the number of Elements in the container. Only useful if you have acquired
+ the mutex.
+ */
+ sal_Int32 SAL_CALL getLength() const SAL_THROW( () );
+
+ /**
+ Return all interfaces added to this container.
+ **/
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > > SAL_CALL getElements() const SAL_THROW( () );
+
+ /** Inserts an element into the container. The position is not specified, thus it is not
+ specified in which order events are fired.
+
+ @attention
+ If you add the same interface more than once, then it will be added to the elements list
+ more than once and thus if you want to remove that interface from the list, you have to call
+ removeInterface() the same number of times.
+ In the latter case, you will also get events fired more than once (if the interface is a
+ listener interface).
+
+ @param rxIFace
+ interface to be added; it is allowed to insert null or
+ the same interface more than once
+ @return
+ the new count of elements in the container
+ */
+ sal_Int32 SAL_CALL addInterface( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & rxIFace ) SAL_THROW( () );
+ /** Removes an element from the container. It uses interface equality to remove the interface.
+
+ @param rxIFace
+ interface to be removed
+ @return
+ the new count of elements in the container
+ */
+ sal_Int32 SAL_CALL removeInterface( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & rxIFace ) SAL_THROW( () );
+ /**
+ Call disposing on all object in the container that
+ support XEventListener. Than clear the container.
+ */
+ void SAL_CALL disposeAndClear( const ::com::sun::star::lang::EventObject & rEvt ) SAL_THROW( () );
+ /**
+ Clears the container without calling disposing().
+ */
+ void SAL_CALL clear() SAL_THROW( () );
+
+ /** Executes a functor for each contained listener of specified type, e.g.
+ <code>forEach<awt::XPaintListener>(...</code>.
+
+ If a com::sun::star::lang::DisposedException occurs which relates to
+ the called listener, then that listener is removed from the container.
+
+ @tpl ListenerT listener type
+ @tpl FuncT unary functor type, let your compiler deduce this for you
+ @param func unary functor object expecting an argument of type
+ ::com::sun::star::uno::Reference<ListenerT>
+ */
+ template <typename ListenerT, typename FuncT>
+ inline void forEach( FuncT const& func );
+
+ /** Calls a UNO listener method for each contained listener.
+
+ The listener method must take a single argument of type EventT,
+ and return <code>void</code>.
+
+ If a com::sun::star::lang::DisposedException occurs which relates to
+ the called listener, then that listener is removed from the container.
+
+ @tpl ListenerT UNO event listener type, let your compiler deduce this for you
+ @tpl EventT event type, let your compiler deduce this for you
+ @param NotificationMethod
+ Pointer to a method of a ListenerT interface.
+ @param Event
+ Event to notify to all contained listeners
+
+ @example
+<pre>
+ awt::PaintEvent aEvent( static_cast< ::cppu::OWeakObject* >( this ), ... );
+ listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
+</pre>
+ */
+ template< typename ListenerT, typename EventT >
+ inline void notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event );
+
+private:
+friend class OInterfaceIteratorHelper;
+ /**
+ bIsList == TRUE -> aData.pAsSequence of type Sequence< XInterfaceSequence >,
+ otherwise aData.pAsInterface == of type (XEventListener *)
+ */
+ detail::element_alias aData;
+ ::osl::Mutex & rMutex;
+ /** TRUE -> used by an iterator. */
+ sal_Bool bInUse;
+ /** TRUE -> aData.pAsSequence is of type Sequence< XInterfaceSequence >. */
+ sal_Bool bIsList;
+
+ OInterfaceContainerHelper( const OInterfaceContainerHelper & ) SAL_THROW( () );
+ OInterfaceContainerHelper & operator = ( const OInterfaceContainerHelper & ) SAL_THROW( () );
+
+ /*
+ Dulicate content of the conaitner and release the old one without destroying.
+ The mutex must be locked and the memberbInUse must be true.
+ */
+ void copyAndResetInUse() SAL_THROW( () );
+
+private:
+ template< typename ListenerT, typename EventT >
+ class NotifySingleListener
+ {
+ private:
+ typedef void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& );
+ NotificationMethod m_pMethod;
+ const EventT& m_rEvent;
+ public:
+ NotifySingleListener( NotificationMethod method, const EventT& event ) : m_pMethod( method ), m_rEvent( event ) { }
+
+ void operator()( const ::com::sun::star::uno::Reference<ListenerT>& listener ) const
+ {
+ (listener.get()->*m_pMethod)( m_rEvent );
+ }
+ };
+};
+
+template <typename ListenerT, typename FuncT>
+inline void OInterfaceContainerHelper::forEach( FuncT const& func )
+{
+ OInterfaceIteratorHelper iter( *this );
+ while (iter.hasMoreElements()) {
+ ::com::sun::star::uno::Reference<ListenerT> const xListener(
+ iter.next(), ::com::sun::star::uno::UNO_QUERY );
+ if (xListener.is()) {
+#if defined(EXCEPTIONS_OFF)
+ func( xListener );
+#else
+ try {
+ func( xListener );
+ }
+ catch (::com::sun::star::lang::DisposedException const& exc) {
+ if (exc.Context == xListener)
+ iter.remove();
+ }
+#endif
+ }
+ }
+}
+
+template< typename ListenerT, typename EventT >
+inline void OInterfaceContainerHelper::notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event )
+{
+ forEach< ListenerT, NotifySingleListener< ListenerT, EventT > >( NotifySingleListener< ListenerT, EventT >( NotificationMethod, Event ) );
+}
+
+//===================================================================
+/**
+ A helper class to store interface references of different types.
+
+ @see OInterfaceIteratorHelper
+ @see OInterfaceContainerHelper
+ */
+template< class key , class hashImpl , class equalImpl >
+class OMultiTypeInterfaceContainerHelperVar
+{
+public:
+ // these are here to force memory de/allocation to sal lib.
+ inline static void * SAL_CALL operator new( size_t nSize ) SAL_THROW( () )
+ { return ::rtl_allocateMemory( nSize ); }
+ inline static void SAL_CALL operator delete( void * pMem ) SAL_THROW( () )
+ { ::rtl_freeMemory( pMem ); }
+ inline static void * SAL_CALL operator new( size_t, void * pMem ) SAL_THROW( () )
+ { return pMem; }
+ inline static void SAL_CALL operator delete( void *, void * ) SAL_THROW( () )
+ {}
+
+ /**
+ Create a container of interface containers.
+
+ @param rMutex the mutex to protect multi thread access.
+ The lifetime must be longer than the lifetime
+ of this object.
+ */
+ inline OMultiTypeInterfaceContainerHelperVar( ::osl::Mutex & ) SAL_THROW( () );
+ /**
+ Deletes all containers.
+ */
+ inline ~OMultiTypeInterfaceContainerHelperVar() SAL_THROW( () );
+
+ /**
+ Return all id's under which at least one interface is added.
+ */
+ inline ::com::sun::star::uno::Sequence< key > SAL_CALL getContainedTypes() const SAL_THROW( () );
+
+ /**
+ Return the container created under this key.
+ The InterfaceContainerHelper exists until the whole MultiTypeContainer is destroyed.
+ @return the container created under this key. If the container
+ was not created, null was returned.
+ */
+ inline OInterfaceContainerHelper * SAL_CALL getContainer( const key & ) const SAL_THROW( () );
+
+ /** Inserts an element into the container with the specified key.
+ The position is not specified, thus it is not specified in which order events are fired.
+
+ @attention
+ If you add the same interface more than once, then it will be added to the elements list
+ more than once and thus if you want to remove that interface from the list, you have to call
+ removeInterface() the same number of times.
+ In the latter case, you will also get events fired more than once (if the interface is a
+ listener interface).
+
+ @param rKey
+ the id of the container
+ @param r
+ interface to be added; it is allowed, to insert null or
+ the same interface more than once
+ @return
+ the new count of elements in the container
+ */
+ inline sal_Int32 SAL_CALL addInterface(
+ const key & rKey,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & r )
+ SAL_THROW( () );
+
+ /** Removes an element from the container with the specified key.
+ It uses interface equality to remove the interface.
+
+ @param rKey
+ the id of the container
+ @param rxIFace
+ interface to be removed
+ @return
+ the new count of elements in the container
+ */
+ inline sal_Int32 SAL_CALL removeInterface(
+ const key & rKey,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & rxIFace )
+ SAL_THROW( () );
+
+ /**
+ Call disposing on all references in the container, that
+ support XEventListener. Then clears the container.
+ @param rEvt the event object which is passed during disposing() call
+ */
+ inline void SAL_CALL disposeAndClear( const ::com::sun::star::lang::EventObject & rEvt ) SAL_THROW( () );
+ /**
+ Remove all elements of all containers. Does not delete the container.
+ */
+ inline void SAL_CALL clear() SAL_THROW( () );
+
+ typedef key keyType;
+private:
+ typedef ::std::vector< std::pair < key , void* > > InterfaceMap;
+ InterfaceMap *m_pMap;
+ ::osl::Mutex & rMutex;
+
+ inline typename InterfaceMap::iterator find(const key &rKey) const
+ {
+ typename InterfaceMap::iterator iter = m_pMap->begin();
+ typename InterfaceMap::iterator end = m_pMap->end();
+
+ while( iter != end )
+ {
+ equalImpl equal;
+ if( equal( iter->first, rKey ) )
+ break;
+ iter++;
+ }
+ return iter;
+ }
+
+ inline OMultiTypeInterfaceContainerHelperVar( const OMultiTypeInterfaceContainerHelperVar & ) SAL_THROW( () );
+ inline OMultiTypeInterfaceContainerHelperVar & operator = ( const OMultiTypeInterfaceContainerHelperVar & ) SAL_THROW( () );
+};
+
+
+
+
+/**
+ This struct contains the standard variables of a broadcaster. Helper
+ classes only know a reference to this struct instead of references
+ to the four members. The access to the members must be guarded with
+ rMutex.
+
+ The additional template parameter keyType has been added, because gcc
+ can't compile addListener( const container::keyType &key ).
+ */
+template < class container , class keyType >
+struct OBroadcastHelperVar
+{
+ /** The shared mutex. */
+ ::osl::Mutex & rMutex;
+ /** ListenerContainer class is thread save. */
+ container aLC;
+ /** Dispose call ready. */
+ sal_Bool bDisposed;
+ /** In dispose call. */
+ sal_Bool bInDispose;
+
+ /**
+ Initialize the structur. bDispose and bInDispose are set to false.
+ @param rMutex the mutex reference.
+ */
+ OBroadcastHelperVar( ::osl::Mutex & rMutex_ ) SAL_THROW( () )
+ : rMutex( rMutex_ )
+ , aLC( rMutex_ )
+ , bDisposed( sal_False )
+ , bInDispose( sal_False )
+ {}
+
+ /**
+ adds a listener threadsafe.
+ **/
+ inline void addListener(
+ const keyType &key,
+ const ::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface > &r )
+ SAL_THROW( () )
+ {
+ ::osl::MutexGuard guard( rMutex );
+ OSL_ENSURE( !bInDispose, "do not add listeners in the dispose call" );
+ OSL_ENSURE( !bDisposed, "object is disposed" );
+ if( ! bInDispose && ! bDisposed )
+ aLC.addInterface( key , r );
+ }
+
+ /**
+ removes a listener threadsafe
+ **/
+ inline void removeListener(
+ const keyType &key,
+ const ::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface > & r )
+ SAL_THROW( () )
+ {
+ ::osl::MutexGuard guard( rMutex );
+ OSL_ENSURE( !bDisposed, "object is disposed" );
+ if( ! bInDispose && ! bDisposed )
+ aLC.removeInterface( key , r );
+ }
+
+ /**
+ Return the container created under this key.
+ @return the container created under this key. If the container
+ was not created, null was returned. This can be used to optimize
+ performance ( construction of an event object can be avoided ).
+ ***/
+ inline OInterfaceContainerHelper * SAL_CALL getContainer( const keyType &key ) const SAL_THROW( () )
+ { return aLC.getContainer( key ); }
+};
+
+/*------------------------------------------
+*
+* In general, the above templates are used with a Type as key.
+* Therefore a default declaration is given ( OMultiTypeInterfaceContainerHelper and OBroadcastHelper )
+*
+*------------------------------------------*/
+
+// helper function call class
+struct hashType_Impl
+{
+ size_t operator()(const ::com::sun::star::uno::Type & s) const SAL_THROW( () )
+ { return s.getTypeName().hashCode(); }
+};
+
+
+/** Specialized class for key type com::sun::star::uno::Type,
+ without explicit usage of STL symbols.
+*/
+class OMultiTypeInterfaceContainerHelper
+{
+public:
+ // these are here to force memory de/allocation to sal lib.
+ inline static void * SAL_CALL operator new( size_t nSize ) SAL_THROW( () )
+ { return ::rtl_allocateMemory( nSize ); }
+ inline static void SAL_CALL operator delete( void * pMem ) SAL_THROW( () )
+ { ::rtl_freeMemory( pMem ); }
+ inline static void * SAL_CALL operator new( size_t, void * pMem ) SAL_THROW( () )
+ { return pMem; }
+ inline static void SAL_CALL operator delete( void *, void * ) SAL_THROW( () )
+ {}
+
+ /**
+ Create a container of interface containers.
+
+ @param rMutex the mutex to protect multi thread access.
+ The lifetime must be longer than the lifetime
+ of this object.
+ */
+ OMultiTypeInterfaceContainerHelper( ::osl::Mutex & ) SAL_THROW( () );
+ /**
+ Delete all containers.
+ */
+ ~OMultiTypeInterfaceContainerHelper() SAL_THROW( () );
+
+ /**
+ Return all id's under which at least one interface is added.
+ */
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getContainedTypes() const SAL_THROW( () );
+
+ /**
+ Return the container created under this key.
+ @return the container created under this key. If the container
+ was not created, null was returned.
+ */
+ OInterfaceContainerHelper * SAL_CALL getContainer( const ::com::sun::star::uno::Type & rKey ) const SAL_THROW( () );
+
+ /** Inserts an element into the container with the specified key.
+ The position is not specified, thus it is not specified in which order events are fired.
+
+ @attention
+ If you add the same interface more than once, then it will be added to the elements list
+ more than once and thus if you want to remove that interface from the list, you have to call
+ removeInterface() the same number of times.
+ In the latter case, you will also get events fired more than once (if the interface is a
+ listener interface).
+
+ @param rKey
+ the id of the container
+ @param r
+ interface to be added; it is allowed, to insert null or
+ the same interface more than once
+ @return
+ the new count of elements in the container
+ */
+ sal_Int32 SAL_CALL addInterface(
+ const ::com::sun::star::uno::Type & rKey,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & r )
+ SAL_THROW( () );
+
+ /** Removes an element from the container with the specified key.
+ It uses interface equality to remove the interface.
+
+ @param rKey
+ the id of the container
+ @param rxIFace
+ interface to be removed
+ @return
+ the new count of elements in the container
+ */
+ sal_Int32 SAL_CALL removeInterface(
+ const ::com::sun::star::uno::Type & rKey,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & rxIFace )
+ SAL_THROW( () );
+
+ /**
+ Call disposing on all object in the container that
+ support XEventListener. Than clear the container.
+ */
+ void SAL_CALL disposeAndClear( const ::com::sun::star::lang::EventObject & rEvt ) SAL_THROW( () );
+ /**
+ Remove all elements of all containers. Does not delete the container.
+ */
+ void SAL_CALL clear() SAL_THROW( () );
+
+ typedef ::com::sun::star::uno::Type keyType;
+private:
+ void *m_pMap;
+ ::osl::Mutex & rMutex;
+
+ inline OMultiTypeInterfaceContainerHelper( const OMultiTypeInterfaceContainerHelper & ) SAL_THROW( () );
+ inline OMultiTypeInterfaceContainerHelper & operator = ( const OMultiTypeInterfaceContainerHelper & ) SAL_THROW( () );
+};
+
+typedef OBroadcastHelperVar< OMultiTypeInterfaceContainerHelper , OMultiTypeInterfaceContainerHelper::keyType > OBroadcastHelper;
+
+}
+
+#endif
+