/* -*- 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 .
*/
/// key is the end of the interval, value is the start of the interval typedef std::map<AccessibleEventNotifier::TClientId,
AccessibleEventNotifier::TClientId> IntervalMap;
void releaseId(AccessibleEventNotifier::TClientId const nId)
{
IntervalMap & rFreeIntervals(GetFreeIntervals());
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
}
/// generates a new client id
AccessibleEventNotifier::TClientId generateId()
{
IntervalMap & rFreeIntervals(GetFreeIntervals());
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
@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 = gaClients;
rPos = rClients.find( nClient );
assert( rClients.end() != rPos && "AccessibleEventNotifier::implLookupClient: invalid client id " "(did you register your client?)!" );
ClientMap::iterator aClientPos; if (!implLookupClient(_nClient, aClientPos)) // already asserted in implLookupClient return;
// notify the listeners
ListenerContainer aListeners(std::move(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)
gaClients.erase(aClientPos);
releaseId(_nClient);
// notify the "disposing" event for this client
EventObject aDisposalEvent;
aDisposalEvent.Source = _rxEventSource;
// now really do the notification
aListeners.disposeAndClear( aGuard, aDisposalEvent );
}
ClientMap::iterator aClientPos; if ( !implLookupClient( _nClient, aClientPos ) ) // already asserted in implLookupClient return;
// since we're synchronous, again, we want to notify immediately
OInterfaceIteratorHelper4 aIt(aGuard, aClientPos->second); // no need to hold lock here, and we don't want to hold lock while calling listeners
aGuard.unlock(); while (aIt.hasMoreElements())
{ try
{
aIt.next()->notifyEvent(_rEvent);
} catch (Exception&)
{ // no assertion, because a broken access remote bridge or something like this // can cause this exception
}
}
}
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.