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 #ifndef INCLUDED_COMPHELPER_ASYNCNOTIFICATION_HXX
21 #define INCLUDED_COMPHELPER_ASYNCNOTIFICATION_HXX
23 #include <sal/config.h>
25 #include <comphelper/comphelperdllapi.h>
26 #include <rtl/ref.hxx>
27 #include <sal/types.h>
28 #include <salhelper/thread.hxx>
29 #include <salhelper/simplereferenceobject.hxx>
37 /** the very basic instance to hold a description of an event
39 class COMPHELPER_DLLPUBLIC AnyEvent
: public salhelper::SimpleReferenceObject
45 virtual ~AnyEvent() override
;
48 AnyEvent( AnyEvent
const & ) = delete;
49 AnyEvent
& operator=( AnyEvent
const & ) = delete;
55 typedef ::rtl::Reference
< AnyEvent
> AnyEventRef
;
60 /** an event processor
62 @see AsyncEventNotifier
64 class SAL_NO_VTABLE IEventProcessor
67 /** process a single event
69 virtual void processEvent( const AnyEvent
& _rEvent
) = 0;
71 virtual void SAL_CALL
acquire() noexcept
= 0;
72 virtual void SAL_CALL
release() noexcept
= 0;
79 //= AsyncEventNotifier
81 struct EventNotifierImpl
;
83 /** a helper class for notifying events asynchronously
85 If you need to notify certain events to external components, you usually should
86 not do this while you have mutexes locked, to prevent multi-threading issues.
88 However, you do not always have complete control over all mutex guards on the stack.
89 If, in such a case, the listener notification is one-way, you can decide to do it
92 The ->AsyncEventNotifier helps you to process such events asynchronously. Every
93 event is tied to an ->IEventProcessor which is responsible for processing it.
95 The AsyncEventNotifier is implemented as a thread itself, which sleeps as long as there are no
96 events in the queue. As soon as you add an event, the thread is woken up, processes the event,
99 class COMPHELPER_DLLPUBLIC AsyncEventNotifierBase
101 friend struct EventNotifierImpl
;
104 std::unique_ptr
<EventNotifierImpl
> m_xImpl
;
106 SAL_DLLPRIVATE
virtual ~AsyncEventNotifierBase();
109 SAL_DLLPRIVATE
virtual void execute();
112 AsyncEventNotifierBase();
114 /** terminates the thread
116 Note that this is a cooperative termination - if you call this from a thread different
117 from the notification thread itself, then it will block until the notification thread
118 finished processing the current event. If you call it from the notification thread
119 itself, it will return immediately, and the thread will be terminated as soon as
120 the current notification is finished.
122 virtual void SAL_CALL
terminate();
124 /** adds an event to the queue, together with the instance which is responsible for
128 the event to add to the queue
130 the processor for the event.<br/>
131 Beware of life time issues here. If your event processor dies or becomes otherwise
132 nonfunctional, you are responsible for removing all respective events from the queue.
133 You can do this by calling ->removeEventsForProcessor
135 void addEvent( const AnyEventRef
& _rEvent
, const ::rtl::Reference
< IEventProcessor
>& _xProcessor
);
137 /** removes all events for the given event processor from the queue
139 void removeEventsForProcessor( const ::rtl::Reference
< IEventProcessor
>& _xProcessor
);
142 /** This class is usable with rtl::Reference.
143 As always, the thread must be joined somewhere.
145 class COMPHELPER_DLLPUBLIC AsyncEventNotifier final
146 : public AsyncEventNotifierBase
147 , public salhelper::Thread
151 SAL_DLLPRIVATE
virtual ~AsyncEventNotifier() override
;
153 SAL_DLLPRIVATE
virtual void execute() override
;
156 /** constructs a notifier thread
158 @param name the thread name, see ::osl_setThreadName; must not be
161 AsyncEventNotifier(char const* name
);
163 virtual void SAL_CALL
terminate() override
;
166 /** This is a hack (when proper joining is not possible), use of which
167 should be avoided by good design.
169 class COMPHELPER_DLLPUBLIC AsyncEventNotifierAutoJoin final
170 : public AsyncEventNotifierBase
171 , private osl::Thread
175 SAL_DLLPRIVATE
AsyncEventNotifierAutoJoin(char const* name
);
177 SAL_DLLPRIVATE
virtual void SAL_CALL
run() override
;
178 SAL_DLLPRIVATE
virtual void SAL_CALL
onTerminated() override
;
181 // only public so shared_ptr finds it
182 SAL_DLLPRIVATE
virtual ~AsyncEventNotifierAutoJoin() override
;
184 static std::shared_ptr
<AsyncEventNotifierAutoJoin
>
185 newAsyncEventNotifierAutoJoin(char const* name
);
187 virtual void SAL_CALL
terminate() override
;
189 using osl::Thread::join
;
190 using osl::Thread::operator new;
191 using osl::Thread::operator delete; // clang really wants this?
193 static void launch(std::shared_ptr
<AsyncEventNotifierAutoJoin
> const&);
199 /** AnyEvent derivee holding a foreign event instance
201 template < typename EVENT_OBJECT
>
202 class SAL_DLLPUBLIC_RTTI EventHolder final
: public AnyEvent
205 typedef EVENT_OBJECT EventObjectType
;
208 EventObjectType
const m_aEvent
;
211 EventHolder( EventObjectType _aEvent
)
212 :m_aEvent(std::move( _aEvent
))
216 const EventObjectType
& getEventObject() const { return m_aEvent
; }
219 COMPHELPER_DLLPUBLIC
void JoinAsyncEventNotifiers();
221 } // namespace comphelper
224 #endif // INCLUDED_COMPHELPER_ASYNCNOTIFICATION_HXX
226 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */