libzypp 17.37.17
signals.h
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\----------------------------------------------------------------------/
9*
10* This file contains private API, this might break at any time between releases.
11* You have been warned!
12*
13*/
14#ifndef ZYPP_NG_BASE_SIGNALS_H_INCLUDED
15#define ZYPP_NG_BASE_SIGNALS_H_INCLUDED
16
17#ifdef ENABLE_SYWU
18#include <sywu/signal.hpp>
19#else
20#include <sigc++/trackable.h>
21#include <sigc++/signal.h>
22#include <sigc++/connection.h>
23#include <sigc++/visit_each.h>
24#include <sigc++/adaptors/adaptors.h>
25#endif
26#include <memory>
27#include <utility>
28#include <cassert>
31
143namespace zyppng {
144
145
150 template <class R, class... T>
151 class Signal;
152
159 template <class SignalHost, typename ReturnType, typename... Arguments>
161
162 class Base;
163 class BasePrivate;
164
165#ifdef ENABLE_SYWU
166 using connection = sywu::Connection;
167
168 template <class R, class... T>
169 using SignalProxyBase = sywu::SignalConceptImpl<R(T...)>;
170
171 template <class R, class... T>
172 class Signal<R(T...)> : public sywu::Signal<R(T...)>
173 { };
174
175 template <class SignalHost, typename ReturnType, typename... Arguments>
176 class MemSignal<SignalHost, ReturnType(Arguments...)> : public sywu::MemberSignal<SignalHost, ReturnType(Arguments...)>
177 { };
178
179#else
180 using connection = sigc::connection;
181 using trackable = sigc::trackable;
182 using sigc::track_obj;
183
184 template <class R, class... T>
185 using SignalProxyBase = sigc::signal<R(T...)>;
186
187
188 template <class R, class... T>
189 class Signal<R(T...)> : public sigc::signal<R(T...)>
190 {
191 public:
193 assert(this->impl()->exec_count_ == 0);
194 if ( this->impl()->exec_count_ > 0 ) {
195 WAR << "Deleting Signal during emission, this is usually a BUG, Slots will be blocked to prevent SIGSEGV." << std::endl;
196#ifdef LIBZYPP_USE_SIGC_BLOCK_WORKAROUND
197 // older sigc versions will segfault if clear() is called in signal emission
198 // we use block instead in those cases which seems to have the same result
199 // since we do not use the slot instances explicitely that _should_ not have side effects
200 // https://bugzilla.gnome.org/show_bug.cgi?id=784550
201 this->block();
202 return;
203#endif
204 }
205
206 this->clear();
207 }
208 };
209
210 template <class SignalHost, typename ReturnType, typename... Arguments>
211 class MemSignal<SignalHost, ReturnType(Arguments...)> : public sigc::signal<ReturnType(Arguments...)>
212 {
213 public:
214 MemSignal ( SignalHost &host ) : _host(host) {}
215
217
218 assert(this->impl()->exec_count_ == 0);
219 if ( this->impl()->exec_count_ > 0 ) {
220 WAR << "Deleting MemSignal during emission, this is definitely a BUG, Slots will be blocked to prevent SIGSEGV." << std::endl;
221#ifdef LIBZYPP_USE_SIGC_BLOCK_WORKAROUND
222 // older sigc versions will segfault if clear() is called in signal emission
223 // we use block instead in those cases which seems to have the same result
224 // since we do not use the slot instances explicitely that _should_ not have side effects
225 // https://bugzilla.gnome.org/show_bug.cgi?id=784550
226 this->block();
227 return;
228#endif
229 }
230 this->clear();
231 }
232
233 template<typename... Args>
234 auto emit( Args&& ...arg ) const {
235 auto ref = _host.shared_from_this();
236 return sigc::signal<ReturnType(Arguments...)>::emit( std::forward<Args>(arg)...);
237 }
238
239 template<typename... Args>
240 auto operator()( Args&& ...arg ) const {
241 //auto ref = _host.shared_from_this();
242 return sigc::signal<ReturnType(Arguments...)>::operator()( std::forward<Args>(arg)...);
243 }
244
245 private:
246 SignalHost &_host;
247 };
248
249 namespace internal {
250
255 template <typename T>
256 inline auto lock_shared_makeLock ( const T& locker ) {
257 try {
258 if constexpr ( std::is_base_of_v<BasePrivate, T> ) {
259 return locker.z_func()->shared_from_this();
260 } else {
261 return locker.shared_from_this();
262 }
263 } catch ( const std::bad_weak_ptr &e ) {
264 ZYPP_CAUGHT( e );
265 ZYPP_THROW( e );
266 }
267 }
268
273 template <typename T_functor, typename ...Lockers>
274 struct lock_shared : public sigc::adapts<T_functor>
275 {
276 template <typename... Args>
277 decltype(auto) operator()( Args&&... args ) const {
278
279 try {
280 auto __attribute__ ((__unused__)) lck = std::apply( []( auto&... lockers ) {
281 return std::make_tuple( lock_shared_makeLock( lockers.invoke() )... );
282 }, _lcks );
283
284 // seems the overloaded function templates in sigc++2 force us to fully specify the overload
285 // we want to use. std::invoke() fails in that case.
286 //return std::invoke( this->functor_, std::forward<Args>(args)... );
287 if constexpr ( sizeof... (Args) == 0 ) {
288 return this->functor_();
289 } else {
290 return this->functor_.template operator()<decltype ( std::forward<Args>(args) )...> ( std::forward<Args>(args)... );
291 }
292 } catch ( const std::bad_weak_ptr &e ) {
293 ZYPP_CAUGHT( e );
294 ERR << "Ignoring signal emit due to a bad_weak_ptr exception during object locking. Maybe the signal was sent to a object that is currently destructing?" << std::endl;
295#ifndef ZYPP_NDEBUG
296 assert( false );
297#endif
298 if constexpr ( !std::is_same_v<void, typename sigc::adapts<T_functor>::result_type> )
299 return typename sigc::adapts<T_functor>::result_type{};
300 else
301 return;
302 }
303 }
304
305 // Constructs a my_adaptor object that wraps the passed functor.
306 // Initializes adapts<T_functor>::functor_, which is invoked from operator()().
307 explicit lock_shared( const T_functor& functor, const Lockers&... lcks ) :
308 sigc::adapts<T_functor>(functor),
309 _lcks( lcks... )
310 {}
311
312 std::tuple<sigc::const_limit_reference<Lockers>...> _lcks;
313 };
314
315 template< typename Functor, typename ...Obj >
316 inline decltype(auto) locking_fun( const Functor &f, const Obj&... o )
317 {
318 return lock_shared<Functor, Obj...>( f, o...);
319 }
320
321 }
322#endif
323
324 template <class R, class... T>
326
332 template <class R, class... T>
333 class SignalProxy<R(T...)>
334 {
335 public:
337
338 SignalProxy ( SignalType &sig ) : _sig ( sig ) {}
339
343 template <typename... Args>
344 connection connect( Args&&... slot )
345 {
346 return _sig.connect( std::forward<Args>(slot)... );
347 }
348
349 private:
351 };
352
353}
354
355#ifndef ENABLE_SYWU
356//
357// Specialization of sigc::visitor for lock_shared.
358namespace sigc
359{
360 template <typename T_functor, typename ...Lockers>
361 struct visitor<zyppng::internal::lock_shared<T_functor, Lockers...> >
362 {
363 template <typename T_action>
364 static void do_visit_each(const T_action& action,
366 {
367 sigc::visit_each(action, target.functor_);
368 std::apply( [&]( auto&... a) {
369 ((void)sigc::visit_each(action, a),...);
370 }, target._lcks );
371
372 }
373 };
374} // end namespace sigc
375#endif
376
377#endif // ZYPP_NG_CORE_SIGNALS_H_INCLUDED
SignalProxy(SignalType &sig)
Definition signals.h:338
connection connect(Args &&... slot)
Forwards the arguments to the internal connect function of the signal type.
Definition signals.h:344
SignalProxyBase< R, T... > SignalType
Definition signals.h:336
unsigned short a
constexpr bool is_base_of_v
Definition TypeTraits.h:27
decltype(auto) locking_fun(const Functor &f, const Obj &... o)
Definition signals.h:316
auto lock_shared_makeLock(const T &locker)
Definition signals.h:256
sigc::trackable trackable
Definition signals.h:181
sigc::connection connection
Definition signals.h:180
sigc::signal< R(T...)> SignalProxyBase
Definition signals.h:185
static void do_visit_each(const T_action &action, const zyppng::internal::lock_shared< T_functor, Lockers... > &target)
Definition signals.h:364
std::tuple< sigc::const_limit_reference< Lockers >... > _lcks
Definition signals.h:312
lock_shared(const T_functor &functor, const Lockers &... lcks)
Definition signals.h:307
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:475
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
#define ERR
Definition Logger.h:102
#define WAR
Definition Logger.h:101