mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-10-30 23:42:42 +01:00 
			
		
		
		
	 285a264aae
			
		
	
	285a264aae
	
	
	
		
			
			Implement a wrapper over Glib::Dispatcher that passes the arguments to the signal consumer via synchronized `std::queue`. Arguments are always passed by value and the return type of the signal is expected to be `void`.
		
			
				
	
	
		
			60 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			60 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #pragma once
 | |
| 
 | |
| #include <glibmm/dispatcher.h>
 | |
| #include <sigc++/signal.h>
 | |
| 
 | |
| #include <functional>
 | |
| #include <mutex>
 | |
| #include <queue>
 | |
| #include <tuple>
 | |
| #include <type_traits>
 | |
| 
 | |
| namespace waybar {
 | |
| 
 | |
| /**
 | |
|  * Thread-safe signal wrapper.
 | |
|  * Uses Glib::Dispatcher to pass events to another thread and locked queue to pass the arguments.
 | |
|  */
 | |
| template <typename... Args>
 | |
| struct SafeSignal : sigc::signal<void(std::decay_t<Args>...)> {
 | |
|  public:
 | |
|   SafeSignal() { dp_.connect(sigc::mem_fun(*this, &SafeSignal::handle_event)); }
 | |
| 
 | |
|   template <typename... EmitArgs>
 | |
|   void emit(EmitArgs&&... args) {
 | |
|     {
 | |
|       std::unique_lock lock(mutex_);
 | |
|       queue_.emplace(std::forward<EmitArgs>(args)...);
 | |
|     }
 | |
|     dp_.emit();
 | |
|   }
 | |
| 
 | |
|   template <typename... EmitArgs>
 | |
|   inline void operator()(EmitArgs&&... args) {
 | |
|     emit(std::forward<EmitArgs>(args)...);
 | |
|   }
 | |
| 
 | |
|  protected:
 | |
|   using signal_t = sigc::signal<void(std::decay_t<Args>...)>;
 | |
|   using arg_tuple_t = std::tuple<std::decay_t<Args>...>;
 | |
|   // ensure that unwrapped methods are not accessible
 | |
|   using signal_t::emit_reverse;
 | |
|   using signal_t::make_slot;
 | |
| 
 | |
|   void handle_event() {
 | |
|     auto fn = signal_t::make_slot();
 | |
|     for (std::unique_lock lock(mutex_); !queue_.empty(); lock.lock()) {
 | |
|       auto args = queue_.front();
 | |
|       queue_.pop();
 | |
|       lock.unlock();
 | |
|       std::apply(fn, args);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Glib::Dispatcher        dp_;
 | |
|   std::mutex              mutex_;
 | |
|   std::queue<arg_tuple_t> queue_;
 | |
| };
 | |
| 
 | |
| }  // namespace waybar
 |