/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* *ThisfileispartoftheLibreOfficeproject. * *ThisSourceCodeFormissubjecttothetermsoftheMozillaPublic *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis *file,Youcanobtainoneathttp://mozilla.org/MPL/2.0/. * *Thisfileincorporatesworkcoveredbythefollowinglicensenotice: * *LicensedtotheApacheSoftwareFoundation(ASF)underoneormore *contributorlicenseagreements.SeetheNOTICEfiledistributed *withthisworkforadditionalinformationregardingcopyright *ownership.TheASFlicensesthisfiletoyouundertheApache *License,Version2.0(the"License");youmaynotusethisfile *exceptincompliancewiththeLicense.Youmayobtainacopyof *theLicenseathttp://www.apache.org/licenses/LICENSE-2.0 .
*/ #pragma once #include <sal/config.h> #include <com/sun/star/lang/EventObject.hpp> #include <comphelper/interfacecontainer4.hxx> #include <memory> #include <mutex> #include <vector> /** */ //for docpp namespace comphelper
{ /** Ahelperclasstostoreinterfacereferencesofdifferenttypes. Thisisacopyofthecodeatinclude/comphelper/multiinterfacecontainer3.hxx, exceptthatit(a)usesstd::mutexinsteadofosl::Mutexand(b)doesnot storeareferencetothemutex,butreliesonthecallingclasstotake alockaroundusingit. @seeOInterfaceIteratorHelper3 @seeOInterfaceContainerHelper3
*/ template <class key, class listener, class equalImpl = std::equal_to<key>> class OMultiTypeInterfaceContainerHelperVar4
{ public:
OMultiTypeInterfaceContainerHelperVar4() {} /** Returnallid'sunderwhichatleastoneinterfaceisadded.
*/ inline std::vector<key> getContainedTypes(std::unique_lock<std::mutex>& rGuard) const
{
assert(rGuard.owns_lock());
std::vector<key> aInterfaceTypes;
aInterfaceTypes.reserve(m_aMap.size()); for (constauto& rPair : m_aMap) // are interfaces added to this container? if (rPair.second->getLength(rGuard)) // yes, put the type in the array
aInterfaceTypes.push_back(rPair.first); return aInterfaceTypes;
} inlinebool hasContainedTypes(std::unique_lock<std::mutex>& rGuard) const
{
assert(rGuard.owns_lock()); for (constauto& rPair : m_aMap) // are interfaces added to this container? if (rPair.second->getLength(rGuard)) returntrue; returnfalse;
} /** Returnthecontainercreatedunderthiskey. TheInterfaceContainerHelperexistsuntilthewholeMultiTypeContainerisdestroyed. @returnthecontainercreatedunderthiskey.Ifthecontainer wasnotcreated,nullwasreturned.
*/ inline OInterfaceContainerHelper4<listener>* getContainer(std::unique_lock<std::mutex>& rGuard, const key& rKey) const
{ auto iter = find(rGuard, rKey); if (iter != m_aMap.end()) return (*iter).second.get(); return nullptr;
} /** Inserts an element into the container with the specified key. Thepositionisnotspecified,thusitisnotspecifiedinwhichordereventsarefired. @attention Ifyouaddthesameinterfacemorethanonce,thenitwillbeaddedtotheelementslist morethanonceandthusifyouwanttoremovethatinterfacefromthelist,youhavetocall removeInterface()thesamenumberoftimes. Inthelattercase,youwillalsogeteventsfiredmorethanonce(iftheinterfaceisa listenerinterface). @paramrKey theidofthecontainer @paramr interfacetobeadded;itisallowed,toinsertnullor thesameinterfacemorethanonce @return thenewcountofelementsinthecontainer
*/ inline sal_Int32 addInterface(::std::unique_lock<::std::mutex>& rGuard, const key& rKey, const css::uno::Reference<listener>& rListener)
{ auto iter = find(rGuard, rKey); if (iter == m_aMap.end())
{ auto pLC = new OInterfaceContainerHelper4<listener>();
m_aMap.emplace_back(rKey, pLC); return pLC->addInterface(rGuard, rListener);
} else return (*iter).second->addInterface(rGuard, rListener);
} /** Removes an element from the container with the specified key. Itusesinterfaceequalitytoremovetheinterface. @paramrKey theidofthecontainer @paramrxIFace interfacetoberemoved @return thenewcountofelementsinthecontainer
*/ inline sal_Int32 removeInterface(::std::unique_lock<::std::mutex>& rGuard, const key& rKey, const css::uno::Reference<listener>& rListener)
{ // search container with id nUik auto iter = find(rGuard, rKey); // container found? if (iter != m_aMap.end()) return (*iter).second->removeInterface(rGuard, rListener); // no container with this id. Always return 0 return0;
} /** Calldisposingonallreferencesinthecontainer,that supportXEventListener.Thenclearsthecontainer. @paramrEvttheeventobjectwhichispassedduringdisposing()call
*/ inlinevoid disposeAndClear(std::unique_lock<std::mutex>& rGuard, const css::lang::EventObject& rEvt)
{
assert(rGuard.owns_lock()); // create a copy, because do not fire event in a guarded section
InterfaceMap tempMap;
{
tempMap = std::move(m_aMap);
}
rGuard.unlock(); // So... we don't want to hold the normal mutex while we fire // the events, but the calling convention here wants a mutex, so // just create a temporary/fake one. Since the listeners we // are working with are now function-local, we don't really need // a mutex at all, but it's easier to create a fake one than // create a bunch of special-case code for this situation.
std::mutex tempMutex;
std::unique_lock tempGuard(tempMutex); for (auto& rPair : tempMap)
{
OInterfaceIteratorHelper4<listener> aIt(tempGuard, *rPair.second); while (aIt.hasMoreElements())
{ try
{
aIt.next()->disposing(rEvt);
} catch (css::uno::RuntimeException&)
{ // be robust, if e.g. a remote bridge has disposed already. // there is no way to delegate the error to the caller :o(.
}
}
}
rGuard.lock(); // return with lock in same state as entry
} /** Removeallelementsofallcontainers.Doesnotdeletethecontainer.
*/ inlinevoid clear(std::unique_lock<std::mutex>& rGuard)
{
assert(rGuard.owns_lock());
(void)rGuard; for (constauto& rPair : m_aMap)
rPair.second->clear();
} typedef key keyType;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.