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