Line data Source code
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 : #ifndef INCLUDED_COMPHELPER_ASYNCNOTIFICATION_HXX
21 : #define INCLUDED_COMPHELPER_ASYNCNOTIFICATION_HXX
22 :
23 : #include <sal/config.h>
24 :
25 : #include <boost/scoped_ptr.hpp>
26 : #include <comphelper/comphelperdllapi.h>
27 : #include <rtl/ref.hxx>
28 : #include <sal/types.h>
29 : #include <salhelper/thread.hxx>
30 :
31 :
32 : namespace comphelper
33 : {
34 :
35 :
36 :
37 : //= AnyEvent
38 :
39 : /** the very basic instance to hold a description of an event
40 : */
41 : class COMPHELPER_DLLPUBLIC AnyEvent : ::rtl::IReference
42 : {
43 : private:
44 : oslInterlockedCount m_refCount;
45 :
46 : public:
47 : AnyEvent();
48 :
49 : virtual oslInterlockedCount SAL_CALL acquire() SAL_OVERRIDE;
50 : virtual oslInterlockedCount SAL_CALL release() SAL_OVERRIDE;
51 :
52 : protected:
53 : virtual ~AnyEvent();
54 :
55 : private:
56 : AnyEvent( AnyEvent& ); // not defined
57 : void operator=( AnyEvent& ); // not defined
58 : };
59 :
60 :
61 : //= typedefs
62 :
63 : typedef ::rtl::Reference< AnyEvent > AnyEventRef;
64 :
65 :
66 : //= IEventProcessor
67 :
68 : /** an event processor
69 :
70 : @see AsyncEventNotifier
71 : */
72 0 : class SAL_NO_VTABLE IEventProcessor
73 : {
74 : public:
75 : /** process a single event
76 : */
77 : virtual void processEvent( const AnyEvent& _rEvent ) = 0;
78 :
79 : virtual void SAL_CALL acquire() throw () = 0;
80 : virtual void SAL_CALL release() throw () = 0;
81 :
82 : protected:
83 0 : ~IEventProcessor() {}
84 : };
85 :
86 :
87 : //= AsyncEventNotifier
88 :
89 : struct EventNotifierImpl;
90 :
91 : /** a helper class for notifying events asynchronously
92 :
93 : If you need to notify certain events to external components, you usually should
94 : not do this while you have mutexes locked, to prevent multi-threading issues.
95 :
96 : However, you do not always have complete control over all mutex guards on the stack.
97 : If, in such a case, the listener notification is one-way, you can decide to do it
98 : asynchronously.
99 :
100 : The ->AsyncEventNotifier helps you to process such events asynchronously. Every
101 : event is tied to an ->IEventProcessor which is responsible for processing it.
102 :
103 : The AsyncEventNotifier is implemented as a thread itself, which sleeps as long as there are no
104 : events in the queue. As soon as you add an event, the thread is woken up, processes the event,
105 : and sleeps again.
106 : */
107 : class COMPHELPER_DLLPUBLIC AsyncEventNotifier: public salhelper::Thread
108 : {
109 : friend struct EventNotifierImpl;
110 :
111 : private:
112 : boost::scoped_ptr< EventNotifierImpl > m_pImpl;
113 :
114 : SAL_DLLPRIVATE virtual ~AsyncEventNotifier();
115 :
116 : // Thread
117 : SAL_DLLPRIVATE virtual void execute() SAL_OVERRIDE;
118 :
119 : public:
120 : /** constructs a notifier thread
121 :
122 : @param name the thread name, see ::osl_setThreadName; must not be
123 : null
124 : */
125 : AsyncEventNotifier(char const * name);
126 :
127 : /** terminates the thread
128 :
129 : Note that this is a cooporative termination - if you call this from a thread different
130 : from the notification thread itself, then it will block until the notification thread
131 : finished processing the current event. If you call it from the notification thread
132 : itself, it will return immediately, and the thread will be terminated as soon as
133 : the current notification is finished.
134 : */
135 : virtual void SAL_CALL terminate() SAL_OVERRIDE;
136 :
137 : /** adds an event to the queue, together with the instance which is responsible for
138 : processing it
139 :
140 : @param _rEvent
141 : the event to add to the queue
142 : @param _xProcessor
143 : the processor for the event.<br/>
144 : Beware of life time issues here. If your event processor dies or becomes otherwise
145 : nonfunctional, you are responsible for removing all respective events from the queue.
146 : You can do this by calling ->removeEventsForProcessor
147 : */
148 : void addEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor );
149 :
150 : /** removes all events for the given event processor from the queue
151 : */
152 : void removeEventsForProcessor( const ::rtl::Reference< IEventProcessor >& _xProcessor );
153 : };
154 :
155 :
156 : //= EventHolder
157 :
158 : /** AnyEvent derivee holding an foreign event instance
159 : */
160 : template < typename EVENT_OBJECT >
161 0 : class EventHolder : public AnyEvent
162 : {
163 : public:
164 : typedef EVENT_OBJECT EventObjectType;
165 :
166 : private:
167 : EventObjectType m_aEvent;
168 :
169 : public:
170 0 : inline EventHolder( const EventObjectType& _rEvent )
171 0 : :m_aEvent( _rEvent )
172 : {
173 0 : }
174 :
175 0 : inline const EventObjectType& getEventObject() const { return m_aEvent; }
176 : };
177 :
178 :
179 : } // namespace comphelper
180 :
181 :
182 : #endif // INCLUDED_COMPHELPER_ASYNCNOTIFICATION_HXX
183 :
184 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|