summaryrefslogtreecommitdiffstats
path: root/include/comphelper/interfacecontainer2.hxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /include/comphelper/interfacecontainer2.hxx
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include/comphelper/interfacecontainer2.hxx')
-rw-r--r--include/comphelper/interfacecontainer2.hxx290
1 files changed, 290 insertions, 0 deletions
diff --git a/include/comphelper/interfacecontainer2.hxx b/include/comphelper/interfacecontainer2.hxx
new file mode 100644
index 000000000..3df7c71d4
--- /dev/null
+++ b/include/comphelper/interfacecontainer2.hxx
@@ -0,0 +1,290 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_COMPHELPER_INTERFACECONTAINER2_H
+#define INCLUDED_COMPHELPER_INTERFACECONTAINER2_H
+
+#include <sal/config.h>
+
+#include <vector>
+
+#include <com/sun/star/lang/EventObject.hpp>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <comphelper/comphelperdllapi.h>
+
+namespace com::sun::star::uno { class XInterface; }
+namespace osl { class Mutex; }
+
+namespace comphelper
+{
+
+namespace detail {
+
+ /**
+ This is here to optimise space in the common case that there are zero or one
+ listeners.
+ */
+ union element_alias2
+ {
+ std::vector< css::uno::Reference< css::uno::XInterface > > *pAsVector;
+ css::uno::XInterface * pAsInterface;
+ element_alias2() : pAsInterface(nullptr) {}
+ };
+
+}
+
+
+class OInterfaceContainerHelper2;
+/**
+ This is the iterator of an OInterfaceContainerHelper2. 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 OInterfaceContainerHelper2
+ */
+class COMPHELPER_DLLPUBLIC OInterfaceIteratorHelper2
+{
+public:
+ /**
+ Create an iterator over the elements of the container. The iterator
+ copies the elements of the container. 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.
+ */
+ OInterfaceIteratorHelper2( OInterfaceContainerHelper2 & rCont );
+
+ /**
+ Releases the connection to the container.
+ */
+ ~OInterfaceIteratorHelper2();
+
+ /** Return true, if there are more elements in the iterator. */
+ bool hasMoreElements() const
+ { return nRemain != 0; }
+ /** Return the next element of the iterator. Calling this method if
+ hasMoreElements() has returned false, is an error. Cast the
+ returned pointer to the
+ */
+ css::uno::XInterface * next();
+
+ /** 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 remove();
+
+private:
+ OInterfaceContainerHelper2 & rCont;
+ detail::element_alias2 aData;
+ sal_Int32 nRemain;
+ bool bIsList;
+
+ OInterfaceIteratorHelper2( const OInterfaceIteratorHelper2 & ) = delete;
+ OInterfaceIteratorHelper2 & operator = ( const OInterfaceIteratorHelper2 & ) = delete;
+};
+
+
+/**
+ A container of interfaces. To access the elements use an iterator.
+ This implementation is thread-safe.
+
+ This is a copy of the code at include/cppuhelper/interfacecontainer.h,
+ Except that it uses a std::vector instead of a Sequence for the mutable listener
+ list, which provides far better performance.
+
+ @see OInterfaceIteratorHelper2
+ */
+class COMPHELPER_DLLPUBLIC OInterfaceContainerHelper2
+{
+public:
+ /**
+ Create an interface container.
+
+ @param rMutex the mutex to protect multi thread access.
+ The lifetime must be longer than the lifetime
+ of this object.
+ */
+ OInterfaceContainerHelper2( ::osl::Mutex & rMutex );
+ /**
+ Release all interfaces. All iterators must be destroyed before
+ the container is destructed.
+ */
+ ~OInterfaceContainerHelper2();
+ /**
+ Return the number of Elements in the container. Only useful if you have acquired
+ the mutex.
+ */
+ sal_Int32 getLength() const;
+
+ /**
+ Return all interfaces added to this container.
+ **/
+ std::vector< css::uno::Reference< css::uno::XInterface > > getElements() const;
+
+ /** 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 addInterface( const css::uno::Reference< css::uno::XInterface > & rxIFace );
+ /** 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 removeInterface( const css::uno::Reference< css::uno::XInterface > & rxIFace );
+ /** Return an interface by index */
+ css::uno::Reference< css::uno::XInterface > getInterface(sal_Int32 nIndex) const;
+ /**
+ Call disposing on all object in the container that
+ support XEventListener. Then clear the container.
+ */
+ void disposeAndClear( const css::lang::EventObject & rEvt );
+ /**
+ Clears the container without calling disposing().
+ */
+ void clear();
+
+ /** Executes a functor for each contained listener of specified type, e.g.
+ <code>forEach<awt::XPaintListener>(...</code>.
+
+ If a css::lang::DisposedException occurs which relates to
+ the called listener, then that listener is removed from the container.
+
+ @tparam ListenerT listener type
+ @tparam FuncT unary functor type, let your compiler deduce this for you
+ @param func unary functor object expecting an argument of type
+ css::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 css::lang::DisposedException occurs which relates to
+ the called listener, then that listener is removed from the container.
+
+ @tparam ListenerT UNO event listener type, let your compiler deduce this for you
+ @tparam 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:
+@code
+ awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
+ listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
+@endcode
+ */
+ template< typename ListenerT, typename EventT >
+ inline void notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event );
+
+private:
+friend class OInterfaceIteratorHelper2;
+ /**
+ bIsList == TRUE -> aData.pAsVector of type vector< XInterfaceSequence >,
+ otherwise aData.pAsInterface == of type (XEventListener *)
+ */
+ detail::element_alias2 aData;
+ ::osl::Mutex & rMutex;
+ /** TRUE -> used by an iterator. */
+ bool bInUse;
+ /** TRUE -> aData.pAsVector is of type Sequence< XInterfaceSequence >. */
+ bool bIsList;
+
+ OInterfaceContainerHelper2( const OInterfaceContainerHelper2 & ) = delete;
+ OInterfaceContainerHelper2 & operator = ( const OInterfaceContainerHelper2 & ) = delete;
+
+ /*
+ Duplicate content of the container and release the old one without destroying.
+ The mutex must be locked and the memberbInUse must be true.
+ */
+ void copyAndResetInUse();
+
+private:
+ template< typename ListenerT, typename EventT >
+ class NotifySingleListener
+ {
+ private:
+ typedef void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& );
+ NotificationMethod const m_pMethod;
+ const EventT& m_rEvent;
+ public:
+ NotifySingleListener( NotificationMethod method, const EventT& event ) : m_pMethod( method ), m_rEvent( event ) { }
+
+ void operator()( const css::uno::Reference<ListenerT>& listener ) const
+ {
+ (listener.get()->*m_pMethod)( m_rEvent );
+ }
+ };
+};
+
+template <typename ListenerT, typename FuncT>
+inline void OInterfaceContainerHelper2::forEach( FuncT const& func )
+{
+ OInterfaceIteratorHelper2 iter( *this );
+ while (iter.hasMoreElements()) {
+ css::uno::Reference<ListenerT> const xListener( iter.next(), css::uno::UNO_QUERY );
+ if (xListener.is()) {
+ try {
+ func( xListener );
+ }
+ catch (css::lang::DisposedException const& exc) {
+ if (exc.Context == xListener)
+ iter.remove();
+ }
+ }
+ }
+}
+
+template< typename ListenerT, typename EventT >
+inline void OInterfaceContainerHelper2::notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event )
+{
+ forEach< ListenerT, NotifySingleListener< ListenerT, EventT > >( NotifySingleListener< ListenerT, EventT >( NotificationMethod, Event ) );
+}
+
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */