bump product version to 6.3.0.0.beta1
[LibreOffice.git] / svl / source / notify / broadcast.cxx
blob9a63e4b2b67b4e011ac0e11f375e4a14b0802f15
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <svl/broadcast.hxx>
21 #include <svl/listener.hxx>
22 #include <svl/hint.hxx>
23 #include <cassert>
24 #include <algorithm>
26 void SvtBroadcaster::Normalize() const
28 if (!mbNormalized)
30 std::sort(maListeners.begin(), maListeners.end());
31 mbNormalized = true;
34 if (!mbDestNormalized)
36 std::sort(maDestructedListeners.begin(), maDestructedListeners.end());
37 mbDestNormalized = true;
41 void SvtBroadcaster::Add( SvtListener* p )
43 assert(!mbDisposing && "called inside my own destructor?");
44 assert(!mbAboutToDie && "called after PrepareForDestruction()?");
45 if (mbDisposing || mbAboutToDie)
46 return;
47 // only reset mbNormalized if we are going to become unsorted
48 if (!maListeners.empty() && maListeners.back() > p)
49 mbNormalized = false;
50 maListeners.push_back(p);
53 void SvtBroadcaster::Remove( SvtListener* p )
55 if (mbDisposing)
56 return;
58 if (mbAboutToDie)
60 maDestructedListeners.push_back(p);
61 mbDestNormalized = false;
62 return;
65 Normalize();
67 auto it = std::lower_bound(maListeners.begin(), maListeners.end(), p);
68 assert (it != maListeners.end() && *it == p);
69 if (it != maListeners.end() && *it == p)
71 maListeners.erase(it);
74 if (maListeners.empty())
75 ListenersGone();
78 SvtBroadcaster::SvtBroadcaster() : mbAboutToDie(false), mbDisposing(false), mbNormalized(true), mbDestNormalized(true) {}
80 SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC ) :
81 mbAboutToDie(false), mbDisposing(false),
82 mbNormalized(true), mbDestNormalized(true)
84 assert(!rBC.mbAboutToDie && "copying an object marked with PrepareForDestruction()?");
85 assert(!rBC.mbDisposing && "copying an object that is in it's destructor?");
87 rBC.Normalize(); // so that insert into ourself is in-order, and therefore we do not need to Normalize()
88 maListeners.reserve(rBC.maListeners.size());
89 for (SvtListener* p : rBC.maListeners)
90 p->StartListening(*this); // this will call back into this->Add()
93 SvtBroadcaster::~SvtBroadcaster()
95 mbDisposing = true;
96 Broadcast( SfxHint(SfxHintId::Dying) );
98 Normalize();
100 // now when both lists are sorted, we can linearly unregister all
101 // listeners, with the exception of those that already asked to be removed
102 // during their own destruction
103 ListenersType::const_iterator dest(maDestructedListeners.begin());
104 for (auto& rpListener : maListeners)
106 // skip the destructed ones
107 while (dest != maDestructedListeners.end() && (*dest < rpListener))
108 ++dest;
110 if (dest == maDestructedListeners.end() || *dest != rpListener)
111 rpListener->BroadcasterDying(*this);
115 void SvtBroadcaster::Broadcast( const SfxHint &rHint )
117 Normalize();
119 ListenersType::const_iterator dest(maDestructedListeners.begin());
120 ListenersType aListeners(maListeners); // this copy is important to avoid erasing entries while iterating
121 for (auto& rpListener : aListeners)
123 // skip the destructed ones
124 while (dest != maDestructedListeners.end() && (*dest < rpListener))
125 ++dest;
127 if (dest == maDestructedListeners.end() || *dest != rpListener)
128 rpListener->Notify(rHint);
132 void SvtBroadcaster::ListenersGone() {}
134 SvtBroadcaster::ListenersType& SvtBroadcaster::GetAllListeners()
136 Normalize();
137 return maListeners;
140 const SvtBroadcaster::ListenersType& SvtBroadcaster::GetAllListeners() const
142 Normalize();
143 return maListeners;
146 bool SvtBroadcaster::HasListeners() const
148 return !maListeners.empty();
151 void SvtBroadcaster::PrepareForDestruction()
153 mbAboutToDie = true;
154 // the reserve() serves two purpose (1) performance (2) makes sure our iterators do not become invalid
155 maDestructedListeners.reserve(maListeners.size());
158 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */