1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <maildispatcher.hxx>
21 #include <imaildsplistener.hxx>
25 #include <com/sun/star/mail/MailException.hpp>
27 #include <osl/diagnose.h>
29 using namespace ::com::sun::star
;
31 typedef std::vector
< ::rtl::Reference
<IMailDispatcherListener
> > MailDispatcherListenerContainer_t
;
33 namespace /* private */
35 class MailDeliveryNotifier
38 MailDeliveryNotifier(uno::Reference
<mail::XMailMessage
> message
) :
39 message_(std::move(message
))
42 void operator() (::rtl::Reference
<IMailDispatcherListener
> const & listener
) const
43 { listener
->mailDelivered(message_
); }
46 uno::Reference
<mail::XMailMessage
> message_
;
49 class MailDeliveryErrorNotifier
52 MailDeliveryErrorNotifier(
53 ::rtl::Reference
<MailDispatcher
> xMailDispatcher
,
54 uno::Reference
<mail::XMailMessage
> message
,
55 OUString error_message
) :
56 m_mail_dispatcher(std::move(xMailDispatcher
)),
57 m_message(std::move(message
)),
58 m_error_message(std::move(error_message
))
61 void operator() (::rtl::Reference
<IMailDispatcherListener
> const & listener
) const
62 { listener
->mailDeliveryError(m_mail_dispatcher
, m_message
, m_error_message
); }
65 ::rtl::Reference
<MailDispatcher
> m_mail_dispatcher
;
66 uno::Reference
<mail::XMailMessage
> m_message
;
67 OUString m_error_message
;
70 } // namespace private
72 MailDispatcher::MailDispatcher(uno::Reference
<mail::XSmtpService
> mailserver
) :
73 m_xMailserver(std::move( mailserver
)),
75 m_bShutdownRequested( false )
77 m_aWakeupCondition
.reset();
78 m_aRunCondition
.reset();
81 throw uno::RuntimeException();
83 // wait until the mail dispatcher thread is really alive
84 // and has acquired a reference to this instance of the
86 m_aRunCondition
.wait();
89 MailDispatcher::~MailDispatcher()
93 void MailDispatcher::enqueueMailMessage(uno::Reference
<mail::XMailMessage
> const & message
)
95 ::osl::MutexGuard
thread_status_guard( m_aThreadStatusMutex
);
96 ::osl::MutexGuard
message_container_guard( m_aMessageContainerMutex
);
98 OSL_PRECOND( !m_bShutdownRequested
, "MailDispatcher thread is shutting down already" );
100 m_aXMessageList
.push_back( message
);
102 m_aWakeupCondition
.set();
105 uno::Reference
<mail::XMailMessage
> MailDispatcher::dequeueMailMessage()
107 ::osl::MutexGuard
guard( m_aMessageContainerMutex
);
108 uno::Reference
<mail::XMailMessage
> message
;
109 if ( !m_aXMessageList
.empty() )
111 message
= m_aXMessageList
.front();
112 m_aXMessageList
.pop_front();
117 void MailDispatcher::start()
119 OSL_PRECOND(!isStarted(), "MailDispatcher is already started!");
121 ::osl::ClearableMutexGuard
thread_status_guard( m_aThreadStatusMutex
);
123 OSL_PRECOND(!m_bShutdownRequested
, "MailDispatcher thread is shutting down already");
125 if ( !m_bShutdownRequested
)
128 m_aWakeupCondition
.set();
129 thread_status_guard
.clear();
133 void MailDispatcher::stop()
135 OSL_PRECOND(isStarted(), "MailDispatcher not started!");
137 ::osl::ClearableMutexGuard
thread_status_guard( m_aThreadStatusMutex
);
139 OSL_PRECOND(!m_bShutdownRequested
, "MailDispatcher thread is shutting down already");
141 if (!m_bShutdownRequested
)
144 m_aWakeupCondition
.reset();
145 thread_status_guard
.clear();
149 void MailDispatcher::shutdown()
151 ::osl::MutexGuard
thread_status_guard( m_aThreadStatusMutex
);
153 OSL_PRECOND(!m_bShutdownRequested
, "MailDispatcher thread is shutting down already");
155 m_bShutdownRequested
= true;
156 m_aWakeupCondition
.set();
160 void MailDispatcher::addListener(::rtl::Reference
<IMailDispatcherListener
> const & listener
)
162 OSL_PRECOND(!m_bShutdownRequested
, "MailDispatcher thread is shutting down already");
164 ::osl::MutexGuard
guard( m_aListenerContainerMutex
);
165 m_aListenerVector
.push_back( listener
);
168 std::vector
< ::rtl::Reference
<IMailDispatcherListener
> > MailDispatcher::cloneListener()
170 ::osl::MutexGuard
guard( m_aListenerContainerMutex
);
171 return m_aListenerVector
;
174 void MailDispatcher::sendMailMessageNotifyListener(uno::Reference
<mail::XMailMessage
> const & message
)
178 m_xMailserver
->sendMailMessage( message
);
179 MailDispatcherListenerContainer_t
aClonedListenerVector(cloneListener());
180 std::for_each( aClonedListenerVector
.begin(), aClonedListenerVector
.end(),
181 MailDeliveryNotifier(message
) );
183 catch (const mail::MailException
& ex
)
185 MailDispatcherListenerContainer_t
aClonedListenerVector(cloneListener());
186 std::for_each( aClonedListenerVector
.begin(), aClonedListenerVector
.end(),
187 MailDeliveryErrorNotifier(this, message
, ex
.Message
) );
189 catch (const uno::RuntimeException
& ex
)
191 MailDispatcherListenerContainer_t
aClonedListenerVector(cloneListener());
192 std::for_each( aClonedListenerVector
.begin(), aClonedListenerVector
.end(),
193 MailDeliveryErrorNotifier(this, message
, ex
.Message
) );
197 void MailDispatcher::run()
199 osl_setThreadName("MailDispatcher");
201 // acquire a self reference in order to avoid race
202 // conditions. The last client of this class must
203 // call shutdown before releasing his last reference
204 // to this class in order to shutdown this thread
205 // which will release his (the very last reference
206 // to the class and so force their destruction
207 m_xSelfReference
= this;
209 // signal that the mail dispatcher thread is now alive
210 m_aRunCondition
.set();
214 m_aWakeupCondition
.wait();
216 ::osl::ClearableMutexGuard
thread_status_guard( m_aThreadStatusMutex
);
217 if ( m_bShutdownRequested
)
220 ::osl::ClearableMutexGuard
message_container_guard( m_aMessageContainerMutex
);
222 if ( !m_aXMessageList
.empty() )
224 thread_status_guard
.clear();
225 uno::Reference
<mail::XMailMessage
> message
= m_aXMessageList
.front();
226 m_aXMessageList
.pop_front();
227 message_container_guard
.clear();
228 sendMailMessageNotifyListener( message
);
230 else // idle - put ourself to sleep
232 m_aWakeupCondition
.reset();
233 message_container_guard
.clear();
234 thread_status_guard
.clear();
235 MailDispatcherListenerContainer_t
aListenerListcloned( cloneListener() );
236 for( const auto & l
: aListenerListcloned
)
242 void MailDispatcher::onTerminated()
244 //keep the reference until the end of onTerminated() because of the call order in the
245 //_threadFunc() from osl/thread.hxx
246 m_xSelfReference
= nullptr;
249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */