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 "debugtrace.hxx"
21 #include "ChangeRequestQueueProcessor.hxx"
22 #include "ConfigurationTracer.hxx"
23 
24 #include "ConfigurationUpdater.hxx"
25 
26 #include <vcl/svapp.hxx>
27 #include <sal/log.hxx>
28 #include <osl/diagnose.h>
29 #include <com/sun/star/container/XNamed.hpp>
30 #include <com/sun/star/drawing/framework/XConfigurationChangeRequest.hpp>
31 
32 using namespace ::com::sun::star;
33 using namespace ::com::sun::star::uno;
34 using namespace ::com::sun::star::drawing::framework;
35 
36 namespace {
37 
38 #if DEBUG_SD_CONFIGURATION_TRACE
39 
TraceRequest(const Reference<XConfigurationChangeRequest> & rxRequest)40 void TraceRequest (const Reference<XConfigurationChangeRequest>& rxRequest)
41 {
42     Reference<container::XNamed> xNamed (rxRequest, UNO_QUERY);
43     if (xNamed.is())
44         SAL_INFO("sd.fwk", OSL_THIS_FUNC << ":    " << xNamed->getName());
45 }
46 
47 #endif
48 
49 } // end of anonymous namespace
50 
51 namespace sd { namespace framework {
52 
ChangeRequestQueueProcessor(const std::shared_ptr<ConfigurationUpdater> & rpConfigurationUpdater)53 ChangeRequestQueueProcessor::ChangeRequestQueueProcessor (
54     const std::shared_ptr<ConfigurationUpdater>& rpConfigurationUpdater)
55     : maMutex(),
56       maQueue(),
57       mnUserEventId(nullptr),
58       mxConfiguration(),
59       mpConfigurationUpdater(rpConfigurationUpdater)
60 {
61 }
62 
~ChangeRequestQueueProcessor()63 ChangeRequestQueueProcessor::~ChangeRequestQueueProcessor()
64 {
65     if (mnUserEventId != nullptr)
66         Application::RemoveUserEvent(mnUserEventId);
67 }
68 
SetConfiguration(const Reference<XConfiguration> & rxConfiguration)69 void ChangeRequestQueueProcessor::SetConfiguration (
70     const Reference<XConfiguration>& rxConfiguration)
71 {
72     ::osl::MutexGuard aGuard (maMutex);
73 
74     mxConfiguration = rxConfiguration;
75     StartProcessing();
76 }
77 
AddRequest(const Reference<XConfigurationChangeRequest> & rxRequest)78 void ChangeRequestQueueProcessor::AddRequest (
79     const Reference<XConfigurationChangeRequest>& rxRequest)
80 {
81     ::osl::MutexGuard aGuard (maMutex);
82 
83 #if DEBUG_SD_CONFIGURATION_TRACE
84     if (maQueue.empty())
85     {
86         SAL_INFO("sd.fwk", OSL_THIS_FUNC << ": Adding requests to empty queue");
87         ConfigurationTracer::TraceConfiguration(
88             mxConfiguration, "current configuration of queue processor");
89     }
90     SAL_INFO("sd.fwk", OSL_THIS_FUNC << ": Adding request");
91     TraceRequest(rxRequest);
92 #endif
93 
94     maQueue.push(rxRequest);
95     StartProcessing();
96 }
97 
StartProcessing()98 void ChangeRequestQueueProcessor::StartProcessing()
99 {
100     ::osl::MutexGuard aGuard (maMutex);
101 
102     if (mnUserEventId == nullptr
103         && mxConfiguration.is()
104         && ! maQueue.empty())
105     {
106         SAL_INFO("sd.fwk", OSL_THIS_FUNC << ": ChangeRequestQueueProcessor scheduling processing");
107         mnUserEventId = Application::PostUserEvent(
108             LINK(this,ChangeRequestQueueProcessor,ProcessEvent));
109     }
110 }
111 
IMPL_LINK_NOARG(ChangeRequestQueueProcessor,ProcessEvent,void *,void)112 IMPL_LINK_NOARG(ChangeRequestQueueProcessor, ProcessEvent, void*, void)
113 {
114     ::osl::MutexGuard aGuard (maMutex);
115 
116     mnUserEventId = nullptr;
117 
118     ProcessOneEvent();
119 
120     if ( ! maQueue.empty())
121     {
122         // Schedule the processing of the next event.
123         StartProcessing();
124     }
125 }
126 
ProcessOneEvent()127 void ChangeRequestQueueProcessor::ProcessOneEvent()
128 {
129     ::osl::MutexGuard aGuard (maMutex);
130 
131     SAL_INFO("sd.fwk", OSL_THIS_FUNC << ": ProcessOneEvent");
132 
133     if (!mxConfiguration.is() || maQueue.empty())
134         return;
135 
136     // Get and remove the first entry from the queue.
137     Reference<XConfigurationChangeRequest> xRequest (maQueue.front());
138     maQueue.pop();
139 
140     // Execute the change request.
141     if (xRequest.is())
142     {
143 #if DEBUG_SD_CONFIGURATION_TRACE
144         TraceRequest(xRequest);
145 #endif
146         xRequest->execute(mxConfiguration);
147     }
148 
149     if (!maQueue.empty())
150         return;
151 
152     SAL_INFO("sd.fwk", OSL_THIS_FUNC << ": All requests are processed");
153     // The queue is empty so tell the ConfigurationManager to update
154     // its state.
155     if (mpConfigurationUpdater != nullptr)
156     {
157 #if DEBUG_SD_CONFIGURATION_TRACE
158         ConfigurationTracer::TraceConfiguration (
159             mxConfiguration, "updating to configuration");
160 #endif
161         mpConfigurationUpdater->RequestUpdate(mxConfiguration);
162     }
163 }
164 
IsEmpty() const165 bool ChangeRequestQueueProcessor::IsEmpty() const
166 {
167     return maQueue.empty();
168 }
169 
ProcessUntilEmpty()170 void ChangeRequestQueueProcessor::ProcessUntilEmpty()
171 {
172     while ( ! IsEmpty())
173         ProcessOneEvent();
174 }
175 
Clear()176 void ChangeRequestQueueProcessor::Clear()
177 {
178     ::osl::MutexGuard aGuard (maMutex);
179     ChangeRequestQueue aEmpty;
180     maQueue.swap(aEmpty);
181 }
182 
183 } } // end of namespace sd::framework::configuration
184 
185 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
186