1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sd.hxx"
26 
27 #include "tools/SdGlobalResourceContainer.hxx"
28 
29 #include <algorithm>
30 #include <vector>
31 
32 using namespace ::com::sun::star;
33 using namespace ::com::sun::star::uno;
34 
35 
36 namespace sd {
37 
38 
39 //===== SdGlobalResourceContainer::Implementation =============================
40 
41 class SdGlobalResourceContainer::Implementation
42 {
43 private:
44     friend class SdGlobalResourceContainer;
45     static SdGlobalResourceContainer* mpInstance;
46 
47 	::osl::Mutex maMutex;
48 
49     /** All instances of SdGlobalResource in this vector are owned by the
50         container and will be destroyed when the container is destroyed.
51     */
52     typedef ::std::vector<SdGlobalResource*> ResourceList;
53     ResourceList maResources;
54 
55     typedef ::std::vector<boost::shared_ptr<SdGlobalResource> > SharedResourceList;
56     SharedResourceList maSharedResources;
57 
58     typedef ::std::vector<Reference<XInterface> > XInterfaceResourceList;
59     XInterfaceResourceList maXInterfaceResources;
60 };
61 
62 
63 
64 
65 // static
Instance(void)66 SdGlobalResourceContainer& SdGlobalResourceContainer::Instance (void)
67 {
68     DBG_ASSERT(Implementation::mpInstance!=NULL,
69         "SdGlobalResourceContainer::Instance(): instance has been deleted");
70     // Maybe we should throw an exception when the instance has been deleted.
71     return *Implementation::mpInstance;
72 }
73 
74 SdGlobalResourceContainer*
75     SdGlobalResourceContainer::Implementation::mpInstance = NULL;
76 
77 
78 
79 
80 //===== SdGlobalResourceContainer =============================================
81 
AddResource(::std::auto_ptr<SdGlobalResource> pResource)82 void SdGlobalResourceContainer::AddResource (
83     ::std::auto_ptr<SdGlobalResource> pResource)
84 {
85     ::osl::MutexGuard aGuard (mpImpl->maMutex);
86 
87     Implementation::ResourceList::iterator iResource;
88     iResource = ::std::find (
89         mpImpl->maResources.begin(),
90         mpImpl->maResources.end(),
91         pResource.get());
92     if (iResource == mpImpl->maResources.end())
93         mpImpl->maResources.push_back(pResource.get());
94     else
95     {
96         // Because the given resource is an auto_ptr it is highly unlikely
97         // that we come here.  But who knows?
98         DBG_ASSERT (false,
99             "SdGlobalResourceContainer:AddResource(): Resource added twice.");
100     }
101     // We can not put the auto_ptr into the vector so we release the
102     // auto_ptr and document that we take ownership explicitly.
103     pResource.release();
104 }
105 
106 
107 
108 
AddResource(::boost::shared_ptr<SdGlobalResource> pResource)109 void SdGlobalResourceContainer::AddResource (
110     ::boost::shared_ptr<SdGlobalResource> pResource)
111 {
112     ::osl::MutexGuard aGuard (mpImpl->maMutex);
113 
114     Implementation::SharedResourceList::iterator iResource;
115     iResource = ::std::find (
116         mpImpl->maSharedResources.begin(),
117         mpImpl->maSharedResources.end(),
118         pResource);
119     if (iResource == mpImpl->maSharedResources.end())
120         mpImpl->maSharedResources.push_back(pResource);
121     else
122     {
123         DBG_ASSERT (false,
124             "SdGlobalResourceContainer:AddResource(): Resource added twice.");
125     }
126 }
127 
128 
129 
130 
AddResource(const Reference<XInterface> & rxResource)131 void SdGlobalResourceContainer::AddResource (const Reference<XInterface>& rxResource)
132 {
133     ::osl::MutexGuard aGuard (mpImpl->maMutex);
134 
135     Implementation::XInterfaceResourceList::iterator iResource;
136     iResource = ::std::find (
137         mpImpl->maXInterfaceResources.begin(),
138         mpImpl->maXInterfaceResources.end(),
139         rxResource);
140     if (iResource == mpImpl->maXInterfaceResources.end())
141         mpImpl->maXInterfaceResources.push_back(rxResource);
142     else
143     {
144         DBG_ASSERT (false,
145             "SdGlobalResourceContainer:AddResource(): Resource added twice.");
146     }
147 }
148 
149 
150 
SdGlobalResourceContainer(void)151 SdGlobalResourceContainer::SdGlobalResourceContainer (void)
152     : mpImpl (new SdGlobalResourceContainer::Implementation())
153 {
154     Implementation::mpInstance = this;
155 }
156 
157 
158 
159 
~SdGlobalResourceContainer(void)160 SdGlobalResourceContainer::~SdGlobalResourceContainer (void)
161 {
162     ::osl::MutexGuard aGuard (mpImpl->maMutex);
163 
164     // Release the resources in reversed order of their addition to the
165     // container.  This is because a resource A added before resource B
166     // may have been created due to a request of B.  Thus B depends on A and
167     // should be destroyed first.
168     Implementation::ResourceList::reverse_iterator iResource;
169     for (iResource = mpImpl->maResources.rbegin();
170          iResource != mpImpl->maResources.rend();
171          ++iResource)
172     {
173         delete *iResource;
174     }
175 
176     // The SharedResourceList has not to be released manually.  We just
177     // assert resources that are still held by someone other than us.
178     Implementation::SharedResourceList::reverse_iterator iSharedResource;
179     for (iSharedResource = mpImpl->maSharedResources.rbegin();
180          iSharedResource != mpImpl->maSharedResources.rend();
181          ++iSharedResource)
182     {
183         if ( ! iSharedResource->unique())
184         {
185             SdGlobalResource* pResource = iSharedResource->get();
186             OSL_TRACE(" %p %d", pResource, iSharedResource->use_count());
187             DBG_ASSERT(iSharedResource->unique(),
188                 "SdGlobalResource still held in ~SdGlobalResourceContainer");
189         }
190     }
191 
192     Implementation::XInterfaceResourceList::reverse_iterator iXInterfaceResource;
193     for (iXInterfaceResource = mpImpl->maXInterfaceResources.rbegin();
194          iXInterfaceResource != mpImpl->maXInterfaceResources.rend();
195          ++iXInterfaceResource)
196     {
197         Reference<lang::XComponent> xComponent (*iXInterfaceResource, UNO_QUERY);
198         *iXInterfaceResource = NULL;
199         if (xComponent.is())
200             xComponent->dispose();
201     }
202 
203     DBG_ASSERT(Implementation::mpInstance == this,
204         "~SdGlobalResourceContainer(): more than one instance of singleton");
205     Implementation::mpInstance = NULL;
206 }
207 
208 
209 
210 
211 } // end of namespace sd
212