mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-04 00:02:52 -05:00 
			
		
		
		
	Add enable_timeout_every() to fire the same timeout repeatedly.
enable_timeout_at() and enable_timeout_after() can still be used when you want to fire a timeout just once. Patch by me, per a suggestion from Tom Lane. Discussion: http://postgr.es/m/2992585.1632938816@sss.pgh.pa.us Discussion: http://postgr.es/m/CA+TgmoYqSF5sCNrgTom9r3Nh=at4WmYFD=gsV-omStZ60S0ZUQ@mail.gmail.com
This commit is contained in:
		
							parent
							
								
									902a2c2800
								
							
						
					
					
						commit
						732e6677a6
					
				@ -36,6 +36,7 @@ typedef struct timeout_params
 | 
			
		||||
 | 
			
		||||
	TimestampTz start_time;		/* time that timeout was last activated */
 | 
			
		||||
	TimestampTz fin_time;		/* time it is, or was last, due to fire */
 | 
			
		||||
	int			interval_in_ms; /* time between firings, or 0 if just once */
 | 
			
		||||
} timeout_params;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -153,7 +154,8 @@ remove_timeout_index(int index)
 | 
			
		||||
 * Enable the specified timeout reason
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
enable_timeout(TimeoutId id, TimestampTz now, TimestampTz fin_time)
 | 
			
		||||
enable_timeout(TimeoutId id, TimestampTz now, TimestampTz fin_time,
 | 
			
		||||
			   int interval_in_ms)
 | 
			
		||||
{
 | 
			
		||||
	int			i;
 | 
			
		||||
 | 
			
		||||
@ -188,6 +190,7 @@ enable_timeout(TimeoutId id, TimestampTz now, TimestampTz fin_time)
 | 
			
		||||
	all_timeouts[id].indicator = false;
 | 
			
		||||
	all_timeouts[id].start_time = now;
 | 
			
		||||
	all_timeouts[id].fin_time = fin_time;
 | 
			
		||||
	all_timeouts[id].interval_in_ms = interval_in_ms;
 | 
			
		||||
 | 
			
		||||
	insert_timeout(id, i);
 | 
			
		||||
}
 | 
			
		||||
@ -399,6 +402,29 @@ handle_sig_alarm(SIGNAL_ARGS)
 | 
			
		||||
				/* And call its handler function */
 | 
			
		||||
				this_timeout->timeout_handler();
 | 
			
		||||
 | 
			
		||||
				/* If it should fire repeatedly, re-enable it. */
 | 
			
		||||
				if (this_timeout->interval_in_ms > 0)
 | 
			
		||||
				{
 | 
			
		||||
					TimestampTz new_fin_time;
 | 
			
		||||
 | 
			
		||||
					/*
 | 
			
		||||
					 * To guard against drift, schedule the next instance of
 | 
			
		||||
					 * the timeout based on the intended firing time rather
 | 
			
		||||
					 * than the actual firing time. But if the timeout was so
 | 
			
		||||
					 * late that we missed an entire cycle, fall back to
 | 
			
		||||
					 * scheduling based on the actual firing time.
 | 
			
		||||
					 */
 | 
			
		||||
					new_fin_time =
 | 
			
		||||
						TimestampTzPlusMilliseconds(this_timeout->fin_time,
 | 
			
		||||
													this_timeout->interval_in_ms);
 | 
			
		||||
					if (new_fin_time < now)
 | 
			
		||||
						new_fin_time =
 | 
			
		||||
							TimestampTzPlusMilliseconds(now,
 | 
			
		||||
														this_timeout->interval_in_ms);
 | 
			
		||||
					enable_timeout(this_timeout->index, now, new_fin_time,
 | 
			
		||||
								   this_timeout->interval_in_ms);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				/*
 | 
			
		||||
				 * The handler might not take negligible time (CheckDeadLock
 | 
			
		||||
				 * for instance isn't too cheap), so let's update our idea of
 | 
			
		||||
@ -449,6 +475,7 @@ InitializeTimeouts(void)
 | 
			
		||||
		all_timeouts[i].timeout_handler = NULL;
 | 
			
		||||
		all_timeouts[i].start_time = 0;
 | 
			
		||||
		all_timeouts[i].fin_time = 0;
 | 
			
		||||
		all_timeouts[i].interval_in_ms = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	all_timeouts_initialized = true;
 | 
			
		||||
@ -532,7 +559,29 @@ enable_timeout_after(TimeoutId id, int delay_ms)
 | 
			
		||||
	/* Queue the timeout at the appropriate time. */
 | 
			
		||||
	now = GetCurrentTimestamp();
 | 
			
		||||
	fin_time = TimestampTzPlusMilliseconds(now, delay_ms);
 | 
			
		||||
	enable_timeout(id, now, fin_time);
 | 
			
		||||
	enable_timeout(id, now, fin_time, 0);
 | 
			
		||||
 | 
			
		||||
	/* Set the timer interrupt. */
 | 
			
		||||
	schedule_alarm(now);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Enable the specified timeout to fire periodically, with the specified
 | 
			
		||||
 * delay as the time between firings.
 | 
			
		||||
 *
 | 
			
		||||
 * Delay is given in milliseconds.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
enable_timeout_every(TimeoutId id, TimestampTz fin_time, int delay_ms)
 | 
			
		||||
{
 | 
			
		||||
	TimestampTz now;
 | 
			
		||||
 | 
			
		||||
	/* Disable timeout interrupts for safety. */
 | 
			
		||||
	disable_alarm();
 | 
			
		||||
 | 
			
		||||
	/* Queue the timeout at the appropriate time. */
 | 
			
		||||
	now = GetCurrentTimestamp();
 | 
			
		||||
	enable_timeout(id, now, fin_time, delay_ms);
 | 
			
		||||
 | 
			
		||||
	/* Set the timer interrupt. */
 | 
			
		||||
	schedule_alarm(now);
 | 
			
		||||
@ -555,7 +604,7 @@ enable_timeout_at(TimeoutId id, TimestampTz fin_time)
 | 
			
		||||
 | 
			
		||||
	/* Queue the timeout at the appropriate time. */
 | 
			
		||||
	now = GetCurrentTimestamp();
 | 
			
		||||
	enable_timeout(id, now, fin_time);
 | 
			
		||||
	enable_timeout(id, now, fin_time, 0);
 | 
			
		||||
 | 
			
		||||
	/* Set the timer interrupt. */
 | 
			
		||||
	schedule_alarm(now);
 | 
			
		||||
@ -590,11 +639,17 @@ enable_timeouts(const EnableTimeoutParams *timeouts, int count)
 | 
			
		||||
			case TMPARAM_AFTER:
 | 
			
		||||
				fin_time = TimestampTzPlusMilliseconds(now,
 | 
			
		||||
													   timeouts[i].delay_ms);
 | 
			
		||||
				enable_timeout(id, now, fin_time);
 | 
			
		||||
				enable_timeout(id, now, fin_time, 0);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case TMPARAM_AT:
 | 
			
		||||
				enable_timeout(id, now, timeouts[i].fin_time);
 | 
			
		||||
				enable_timeout(id, now, timeouts[i].fin_time, 0);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case TMPARAM_EVERY:
 | 
			
		||||
				fin_time = TimestampTzPlusMilliseconds(now,
 | 
			
		||||
													   timeouts[i].delay_ms);
 | 
			
		||||
				enable_timeout(id, now, fin_time, timeouts[i].delay_ms);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			default:
 | 
			
		||||
 | 
			
		||||
@ -48,14 +48,15 @@ typedef void (*timeout_handler_proc) (void);
 | 
			
		||||
typedef enum TimeoutType
 | 
			
		||||
{
 | 
			
		||||
	TMPARAM_AFTER,
 | 
			
		||||
	TMPARAM_AT
 | 
			
		||||
	TMPARAM_AT,
 | 
			
		||||
	TMPARAM_EVERY
 | 
			
		||||
} TimeoutType;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
	TimeoutId	id;				/* timeout to set */
 | 
			
		||||
	TimeoutType type;			/* TMPARAM_AFTER or TMPARAM_AT */
 | 
			
		||||
	int			delay_ms;		/* only used for TMPARAM_AFTER */
 | 
			
		||||
	int			delay_ms;		/* only used for TMPARAM_AFTER/EVERY */
 | 
			
		||||
	TimestampTz fin_time;		/* only used for TMPARAM_AT */
 | 
			
		||||
} EnableTimeoutParams;
 | 
			
		||||
 | 
			
		||||
@ -75,6 +76,8 @@ extern void reschedule_timeouts(void);
 | 
			
		||||
 | 
			
		||||
/* timeout operation */
 | 
			
		||||
extern void enable_timeout_after(TimeoutId id, int delay_ms);
 | 
			
		||||
extern void enable_timeout_every(TimeoutId id, TimestampTz fin_time,
 | 
			
		||||
								 int delay_ms);
 | 
			
		||||
extern void enable_timeout_at(TimeoutId id, TimestampTz fin_time);
 | 
			
		||||
extern void enable_timeouts(const EnableTimeoutParams *timeouts, int count);
 | 
			
		||||
extern void disable_timeout(TimeoutId id, bool keep_indicator);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user