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>
26 #include <osl/diagnose.h>
28 using namespace ::com::sun::star
;
30 typedef std::vector
< ::rtl::Reference
<IMailDispatcherListener
> > MailDispatcherListenerContainer_t
;
32 namespace /* private */
34 class MailDeliveryNotifier
37 MailDeliveryNotifier(uno::Reference
<mail::XMailMessage
> const & message
) :
41 void operator() (::rtl::Reference
<IMailDispatcherListener
> const & listener
) const
42 { listener
->mailDelivered(message_
); }
45 uno::Reference
<mail::XMailMessage
> message_
;
48 class MailDeliveryErrorNotifier
51 MailDeliveryErrorNotifier(
52 ::rtl::Reference
<MailDispatcher
> const & xMailDispatcher
,
53 uno::Reference
<mail::XMailMessage
> const & message
,
54 const OUString
& error_message
) :
55 mail_dispatcher_(xMailDispatcher
),
57 error_message_(error_message
)
60 void operator() (::rtl::Reference
<IMailDispatcherListener
> const & listener
) const
61 { listener
->mailDeliveryError(mail_dispatcher_
, message_
, error_message_
); }
64 ::rtl::Reference
<MailDispatcher
> mail_dispatcher_
;
65 uno::Reference
<mail::XMailMessage
> message_
;
66 OUString error_message_
;
69 } // namespace private
71 MailDispatcher::MailDispatcher(uno::Reference
<mail::XSmtpService
> const & mailserver
) :
72 m_xMailserver( mailserver
),
74 m_bShutdownRequested( false )
76 m_aWakeupCondition
.reset();
77 m_aRunCondition
.reset();
80 throw uno::RuntimeException();
82 // wait until the mail dispatcher thread is really alive
83 // and has acquired a reference to this instance of the
85 m_aRunCondition
.wait();
88 MailDispatcher::~MailDispatcher()
92 void MailDispatcher::enqueueMailMessage(uno::Reference
<mail::XMailMessage
> const & message
)
94 ::osl::MutexGuard
thread_status_guard( m_aThreadStatusMutex
);
95 ::osl::MutexGuard
message_container_guard( m_aMessageContainerMutex
);
97 OSL_PRECOND( !m_bShutdownRequested
, "MailDispatcher thread is shutting down already" );
99 m_aXMessageList
.push_back( message
);
101 m_aWakeupCondition
.set();
104 uno::Reference
<mail::XMailMessage
> MailDispatcher::dequeueMailMessage()
106 ::osl::MutexGuard
guard( m_aMessageContainerMutex
);
107 uno::Reference
<mail::XMailMessage
> message
;
108 if ( !m_aXMessageList
.empty() )
110 message
= m_aXMessageList
.front();
111 m_aXMessageList
.pop_front();
116 void MailDispatcher::start()
118 OSL_PRECOND(!isStarted(), "MailDispatcher is already started!");
120 ::osl::ClearableMutexGuard
thread_status_guard( m_aThreadStatusMutex
);
122 OSL_PRECOND(!m_bShutdownRequested
, "MailDispatcher thread is shutting down already");
124 if ( !m_bShutdownRequested
)
127 m_aWakeupCondition
.set();
128 thread_status_guard
.clear();
132 void MailDispatcher::stop()
134 OSL_PRECOND(isStarted(), "MailDispatcher not started!");
136 ::osl::ClearableMutexGuard
thread_status_guard( m_aThreadStatusMutex
);
138 OSL_PRECOND(!m_bShutdownRequested
, "MailDispatcher thread is shutting down already");
140 if (!m_bShutdownRequested
)
143 m_aWakeupCondition
.reset();
144 thread_status_guard
.clear();
148 void MailDispatcher::shutdown()
150 ::osl::MutexGuard
thread_status_guard( m_aThreadStatusMutex
);
152 OSL_PRECOND(!m_bShutdownRequested
, "MailDispatcher thread is shutting down already");
154 m_bShutdownRequested
= true;
155 m_aWakeupCondition
.set();
159 void MailDispatcher::addListener(::rtl::Reference
<IMailDispatcherListener
> const & listener
)
161 OSL_PRECOND(!m_bShutdownRequested
, "MailDispatcher thread is shutting down already");
163 ::osl::MutexGuard
guard( m_aListenerContainerMutex
);
164 m_aListenerVector
.push_back( listener
);
167 std::vector
< ::rtl::Reference
<IMailDispatcherListener
> > MailDispatcher::cloneListener()
169 ::osl::MutexGuard
guard( m_aListenerContainerMutex
);
170 return m_aListenerVector
;
173 void MailDispatcher::sendMailMessageNotifyListener(uno::Reference
<mail::XMailMessage
> const & message
)
177 m_xMailserver
->sendMailMessage( message
);
178 MailDispatcherListenerContainer_t
aClonedListenerVector(cloneListener());
179 std::for_each( aClonedListenerVector
.begin(), aClonedListenerVector
.end(),
180 MailDeliveryNotifier(message
) );
182 catch (const mail::MailException
& ex
)
184 MailDispatcherListenerContainer_t
aClonedListenerVector(cloneListener());
185 std::for_each( aClonedListenerVector
.begin(), aClonedListenerVector
.end(),
186 MailDeliveryErrorNotifier(this, message
, ex
.Message
) );
188 catch (const uno::RuntimeException
& ex
)
190 MailDispatcherListenerContainer_t
aClonedListenerVector(cloneListener());
191 std::for_each( aClonedListenerVector
.begin(), aClonedListenerVector
.end(),
192 MailDeliveryErrorNotifier(this, message
, ex
.Message
) );
196 void MailDispatcher::run()
198 osl_setThreadName("MailDispatcher");
200 // acquire a self reference in order to avoid race
201 // conditions. The last client of this class must
202 // call shutdown before releasing his last reference
203 // to this class in order to shutdown this thread
204 // which will release his (the very last reference
205 // to the class and so force their destruction
206 m_xSelfReference
= this;
208 // signal that the mail dispatcher thread is now alive
209 m_aRunCondition
.set();
213 m_aWakeupCondition
.wait();
215 ::osl::ClearableMutexGuard
thread_status_guard( m_aThreadStatusMutex
);
216 if ( m_bShutdownRequested
)
219 ::osl::ClearableMutexGuard
message_container_guard( m_aMessageContainerMutex
);
221 if ( !m_aXMessageList
.empty() )
223 thread_status_guard
.clear();
224 uno::Reference
<mail::XMailMessage
> message
= m_aXMessageList
.front();
225 m_aXMessageList
.pop_front();
226 message_container_guard
.clear();
227 sendMailMessageNotifyListener( message
);
229 else // idle - put ourself to sleep
231 m_aWakeupCondition
.reset();
232 message_container_guard
.clear();
233 thread_status_guard
.clear();
234 MailDispatcherListenerContainer_t
aListenerListcloned( cloneListener() );
235 for( const auto & l
: aListenerListcloned
)
241 void MailDispatcher::onTerminated()
243 //keep the reference until the end of onTerminated() because of the call order in the
244 //_threadFunc() from osl/thread.hxx
245 m_xSelfReference
= nullptr;
248 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */