comphelper/source/misc/accessibleeventnotifier.cxx | 374 ++++++++++----------- include/comphelper/accessibleeventnotifier.hxx | 169 ++++----- 2 files changed, 261 insertions(+), 282 deletions(-)
New commits: commit 6ba107fbab8a110a6545a935bbdbdb9356d53d61 Author: Kohei Yoshida <[email protected]> Date: Sat Feb 18 19:01:14 2017 -0500 Consistent formatting & indentation. Change-Id: I5dce7d05156313d460533040b8f7a3de3d8c59d7 Reviewed-on: https://gerrit.libreoffice.org/34420 Reviewed-by: Kohei Yoshida <[email protected]> Tested-by: Kohei Yoshida <[email protected]> diff --git a/comphelper/source/misc/accessibleeventnotifier.cxx b/comphelper/source/misc/accessibleeventnotifier.cxx index 9eeeafc..507b4f8 100644 --- a/comphelper/source/misc/accessibleeventnotifier.cxx +++ b/comphelper/source/misc/accessibleeventnotifier.cxx @@ -31,261 +31,251 @@ using namespace ::com::sun::star::lang; using namespace ::com::sun::star::accessibility; using namespace ::comphelper; -namespace +namespace { + +typedef std::pair< AccessibleEventNotifier::TClientId, + AccessibleEventObject > ClientEvent; + +typedef std::map< AccessibleEventNotifier::TClientId, + ::comphelper::OInterfaceContainerHelper2* > ClientMap; + +/// key is the end of the interval, value is the start of the interval +typedef std::map<AccessibleEventNotifier::TClientId, + AccessibleEventNotifier::TClientId> IntervalMap; + +struct lclMutex : public rtl::Static< ::osl::Mutex, lclMutex > {}; + +struct Clients : public rtl::Static< ClientMap, Clients > {}; + +struct FreeIntervals : public rtl::StaticWithInit<IntervalMap, FreeIntervals> { - typedef std::pair< AccessibleEventNotifier::TClientId, - AccessibleEventObject > ClientEvent; - - typedef std::map< AccessibleEventNotifier::TClientId, - ::comphelper::OInterfaceContainerHelper2* > ClientMap; - - /// key is the end of the interval, value is the start of the interval - typedef std::map<AccessibleEventNotifier::TClientId, - AccessibleEventNotifier::TClientId> IntervalMap; - - struct lclMutex - : public rtl::Static< ::osl::Mutex, lclMutex > {}; - struct Clients - : public rtl::Static< ClientMap, Clients > {}; - struct FreeIntervals - : public rtl::StaticWithInit<IntervalMap, FreeIntervals> { - IntervalMap operator() () { - IntervalMap map; - map.insert(std::make_pair( - std::numeric_limits<AccessibleEventNotifier::TClientId>::max(), 1)); - return map; - } - }; - - void releaseId(AccessibleEventNotifier::TClientId const nId) + IntervalMap operator() () { - IntervalMap & rFreeIntervals(FreeIntervals::get()); - IntervalMap::iterator const upper(rFreeIntervals.upper_bound(nId)); - assert(upper != rFreeIntervals.end()); - assert(nId < upper->second); // second is start of the interval! - if (nId + 1 == upper->second) - { - --upper->second; // add nId to existing interval - } - else - { - IntervalMap::iterator const lower(rFreeIntervals.lower_bound(nId)); - if (lower != rFreeIntervals.end() && lower->first == nId - 1) - { - // add nId by replacing lower with new merged entry - rFreeIntervals.insert(std::make_pair(nId, lower->second)); - rFreeIntervals.erase(lower); - } - else // otherwise just add new 1-element interval - { - rFreeIntervals.insert(std::make_pair(nId, nId)); - } - } - // currently it's not checked whether intervals can be merged now - // hopefully that won't be a problem in practice + IntervalMap map; + map.insert(std::make_pair( + std::numeric_limits<AccessibleEventNotifier::TClientId>::max(), 1)); + return map; } +}; - /// generates a new client id - AccessibleEventNotifier::TClientId generateId() +void releaseId(AccessibleEventNotifier::TClientId const nId) +{ + IntervalMap & rFreeIntervals(FreeIntervals::get()); + IntervalMap::iterator const upper(rFreeIntervals.upper_bound(nId)); + assert(upper != rFreeIntervals.end()); + assert(nId < upper->second); // second is start of the interval! + if (nId + 1 == upper->second) + { + --upper->second; // add nId to existing interval + } + else { - IntervalMap & rFreeIntervals(FreeIntervals::get()); - assert(!rFreeIntervals.empty()); - IntervalMap::iterator const iter(rFreeIntervals.begin()); - AccessibleEventNotifier::TClientId const nFirst = iter->first; - AccessibleEventNotifier::TClientId const nFreeId = iter->second; - assert(nFreeId <= nFirst); - if (nFreeId != nFirst) + IntervalMap::iterator const lower(rFreeIntervals.lower_bound(nId)); + if (lower != rFreeIntervals.end() && lower->first == nId - 1) { - ++iter->second; // remove nFreeId from interval + // add nId by replacing lower with new merged entry + rFreeIntervals.insert(std::make_pair(nId, lower->second)); + rFreeIntervals.erase(lower); } - else + else // otherwise just add new 1-element interval { - rFreeIntervals.erase(iter); // remove 1-element interval + rFreeIntervals.insert(std::make_pair(nId, nId)); } + } + // currently it's not checked whether intervals can be merged now + // hopefully that won't be a problem in practice +} - assert(Clients::get().end() == Clients::get().find(nFreeId)); - - return nFreeId; +/// generates a new client id +AccessibleEventNotifier::TClientId generateId() +{ + IntervalMap & rFreeIntervals(FreeIntervals::get()); + assert(!rFreeIntervals.empty()); + IntervalMap::iterator const iter(rFreeIntervals.begin()); + AccessibleEventNotifier::TClientId const nFirst = iter->first; + AccessibleEventNotifier::TClientId const nFreeId = iter->second; + assert(nFreeId <= nFirst); + if (nFreeId != nFirst) + { + ++iter->second; // remove nFreeId from interval + } + else + { + rFreeIntervals.erase(iter); // remove 1-element interval } - /** looks up a client in our client map, asserts if it cannot find it or - no event thread is present + assert(Clients::get().end() == Clients::get().find(nFreeId)); - @precond - to be called with our mutex locked + return nFreeId; +} - @param nClient - the id of the client to lookup - @param rPos - out-parameter for the position of the client in the client map +/** looks up a client in our client map, asserts if it cannot find it or + no event thread is present - @return - <TRUE/> if and only if the client could be found and - <arg>rPos</arg> has been filled with its position - */ - bool implLookupClient( - const AccessibleEventNotifier::TClientId nClient, - ClientMap::iterator& rPos ) - { - // look up this client - ClientMap &rClients = Clients::get(); - rPos = rClients.find( nClient ); - assert( rClients.end() != rPos && - "AccessibleEventNotifier::implLookupClient: invalid client id " - "(did you register your client?)!" ); - - return ( rClients.end() != rPos ); - } + @precond + to be called with our mutex locked + + @param nClient + the id of the client to lookup + @param rPos + out-parameter for the position of the client in the client map + + @return + <TRUE/> if and only if the client could be found and + <arg>rPos</arg> has been filled with its position +*/ +bool implLookupClient( + const AccessibleEventNotifier::TClientId nClient, + ClientMap::iterator& rPos ) +{ + // look up this client + ClientMap &rClients = Clients::get(); + rPos = rClients.find( nClient ); + assert( rClients.end() != rPos && + "AccessibleEventNotifier::implLookupClient: invalid client id " + "(did you register your client?)!" ); + + return ( rClients.end() != rPos ); } +} // anonymous namespace -namespace comphelper +namespace comphelper { + +AccessibleEventNotifier::TClientId AccessibleEventNotifier::registerClient() { + ::osl::MutexGuard aGuard( lclMutex::get() ); + // generate a new client id + TClientId nNewClientId = generateId( ); - AccessibleEventNotifier::TClientId AccessibleEventNotifier::registerClient( ) - { - ::osl::MutexGuard aGuard( lclMutex::get() ); + // the event listeners for the new client + ::comphelper::OInterfaceContainerHelper2 *const pNewListeners = + new ::comphelper::OInterfaceContainerHelper2( lclMutex::get() ); + // note that we're using our own mutex here, so the listener containers for all + // our clients share this same mutex. + // this is a reminiscence to the days where the notifier was asynchronous. Today this is + // completely nonsense, and potentially slowing down the Office me thinks... - // generate a new client id - TClientId nNewClientId = generateId( ); + // add the client + Clients::get().insert( ClientMap::value_type( nNewClientId, pNewListeners ) ); - // the event listeners for the new client - ::comphelper::OInterfaceContainerHelper2 *const pNewListeners = - new ::comphelper::OInterfaceContainerHelper2( lclMutex::get() ); - // note that we're using our own mutex here, so the listener containers for all - // our clients share this same mutex. - // this is a reminiscence to the days where the notifier was asynchronous. Today this is - // completely nonsense, and potentially slowing down the Office me thinks... + // outta here + return nNewClientId; +} - // add the client - Clients::get().insert( ClientMap::value_type( nNewClientId, pNewListeners ) ); +void AccessibleEventNotifier::revokeClient( const TClientId _nClient ) +{ + ::osl::MutexGuard aGuard( lclMutex::get() ); - // outta here - return nNewClientId; - } + ClientMap::iterator aClientPos; + if ( !implLookupClient( _nClient, aClientPos ) ) + // already asserted in implLookupClient + return; + // remove it from the clients map + delete aClientPos->second; + Clients::get().erase( aClientPos ); + releaseId(_nClient); +} + +void AccessibleEventNotifier::revokeClientNotifyDisposing( + const TClientId _nClient, const Reference< XInterface >& _rxEventSource ) +{ + ::comphelper::OInterfaceContainerHelper2* pListeners(nullptr); - void AccessibleEventNotifier::revokeClient( const TClientId _nClient ) { + // rhbz#1001768 drop the mutex before calling disposeAndClear ::osl::MutexGuard aGuard( lclMutex::get() ); ClientMap::iterator aClientPos; - if ( !implLookupClient( _nClient, aClientPos ) ) + if (!implLookupClient(_nClient, aClientPos)) // already asserted in implLookupClient return; - // remove it from the clients map - delete aClientPos->second; - Clients::get().erase( aClientPos ); + // notify the listeners + pListeners = aClientPos->second; + + // we do not need the entry in the clients map anymore + // (do this before actually notifying, because some client + // implementations have re-entrance problems and call into + // revokeClient while we are notifying from here) + Clients::get().erase(aClientPos); releaseId(_nClient); } + // notify the "disposing" event for this client + EventObject aDisposalEvent; + aDisposalEvent.Source = _rxEventSource; - void AccessibleEventNotifier::revokeClientNotifyDisposing( const TClientId _nClient, - const Reference< XInterface >& _rxEventSource ) - { - ::comphelper::OInterfaceContainerHelper2* pListeners(nullptr); + // now really do the notification + pListeners->disposeAndClear( aDisposalEvent ); + delete pListeners; +} - { - // rhbz#1001768 drop the mutex before calling disposeAndClear - ::osl::MutexGuard aGuard( lclMutex::get() ); - - ClientMap::iterator aClientPos; - if (!implLookupClient(_nClient, aClientPos)) - // already asserted in implLookupClient - return; - - // notify the listeners - pListeners = aClientPos->second; - - // we do not need the entry in the clients map anymore - // (do this before actually notifying, because some client - // implementations have re-entrance problems and call into - // revokeClient while we are notifying from here) - Clients::get().erase(aClientPos); - releaseId(_nClient); - } +sal_Int32 AccessibleEventNotifier::addEventListener( + const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) +{ + ::osl::MutexGuard aGuard( lclMutex::get() ); - // notify the "disposing" event for this client - EventObject aDisposalEvent; - aDisposalEvent.Source = _rxEventSource; + ClientMap::iterator aClientPos; + if ( !implLookupClient( _nClient, aClientPos ) ) + // already asserted in implLookupClient + return 0; - // now really do the notification - pListeners->disposeAndClear( aDisposalEvent ); - delete pListeners; - } + if ( _rxListener.is() ) + aClientPos->second->addInterface( _rxListener ); + return aClientPos->second->getLength(); +} - sal_Int32 AccessibleEventNotifier::addEventListener( - const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) - { - ::osl::MutexGuard aGuard( lclMutex::get() ); +sal_Int32 AccessibleEventNotifier::removeEventListener( + const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) +{ + ::osl::MutexGuard aGuard( lclMutex::get() ); - ClientMap::iterator aClientPos; - if ( !implLookupClient( _nClient, aClientPos ) ) - // already asserted in implLookupClient - return 0; + ClientMap::iterator aClientPos; + if ( !implLookupClient( _nClient, aClientPos ) ) + // already asserted in implLookupClient + return 0; - if ( _rxListener.is() ) - aClientPos->second->addInterface( _rxListener ); + if ( _rxListener.is() ) + aClientPos->second->removeInterface( _rxListener ); - return aClientPos->second->getLength(); - } + return aClientPos->second->getLength(); +} +void AccessibleEventNotifier::addEvent( const TClientId _nClient, const AccessibleEventObject& _rEvent ) +{ + std::vector< Reference< XInterface > > aListeners; - sal_Int32 AccessibleEventNotifier::removeEventListener( - const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) { ::osl::MutexGuard aGuard( lclMutex::get() ); ClientMap::iterator aClientPos; if ( !implLookupClient( _nClient, aClientPos ) ) // already asserted in implLookupClient - return 0; - - if ( _rxListener.is() ) - aClientPos->second->removeInterface( _rxListener ); + return; - return aClientPos->second->getLength(); + // since we're synchronous, again, we want to notify immediately + aListeners = aClientPos->second->getElements(); } - - void AccessibleEventNotifier::addEvent( const TClientId _nClient, const AccessibleEventObject& _rEvent ) + // default handling: loop through all listeners, and notify them + for ( const auto& rListener : aListeners ) { - std::vector< Reference< XInterface > > aListeners; - - // --- <mutex lock> ------------------------------- + try { - ::osl::MutexGuard aGuard( lclMutex::get() ); - - ClientMap::iterator aClientPos; - if ( !implLookupClient( _nClient, aClientPos ) ) - // already asserted in implLookupClient - return; - - // since we're synchronous, again, we want to notify immediately - aListeners = aClientPos->second->getElements(); + static_cast< XAccessibleEventListener* >( rListener.get() )->notifyEvent( _rEvent ); } - // --- </mutex lock> ------------------------------ - - // default handling: loop through all listeners, and notify them - for ( const auto& rListener : aListeners ) + catch( const Exception& ) { - try - { - static_cast< XAccessibleEventListener* >( rListener.get() )->notifyEvent( _rEvent ); - } - catch( const Exception& ) - { - // no assertion, because a broken access remote bridge or something like this - // can cause this exception - } + // no assertion, because a broken access remote bridge or something like this + // can cause this exception } } +} - -} // namespace comphelper - +} // namespace comphelper /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/accessibleeventnotifier.hxx b/include/comphelper/accessibleeventnotifier.hxx index 572ac77..f8cf110 100644 --- a/include/comphelper/accessibleeventnotifier.hxx +++ b/include/comphelper/accessibleeventnotifier.hxx @@ -25,98 +25,87 @@ #include <comphelper/comphelperdllapi.h> +namespace comphelper { -namespace comphelper +class COMPHELPER_DLLPUBLIC AccessibleEventNotifier { - - - //= AccessibleEventNotifier - - class COMPHELPER_DLLPUBLIC AccessibleEventNotifier - { - // typedefs - public: - typedef sal_uInt32 TClientId; - - public: - AccessibleEventNotifier() = delete; - ~AccessibleEventNotifier() = delete; - AccessibleEventNotifier( const AccessibleEventNotifier& ) = delete; - AccessibleEventNotifier& operator=( const AccessibleEventNotifier& ) = delete; - - /** registers a client of this class, means a broadcaster of AccessibleEvents - - <p>No precaution is taken to care for disposal of this component. When the component - dies, it <b>must</b> call <member>revokeClient</member> or <member>revokeClientNotifyDisposing</member> - explicitly itself.</p> - */ - static TClientId registerClient( ); - - /** revokes a broadcaster of AccessibleEvents - - <p>Note that no disposing event is fired when you use this method, the client is simply revoked. - You can for instance revoke a client if the last listener for it is revoked, but the client - itself is not disposed.<br/> - When the client is disposed, you should prefer <member>revokeClientNotifyDisposing</member></p> - - <p>Any possibly pending events for this client are removed from the queue.</p> - - @seealso revokeClientNotifyDisposing - */ - static void revokeClient( const TClientId _nClient ); - - /** revokes a client, with additionally notifying a disposing event to all listeners registered for - this client - - <p>Any other possibly pending events for this client are removed from the queue</p> - - @param _nClient - the id of the client which should be revoked - @param _rxEventSource - the source to be notified together with the <member scope="com.sun.star.lang">XComponent::disposing</member> - call. - */ - static void revokeClientNotifyDisposing( - const TClientId _nClient, - const css::uno::Reference< css::uno::XInterface >& _rxEventSource - ); - - /** registers a listener for the given client - - @param _nClient - the id of the client for which a listener should be registered - @return - the number of event listeners currently registered for this client - */ - static sal_Int32 addEventListener( - const TClientId _nClient, - const css::uno::Reference< css::accessibility::XAccessibleEventListener >& _rxListener - ); - - /** revokes a listener for the given client - - @param _nClient - the id of the client for which a listener should be revoked - @return - the number of event listeners currently registered for this client - */ - static sal_Int32 removeEventListener( - const TClientId _nClient, - const css::uno::Reference< css::accessibility::XAccessibleEventListener >& _rxListener - ); - - /** adds an event, which is to be broadcasted, to the queue - - @param _nClient - the id of the client which needs to broadcast the event - */ - static void addEvent( - const TClientId _nClient, - const css::accessibility::AccessibleEventObject& _rEvent - ); - - }; - +public: + typedef sal_uInt32 TClientId; + +public: + AccessibleEventNotifier() = delete; + ~AccessibleEventNotifier() = delete; + AccessibleEventNotifier( const AccessibleEventNotifier& ) = delete; + AccessibleEventNotifier& operator=( const AccessibleEventNotifier& ) = delete; + + /** registers a client of this class, means a broadcaster of AccessibleEvents + + <p>No precaution is taken to care for disposal of this component. When the component + dies, it <b>must</b> call <member>revokeClient</member> or <member>revokeClientNotifyDisposing</member> + explicitly itself.</p> + */ + static TClientId registerClient(); + + /** revokes a broadcaster of AccessibleEvents + + <p>Note that no disposing event is fired when you use this method, the client is simply revoked. + You can for instance revoke a client if the last listener for it is revoked, but the client + itself is not disposed.<br/> + When the client is disposed, you should prefer <member>revokeClientNotifyDisposing</member></p> + + <p>Any possibly pending events for this client are removed from the queue.</p> + + @seealso revokeClientNotifyDisposing + */ + static void revokeClient( const TClientId _nClient ); + + /** revokes a client, with additionally notifying a disposing event to all listeners registered for + this client + + <p>Any other possibly pending events for this client are removed from the queue</p> + + @param _nClient + the id of the client which should be revoked + @param _rxEventSource + the source to be notified together with the <member scope="com.sun.star.lang">XComponent::disposing</member> + call. + */ + static void revokeClientNotifyDisposing( + const TClientId _nClient, + const css::uno::Reference< css::uno::XInterface >& _rxEventSource ); + + /** registers a listener for the given client + + @param _nClient + the id of the client for which a listener should be registered + @return + the number of event listeners currently registered for this client + */ + static sal_Int32 addEventListener( + const TClientId _nClient, + const css::uno::Reference< css::accessibility::XAccessibleEventListener >& _rxListener ); + + /** revokes a listener for the given client + + @param _nClient + the id of the client for which a listener should be revoked + @return + the number of event listeners currently registered for this client + */ + static sal_Int32 removeEventListener( + const TClientId _nClient, + const css::uno::Reference< css::accessibility::XAccessibleEventListener >& _rxListener ); + + /** adds an event, which is to be broadcasted, to the queue + + @param _nClient + the id of the client which needs to broadcast the event + */ + static void addEvent( + const TClientId _nClient, + const css::accessibility::AccessibleEventObject& _rEvent ); + +}; } // namespace comphelper _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
