diff src/ex_cmds2.c @ 19396:a961efb326e5 v8.2.0256

patch 8.2.0256: time and timer related code is spread out Commit: https://github.com/vim/vim/commit/0a8fed6231c84e4e1b3a7dd6c0d95d3f98207fe0 Author: Bram Moolenaar <Bram@vim.org> Date: Fri Feb 14 13:22:17 2020 +0100 patch 8.2.0256: time and timer related code is spread out Problem: Time and timer related code is spread out. Solution: Move time and timer related code to a new file. (Yegappan Lakshmanan, closes #5604)
author Bram Moolenaar <Bram@vim.org>
date Fri, 14 Feb 2020 13:30:05 +0100
parents 5c405689da3e
children 435726a03481
line wrap: on
line diff
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -14,498 +14,6 @@
 #include "vim.h"
 #include "version.h"
 
-#if defined(FEAT_EVAL) || defined(PROTO)
-# if defined(FEAT_TIMERS) || defined(PROTO)
-static timer_T	*first_timer = NULL;
-static long	last_timer_id = 0;
-
-/*
- * Return time left until "due".  Negative if past "due".
- */
-    long
-proftime_time_left(proftime_T *due, proftime_T *now)
-{
-#  ifdef MSWIN
-    LARGE_INTEGER fr;
-
-    if (now->QuadPart > due->QuadPart)
-	return 0;
-    QueryPerformanceFrequency(&fr);
-    return (long)(((double)(due->QuadPart - now->QuadPart)
-		   / (double)fr.QuadPart) * 1000);
-#  else
-    if (now->tv_sec > due->tv_sec)
-	return 0;
-    return (due->tv_sec - now->tv_sec) * 1000
-	+ (due->tv_usec - now->tv_usec) / 1000;
-#  endif
-}
-
-/*
- * Insert a timer in the list of timers.
- */
-    static void
-insert_timer(timer_T *timer)
-{
-    timer->tr_next = first_timer;
-    timer->tr_prev = NULL;
-    if (first_timer != NULL)
-	first_timer->tr_prev = timer;
-    first_timer = timer;
-    did_add_timer = TRUE;
-}
-
-/*
- * Take a timer out of the list of timers.
- */
-    static void
-remove_timer(timer_T *timer)
-{
-    if (timer->tr_prev == NULL)
-	first_timer = timer->tr_next;
-    else
-	timer->tr_prev->tr_next = timer->tr_next;
-    if (timer->tr_next != NULL)
-	timer->tr_next->tr_prev = timer->tr_prev;
-}
-
-    static void
-free_timer(timer_T *timer)
-{
-    free_callback(&timer->tr_callback);
-    vim_free(timer);
-}
-
-/*
- * Create a timer and return it.  NULL if out of memory.
- * Caller should set the callback.
- */
-    timer_T *
-create_timer(long msec, int repeat)
-{
-    timer_T	*timer = ALLOC_CLEAR_ONE(timer_T);
-    long	prev_id = last_timer_id;
-
-    if (timer == NULL)
-	return NULL;
-    if (++last_timer_id <= prev_id)
-	// Overflow!  Might cause duplicates...
-	last_timer_id = 0;
-    timer->tr_id = last_timer_id;
-    insert_timer(timer);
-    if (repeat != 0)
-	timer->tr_repeat = repeat - 1;
-    timer->tr_interval = msec;
-
-    profile_setlimit(msec, &timer->tr_due);
-    return timer;
-}
-
-/*
- * Invoke the callback of "timer".
- */
-    static void
-timer_callback(timer_T *timer)
-{
-    typval_T	rettv;
-    typval_T	argv[2];
-
-    argv[0].v_type = VAR_NUMBER;
-    argv[0].vval.v_number = (varnumber_T)timer->tr_id;
-    argv[1].v_type = VAR_UNKNOWN;
-
-    call_callback(&timer->tr_callback, -1, &rettv, 1, argv);
-    clear_tv(&rettv);
-}
-
-/*
- * Call timers that are due.
- * Return the time in msec until the next timer is due.
- * Returns -1 if there are no pending timers.
- */
-    long
-check_due_timer(void)
-{
-    timer_T	*timer;
-    timer_T	*timer_next;
-    long	this_due;
-    long	next_due = -1;
-    proftime_T	now;
-    int		did_one = FALSE;
-    int		need_update_screen = FALSE;
-    long	current_id = last_timer_id;
-
-    // Don't run any timers while exiting or dealing with an error.
-    if (exiting || aborting())
-	return next_due;
-
-    profile_start(&now);
-    for (timer = first_timer; timer != NULL && !got_int; timer = timer_next)
-    {
-	timer_next = timer->tr_next;
-
-	if (timer->tr_id == -1 || timer->tr_firing || timer->tr_paused)
-	    continue;
-	this_due = proftime_time_left(&timer->tr_due, &now);
-	if (this_due <= 1)
-	{
-	    // Save and restore a lot of flags, because the timer fires while
-	    // waiting for a character, which might be halfway a command.
-	    int save_timer_busy = timer_busy;
-	    int save_vgetc_busy = vgetc_busy;
-	    int save_did_emsg = did_emsg;
-	    int save_called_emsg = called_emsg;
-	    int save_must_redraw = must_redraw;
-	    int save_trylevel = trylevel;
-	    int save_did_throw = did_throw;
-	    int save_ex_pressedreturn = get_pressedreturn();
-	    int save_may_garbage_collect = may_garbage_collect;
-	    except_T *save_current_exception = current_exception;
-	    vimvars_save_T vvsave;
-
-	    // Create a scope for running the timer callback, ignoring most of
-	    // the current scope, such as being inside a try/catch.
-	    timer_busy = timer_busy > 0 || vgetc_busy > 0;
-	    vgetc_busy = 0;
-	    called_emsg = 0;
-	    did_emsg = FALSE;
-	    did_uncaught_emsg = FALSE;
-	    must_redraw = 0;
-	    trylevel = 0;
-	    did_throw = FALSE;
-	    current_exception = NULL;
-	    may_garbage_collect = FALSE;
-	    save_vimvars(&vvsave);
-
-	    timer->tr_firing = TRUE;
-	    timer_callback(timer);
-	    timer->tr_firing = FALSE;
-
-	    timer_next = timer->tr_next;
-	    did_one = TRUE;
-	    timer_busy = save_timer_busy;
-	    vgetc_busy = save_vgetc_busy;
-	    if (did_uncaught_emsg)
-		++timer->tr_emsg_count;
-	    did_emsg = save_did_emsg;
-	    called_emsg = save_called_emsg;
-	    trylevel = save_trylevel;
-	    did_throw = save_did_throw;
-	    current_exception = save_current_exception;
-	    restore_vimvars(&vvsave);
-	    if (must_redraw != 0)
-		need_update_screen = TRUE;
-	    must_redraw = must_redraw > save_must_redraw
-					      ? must_redraw : save_must_redraw;
-	    set_pressedreturn(save_ex_pressedreturn);
-	    may_garbage_collect = save_may_garbage_collect;
-
-	    // Only fire the timer again if it repeats and stop_timer() wasn't
-	    // called while inside the callback (tr_id == -1).
-	    if (timer->tr_repeat != 0 && timer->tr_id != -1
-		    && timer->tr_emsg_count < 3)
-	    {
-		profile_setlimit(timer->tr_interval, &timer->tr_due);
-		this_due = proftime_time_left(&timer->tr_due, &now);
-		if (this_due < 1)
-		    this_due = 1;
-		if (timer->tr_repeat > 0)
-		    --timer->tr_repeat;
-	    }
-	    else
-	    {
-		this_due = -1;
-		remove_timer(timer);
-		free_timer(timer);
-	    }
-	}
-	if (this_due > 0 && (next_due == -1 || next_due > this_due))
-	    next_due = this_due;
-    }
-
-    if (did_one)
-	redraw_after_callback(need_update_screen);
-
-#ifdef FEAT_BEVAL_TERM
-    if (bevalexpr_due_set)
-    {
-	this_due = proftime_time_left(&bevalexpr_due, &now);
-	if (this_due <= 1)
-	{
-	    bevalexpr_due_set = FALSE;
-	    if (balloonEval == NULL)
-	    {
-		balloonEval = ALLOC_CLEAR_ONE(BalloonEval);
-		balloonEvalForTerm = TRUE;
-	    }
-	    if (balloonEval != NULL)
-	    {
-		general_beval_cb(balloonEval, 0);
-		setcursor();
-		out_flush();
-	    }
-	}
-	else if (next_due == -1 || next_due > this_due)
-	    next_due = this_due;
-    }
-#endif
-#ifdef FEAT_TERMINAL
-    // Some terminal windows may need their buffer updated.
-    next_due = term_check_timers(next_due, &now);
-#endif
-
-    return current_id != last_timer_id ? 1 : next_due;
-}
-
-/*
- * Find a timer by ID.  Returns NULL if not found;
- */
-    static timer_T *
-find_timer(long id)
-{
-    timer_T *timer;
-
-    if (id >= 0)
-    {
-	for (timer = first_timer; timer != NULL; timer = timer->tr_next)
-	    if (timer->tr_id == id)
-		return timer;
-    }
-    return NULL;
-}
-
-
-/*
- * Stop a timer and delete it.
- */
-    void
-stop_timer(timer_T *timer)
-{
-    if (timer->tr_firing)
-	// Free the timer after the callback returns.
-	timer->tr_id = -1;
-    else
-    {
-	remove_timer(timer);
-	free_timer(timer);
-    }
-}
-
-    static void
-stop_all_timers(void)
-{
-    timer_T *timer;
-    timer_T *timer_next;
-
-    for (timer = first_timer; timer != NULL; timer = timer_next)
-    {
-	timer_next = timer->tr_next;
-	stop_timer(timer);
-    }
-}
-
-    static void
-add_timer_info(typval_T *rettv, timer_T *timer)
-{
-    list_T	*list = rettv->vval.v_list;
-    dict_T	*dict = dict_alloc();
-    dictitem_T	*di;
-    long	remaining;
-    proftime_T	now;
-
-    if (dict == NULL)
-	return;
-    list_append_dict(list, dict);
-
-    dict_add_number(dict, "id", timer->tr_id);
-    dict_add_number(dict, "time", (long)timer->tr_interval);
-
-    profile_start(&now);
-    remaining = proftime_time_left(&timer->tr_due, &now);
-    dict_add_number(dict, "remaining", (long)remaining);
-
-    dict_add_number(dict, "repeat",
-		    (long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1));
-    dict_add_number(dict, "paused", (long)(timer->tr_paused));
-
-    di = dictitem_alloc((char_u *)"callback");
-    if (di != NULL)
-    {
-	if (dict_add(dict, di) == FAIL)
-	    vim_free(di);
-	else
-	    put_callback(&timer->tr_callback, &di->di_tv);
-    }
-}
-
-    static void
-add_timer_info_all(typval_T *rettv)
-{
-    timer_T *timer;
-
-    for (timer = first_timer; timer != NULL; timer = timer->tr_next)
-	if (timer->tr_id != -1)
-	    add_timer_info(rettv, timer);
-}
-
-/*
- * Mark references in partials of timers.
- */
-    int
-set_ref_in_timer(int copyID)
-{
-    int		abort = FALSE;
-    timer_T	*timer;
-    typval_T	tv;
-
-    for (timer = first_timer; !abort && timer != NULL; timer = timer->tr_next)
-    {
-	if (timer->tr_callback.cb_partial != NULL)
-	{
-	    tv.v_type = VAR_PARTIAL;
-	    tv.vval.v_partial = timer->tr_callback.cb_partial;
-	}
-	else
-	{
-	    tv.v_type = VAR_FUNC;
-	    tv.vval.v_string = timer->tr_callback.cb_name;
-	}
-	abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
-    }
-    return abort;
-}
-
-# if defined(EXITFREE) || defined(PROTO)
-    void
-timer_free_all()
-{
-    timer_T *timer;
-
-    while (first_timer != NULL)
-    {
-	timer = first_timer;
-	remove_timer(timer);
-	free_timer(timer);
-    }
-}
-# endif
-
-/*
- * "timer_info([timer])" function
- */
-    void
-f_timer_info(typval_T *argvars, typval_T *rettv)
-{
-    timer_T *timer = NULL;
-
-    if (rettv_list_alloc(rettv) != OK)
-	return;
-    if (argvars[0].v_type != VAR_UNKNOWN)
-    {
-	if (argvars[0].v_type != VAR_NUMBER)
-	    emsg(_(e_number_exp));
-	else
-	{
-	    timer = find_timer((int)tv_get_number(&argvars[0]));
-	    if (timer != NULL)
-		add_timer_info(rettv, timer);
-	}
-    }
-    else
-	add_timer_info_all(rettv);
-}
-
-/*
- * "timer_pause(timer, paused)" function
- */
-    void
-f_timer_pause(typval_T *argvars, typval_T *rettv UNUSED)
-{
-    timer_T	*timer = NULL;
-    int		paused = (int)tv_get_number(&argvars[1]);
-
-    if (argvars[0].v_type != VAR_NUMBER)
-	emsg(_(e_number_exp));
-    else
-    {
-	timer = find_timer((int)tv_get_number(&argvars[0]));
-	if (timer != NULL)
-	    timer->tr_paused = paused;
-    }
-}
-
-/*
- * "timer_start(time, callback [, options])" function
- */
-    void
-f_timer_start(typval_T *argvars, typval_T *rettv)
-{
-    long	msec = (long)tv_get_number(&argvars[0]);
-    timer_T	*timer;
-    int		repeat = 0;
-    callback_T	callback;
-    dict_T	*dict;
-
-    rettv->vval.v_number = -1;
-    if (check_secure())
-	return;
-    if (argvars[2].v_type != VAR_UNKNOWN)
-    {
-	if (argvars[2].v_type != VAR_DICT
-				   || (dict = argvars[2].vval.v_dict) == NULL)
-	{
-	    semsg(_(e_invarg2), tv_get_string(&argvars[2]));
-	    return;
-	}
-	if (dict_find(dict, (char_u *)"repeat", -1) != NULL)
-	    repeat = dict_get_number(dict, (char_u *)"repeat");
-    }
-
-    callback = get_callback(&argvars[1]);
-    if (callback.cb_name == NULL)
-	return;
-
-    timer = create_timer(msec, repeat);
-    if (timer == NULL)
-	free_callback(&callback);
-    else
-    {
-	set_callback(&timer->tr_callback, &callback);
-	rettv->vval.v_number = (varnumber_T)timer->tr_id;
-    }
-}
-
-/*
- * "timer_stop(timer)" function
- */
-    void
-f_timer_stop(typval_T *argvars, typval_T *rettv UNUSED)
-{
-    timer_T *timer;
-
-    if (argvars[0].v_type != VAR_NUMBER)
-    {
-	emsg(_(e_number_exp));
-	return;
-    }
-    timer = find_timer((int)tv_get_number(&argvars[0]));
-    if (timer != NULL)
-	stop_timer(timer);
-}
-
-/*
- * "timer_stopall()" function
- */
-    void
-f_timer_stopall(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
-{
-    stop_all_timers();
-}
-
-# endif // FEAT_TIMERS
-
-#endif // FEAT_EVAL
-
 /*
  * If 'autowrite' option set, try to write the file.
  * Careful: autocommands may make "buf" invalid!