mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	loop: simplify before and after events
Because the signal can't be removed from the callback we can simply iterate backwards and then forwards. The first added hook (the unlock/lock pair) is called last before going into the poll and first when leaving. This executes all other callbacks inside a locked situation. And removing them with the lock is not going to cause problems.
This commit is contained in:
		
							parent
							
								
									854d019343
								
							
						
					
					
						commit
						e5f7e040dc
					
				
					 3 changed files with 28 additions and 16 deletions
				
			
		| 
						 | 
					@ -113,7 +113,9 @@ struct spa_loop_methods {
 | 
				
			||||||
#define spa_loop_invoke(l,...)		spa_loop_method(l,invoke,0,##__VA_ARGS__)
 | 
					#define spa_loop_invoke(l,...)		spa_loop_method(l,invoke,0,##__VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Control hooks */
 | 
					/** Control hooks. These hooks can't be removed from their
 | 
				
			||||||
 | 
					 *  callbacks and must be removed from a safe place (when the loop
 | 
				
			||||||
 | 
					 *  is not running or when it is locked). */
 | 
				
			||||||
struct spa_loop_control_hooks {
 | 
					struct spa_loop_control_hooks {
 | 
				
			||||||
#define SPA_VERSION_LOOP_CONTROL_HOOKS	0
 | 
					#define SPA_VERSION_LOOP_CONTROL_HOOKS	0
 | 
				
			||||||
	uint32_t version;
 | 
						uint32_t version;
 | 
				
			||||||
| 
						 | 
					@ -125,8 +127,21 @@ struct spa_loop_control_hooks {
 | 
				
			||||||
	void (*after) (void *data);
 | 
						void (*after) (void *data);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define spa_loop_control_hook_before(l) spa_hook_list_call_simple(l, struct spa_loop_control_hooks, before, 0)
 | 
					#define spa_loop_control_hook_before(l)							\
 | 
				
			||||||
#define spa_loop_control_hook_after(l) spa_hook_list_call_simple(l, struct spa_loop_control_hooks, after, 0)
 | 
					({											\
 | 
				
			||||||
 | 
						struct spa_hook_list *_l = l;							\
 | 
				
			||||||
 | 
						struct spa_hook *_h;								\
 | 
				
			||||||
 | 
						spa_list_for_each_reverse(_h, &_l->list, link)					\
 | 
				
			||||||
 | 
							spa_callbacks_call(&_h->cb, struct spa_loop_control_hooks, before, 0);	\
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define spa_loop_control_hook_after(l)							\
 | 
				
			||||||
 | 
					({											\
 | 
				
			||||||
 | 
						struct spa_hook_list *_l = l;							\
 | 
				
			||||||
 | 
						struct spa_hook *_h;								\
 | 
				
			||||||
 | 
						spa_list_for_each(_h, &_l->list, link)						\
 | 
				
			||||||
 | 
							spa_callbacks_call(&_h->cb, struct spa_loop_control_hooks, after, 0);	\
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Control an event loop
 | 
					 * Control an event loop
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,9 +98,17 @@ static inline void spa_list_remove(struct spa_list *elem)
 | 
				
			||||||
	     !spa_list_is_end(pos, head, member);			\
 | 
						     !spa_list_is_end(pos, head, member);			\
 | 
				
			||||||
	     pos = spa_list_next(pos, member))
 | 
						     pos = spa_list_next(pos, member))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define spa_list_for_each_prev(pos, head, curr, member)			\
 | 
				
			||||||
 | 
						for (pos = spa_list_last(curr, __typeof__(*pos), member);	\
 | 
				
			||||||
 | 
						     !spa_list_is_end(pos, head, member);			\
 | 
				
			||||||
 | 
						     pos = spa_list_prev(pos, member))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define spa_list_for_each(pos, head, member)				\
 | 
					#define spa_list_for_each(pos, head, member)				\
 | 
				
			||||||
	spa_list_for_each_next(pos, head, head, member)
 | 
						spa_list_for_each_next(pos, head, head, member)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define spa_list_for_each_reverse(pos, head, member)				\
 | 
				
			||||||
 | 
						spa_list_for_each_prev(pos, head, head, member)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define spa_list_for_each_safe_next(pos, tmp, head, curr, member)	\
 | 
					#define spa_list_for_each_safe_next(pos, tmp, head, curr, member)	\
 | 
				
			||||||
	for (pos = spa_list_first(curr, __typeof__(*pos), member);	\
 | 
						for (pos = spa_list_first(curr, __typeof__(*pos), member);	\
 | 
				
			||||||
	     tmp = spa_list_next(pos, member),				\
 | 
						     tmp = spa_list_next(pos, member),				\
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -278,24 +278,13 @@ static int loop_iterate(void *object, int timeout)
 | 
				
			||||||
	struct impl *impl = object;
 | 
						struct impl *impl = object;
 | 
				
			||||||
	struct spa_loop *loop = &impl->loop;
 | 
						struct spa_loop *loop = &impl->loop;
 | 
				
			||||||
	struct spa_poll_event ep[32];
 | 
						struct spa_poll_event ep[32];
 | 
				
			||||||
	struct spa_list save;
 | 
					 | 
				
			||||||
	struct spa_hook *hook;
 | 
					 | 
				
			||||||
	int i, nfds;
 | 
						int i, nfds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_init(&save);
 | 
						spa_loop_control_hook_before(&impl->hooks_list);
 | 
				
			||||||
	spa_list_consume(hook, &impl->hooks_list.list, link) {
 | 
					 | 
				
			||||||
		spa_list_remove(&hook->link);
 | 
					 | 
				
			||||||
		spa_list_prepend(&save, &hook->link);
 | 
					 | 
				
			||||||
		spa_callbacks_call(&hook->cb, struct spa_loop_control_hooks, before, 0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nfds = spa_system_pollfd_wait(impl->system, impl->poll_fd, ep, SPA_N_ELEMENTS(ep), timeout);
 | 
						nfds = spa_system_pollfd_wait(impl->system, impl->poll_fd, ep, SPA_N_ELEMENTS(ep), timeout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_consume(hook, &save, link) {
 | 
						spa_loop_control_hook_after(&impl->hooks_list);
 | 
				
			||||||
		spa_list_remove(&hook->link);
 | 
					 | 
				
			||||||
		spa_list_append(&impl->hooks_list.list, &hook->link);
 | 
					 | 
				
			||||||
		spa_callbacks_call(&hook->cb, struct spa_loop_control_hooks, after, 0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (SPA_UNLIKELY(nfds < 0))
 | 
						if (SPA_UNLIKELY(nfds < 0))
 | 
				
			||||||
		return nfds;
 | 
							return nfds;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue