LibreOffice Module svl (master) 1
SfxBroadcaster.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
21
22#include <svl/hint.hxx>
23#include <svl/lstner.hxx>
24#include <tools/debug.hxx>
25
26#include <algorithm>
27#include <cassert>
28#include <vector>
29
30// broadcast immediately
31
33{
34 // notify all registered listeners exactly once
35 size_t nSize = m_Listeners.size();
36 for (size_t i = 0; i < nSize; ++i)
37 {
38 SfxListener* const pListener = m_Listeners[i];
39 if (pListener)
40 pListener->Notify(*this, rHint);
41 }
42}
43
44// unregister all listeners
45
46SfxBroadcaster::~SfxBroadcaster() COVERITY_NOEXCEPT_FALSE
47{
49
50 // remove all still registered listeners
51 for (size_t i = 0; i < m_Listeners.size(); ++i)
52 {
53 SfxListener* const pListener = m_Listeners[i];
54 if (pListener)
55 pListener->RemoveBroadcaster_Impl(*this);
56 }
57}
58
59// copy ctor of class SfxBroadcaster
60
62{
63 for (size_t i = 0; i < rOther.m_Listeners.size(); ++i)
64 {
65 SfxListener* const pListener = rOther.m_Listeners[i];
66 if (pListener)
67 pListener->StartListening(*this);
68 }
69}
70
71// add a new SfxListener to the list
72
74{
76 if (m_RemovedPositions.empty())
77 {
78 m_Listeners.push_back(&rListener);
79 }
80 else
81 {
82 size_t targetPosition = m_RemovedPositions.back();
83 m_RemovedPositions.pop_back();
84 assert(m_Listeners[targetPosition] == nullptr);
85 m_Listeners[targetPosition] = &rListener;
86 }
87}
88
89// forward a notification to all registered listeners
90
92{
93 for (size_t i = 0; i < m_Listeners.size(); ++i)
94 {
95 SfxListener* const pListener = m_Listeners[i];
96 if (pListener)
97 pListener->Notify(rBC, rHint);
98 }
99}
100
101// remove one SfxListener from the list
102
104{
106
107 // First, check the slots either side of the last removed slot, makes a significant
108 // difference when the list is large.
109 int positionOfRemovedElement = -1;
110 if (!m_RemovedPositions.empty())
111 {
112 auto i = m_RemovedPositions.back();
113 if (i < m_Listeners.size() - 2 && m_Listeners[i + 1] == &rListener)
114 {
115 positionOfRemovedElement = i + 1;
116 }
117 else if (i > 0 && m_Listeners[i - 1] == &rListener)
118 {
119 positionOfRemovedElement = i - 1;
120 }
121 }
122 // then scan the whole list if we didn't find it
123 if (positionOfRemovedElement == -1)
124 {
125 auto aIter = std::find(m_Listeners.begin(), m_Listeners.end(), &rListener);
126 positionOfRemovedElement = std::distance(m_Listeners.begin(), aIter);
127 }
128 // DO NOT erase the listener, set the pointer to 0
129 // because the current continuation may contain this->Broadcast
130 m_Listeners[positionOfRemovedElement] = nullptr;
131 m_RemovedPositions.push_back(positionOfRemovedElement);
132}
133
134void SfxBroadcaster::ForAllListeners(std::function<bool(SfxListener*)> f) const
135{
136 for (size_t i = 0; i < m_Listeners.size(); ++i)
137 {
138 SfxListener* const pListener = m_Listeners[i];
139 if (pListener)
140 f(pListener);
141 }
142}
143
144bool SfxBroadcaster::HasListeners() const { return GetListenerCount() != 0; }
145
147{
148 return m_Listeners.size() - m_RemovedPositions.size();
149}
150
151/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void RemoveListener(SfxListener &rListener)
bool HasListeners() const
void AddListener(SfxListener &rListener)
std::vector< size_t > m_RemovedPositions
Contains the positions of removed listeners.
std::vector< SfxListener * > m_Listeners
size_t GetListenerCount() const
Get the number of listeners which are registered at this broadcaster.
void ForAllListeners(std::function< bool(SfxListener *)> f) const
Iterate over all the listeners and call the passed function.
void Broadcast(const SfxHint &rHint)
void Forward(SfxBroadcaster &rBC, const SfxHint &rHint)
virtual ~SfxBroadcaster() COVERITY_NOEXCEPT_FALSE
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
Registers a specific SfxBroadcaster.
Definition: lstner.cxx:79
void RemoveBroadcaster_Impl(SfxBroadcaster &rBC)
Definition: lstner.cxx:60
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint)
Definition: lstner.cxx:157
#define DBG_TESTSOLARMUTEX()
int i