/src/libreoffice/sd/source/ui/tools/SdGlobalResourceContainer.cxx
Line | Count | Source |
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 | | |
20 | | #include <tools/SdGlobalResourceContainer.hxx> |
21 | | |
22 | | #include <comphelper/processfactory.hxx> |
23 | | #include <comphelper/unique_disposing_ptr.hxx> |
24 | | |
25 | | #include <com/sun/star/frame/Desktop.hpp> |
26 | | |
27 | | #include <sal/log.hxx> |
28 | | #include <tools/debug.hxx> |
29 | | |
30 | | #include <algorithm> |
31 | | #include <memory> |
32 | | #include <mutex> |
33 | | #include <vector> |
34 | | |
35 | | using namespace ::com::sun::star; |
36 | | using namespace ::com::sun::star::uno; |
37 | | |
38 | | namespace sd { |
39 | | |
40 | | class SdGlobalResourceContainerInstance |
41 | | : public comphelper::unique_disposing_solar_mutex_reset_ptr<SdGlobalResourceContainer> |
42 | | { |
43 | | public: |
44 | | SdGlobalResourceContainerInstance() |
45 | 0 | : comphelper::unique_disposing_solar_mutex_reset_ptr<SdGlobalResourceContainer>( |
46 | 0 | uno::Reference<lang::XComponent>(frame::Desktop::create(comphelper::getProcessComponentContext()), uno::UNO_QUERY_THROW), |
47 | 0 | new SdGlobalResourceContainer, true) |
48 | 0 | { |
49 | 0 | } |
50 | | }; |
51 | | |
52 | | namespace { |
53 | | |
54 | | SdGlobalResourceContainerInstance& theSdGlobalResourceContainerInstance() |
55 | 0 | { |
56 | 0 | static SdGlobalResourceContainerInstance SINGLETON; |
57 | 0 | return SINGLETON; |
58 | 0 | } |
59 | | |
60 | | } // namespace |
61 | | |
62 | | //===== SdGlobalResourceContainer::Implementation ============================= |
63 | | |
64 | | class SdGlobalResourceContainer::Implementation |
65 | | { |
66 | | private: |
67 | | friend class SdGlobalResourceContainer; |
68 | | |
69 | | std::mutex maMutex; |
70 | | |
71 | | /** All instances of SdGlobalResource in this vector are owned by the |
72 | | container and will be destroyed when the container is destroyed. |
73 | | */ |
74 | | std::vector<std::unique_ptr<SdGlobalResource>> maResources; |
75 | | |
76 | | typedef ::std::vector<std::shared_ptr<SdGlobalResource> > SharedResourceList; |
77 | | SharedResourceList maSharedResources; |
78 | | |
79 | | typedef ::std::vector<Reference<XInterface> > XInterfaceResourceList; |
80 | | XInterfaceResourceList maXInterfaceResources; |
81 | | }; |
82 | | |
83 | | // static |
84 | | SdGlobalResourceContainer& SdGlobalResourceContainer::Instance() |
85 | 0 | { |
86 | 0 | SdGlobalResourceContainer *const pRet(theSdGlobalResourceContainerInstance().get()); |
87 | 0 | assert(pRet); // error if it has been deleted and is null |
88 | 0 | return *pRet; |
89 | 0 | } |
90 | | |
91 | | //===== SdGlobalResourceContainer ============================================= |
92 | | |
93 | | void SdGlobalResourceContainer::AddResource ( |
94 | | ::std::unique_ptr<SdGlobalResource> pResource) |
95 | 0 | { |
96 | 0 | std::unique_lock aGuard (mpImpl->maMutex); |
97 | |
|
98 | 0 | assert( std::none_of( |
99 | 0 | mpImpl->maResources.begin(), |
100 | 0 | mpImpl->maResources.end(), |
101 | 0 | [&](const std::unique_ptr<SdGlobalResource>& p) { return p == pResource; }) |
102 | 0 | && "duplicate resource?"); |
103 | |
|
104 | 0 | mpImpl->maResources.push_back(std::move(pResource)); |
105 | 0 | } |
106 | | |
107 | | void SdGlobalResourceContainer::AddResource ( |
108 | | const std::shared_ptr<SdGlobalResource>& pResource) |
109 | 0 | { |
110 | 0 | std::unique_lock aGuard (mpImpl->maMutex); |
111 | |
|
112 | 0 | Implementation::SharedResourceList::iterator iResource = ::std::find ( |
113 | 0 | mpImpl->maSharedResources.begin(), |
114 | 0 | mpImpl->maSharedResources.end(), |
115 | 0 | pResource); |
116 | 0 | if (iResource == mpImpl->maSharedResources.end()) |
117 | 0 | mpImpl->maSharedResources.push_back(pResource); |
118 | 0 | else |
119 | 0 | { |
120 | 0 | SAL_WARN ("sd.tools", |
121 | 0 | "SdGlobalResourceContainer:AddResource(): Resource added twice."); |
122 | 0 | } |
123 | 0 | } |
124 | | |
125 | | void SdGlobalResourceContainer::AddResource (const Reference<XInterface>& rxResource) |
126 | 0 | { |
127 | 0 | std::unique_lock aGuard (mpImpl->maMutex); |
128 | |
|
129 | 0 | Implementation::XInterfaceResourceList::iterator iResource = ::std::find ( |
130 | 0 | mpImpl->maXInterfaceResources.begin(), |
131 | 0 | mpImpl->maXInterfaceResources.end(), |
132 | 0 | rxResource); |
133 | 0 | if (iResource == mpImpl->maXInterfaceResources.end()) |
134 | 0 | mpImpl->maXInterfaceResources.push_back(rxResource); |
135 | 0 | else |
136 | 0 | { |
137 | 0 | SAL_WARN ("sd.tools", |
138 | 0 | "SdGlobalResourceContainer:AddResource(): Resource added twice."); |
139 | 0 | } |
140 | 0 | } |
141 | | |
142 | | SdGlobalResourceContainer::SdGlobalResourceContainer() |
143 | 0 | : mpImpl (new SdGlobalResourceContainer::Implementation) |
144 | 0 | { |
145 | 0 | } |
146 | | |
147 | | SdGlobalResourceContainer::~SdGlobalResourceContainer() |
148 | 0 | { |
149 | 0 | std::unique_lock aGuard (mpImpl->maMutex); |
150 | | |
151 | | // Release the resources in reversed order of their addition to the |
152 | | // container. This is because a resource A added before resource B |
153 | | // may have been created due to a request of B. Thus B depends on A and |
154 | | // should be destroyed first. |
155 | 0 | for (auto iResource = mpImpl->maResources.rbegin(); |
156 | 0 | iResource != mpImpl->maResources.rend(); |
157 | 0 | ++iResource) |
158 | 0 | { |
159 | 0 | iResource->reset(); |
160 | 0 | } |
161 | | |
162 | | |
163 | | // The SharedResourceList has not to be released manually. We just |
164 | | // assert resources that are still held by someone other than us. |
165 | 0 | Implementation::SharedResourceList::reverse_iterator iSharedResource; |
166 | 0 | for (iSharedResource = mpImpl->maSharedResources.rbegin(); |
167 | 0 | iSharedResource != mpImpl->maSharedResources.rend(); |
168 | 0 | ++iSharedResource) |
169 | 0 | { |
170 | 0 | if (iSharedResource->use_count() > 1) |
171 | 0 | { |
172 | 0 | SdGlobalResource* pResource = iSharedResource->get(); |
173 | 0 | SAL_INFO( |
174 | 0 | "sd.tools", pResource << " " << iSharedResource->use_count()); |
175 | 0 | DBG_ASSERT(iSharedResource->use_count() == 1, |
176 | 0 | "SdGlobalResource still held in ~SdGlobalResourceContainer"); |
177 | 0 | } |
178 | 0 | } |
179 | | |
180 | 0 | Implementation::XInterfaceResourceList::reverse_iterator iXInterfaceResource; |
181 | 0 | for (iXInterfaceResource = mpImpl->maXInterfaceResources.rbegin(); |
182 | 0 | iXInterfaceResource != mpImpl->maXInterfaceResources.rend(); |
183 | 0 | ++iXInterfaceResource) |
184 | 0 | { |
185 | 0 | Reference<lang::XComponent> xComponent (*iXInterfaceResource, UNO_QUERY); |
186 | 0 | *iXInterfaceResource = nullptr; |
187 | 0 | if (xComponent.is()) |
188 | 0 | xComponent->dispose(); |
189 | 0 | } |
190 | 0 | } |
191 | | |
192 | | } // end of namespace sd |
193 | | |
194 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |