On Thursday, September 19, 2013 3:29:35 AM UTC-7, ZyX wrote: > On Sep 19, 2013 2:01 PM, "kans" <[email protected]> wrote: > > > > > > On Friday, September 13, 2013 2:43:13 AM UTC-7, kans wrote: > > > > On Thursday, September 12, 2013 1:59:51 AM UTC-7, ZyX wrote: > > > > > > > > > On Sep 12, 2013 3:28 AM, "kans" <[email protected]> wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Wednesday, September 11, 2013 7:46:06 AM UTC-7, ZyX wrote: > > > > > > > > > > > > > > > > > > > > On Sep 11, 2013 1:27 PM, "Thomas" <[email protected]> wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On 11 September 2013 00:18, Nikolay Pavlov <[email protected]> > > > > > > > wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >> Why do you keep calling it async? > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Referring to the introduction to asynchronous programming linked > > > > > > > below, the patch is an almost asynchronous feature, or at least a > > > > > > > completition of the already existing asynchronous features of > > > > > > > vim. With all the "autocmd-events" we already have the > > > > > > > posibillity to run code asynchronous. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Anyway asynchronous doesn't mean threaded, as far as I know and > > > > > > > referring again to the link. That a two different concepts (which > > > > > > > you can combine if you want). > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > http://cs.brown.edu/courses/cs168/f12/handouts/async.pdf > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Now please show how you can run one sequence of commands > > > > > > interleaved with the other with this patch. Function that runs with > > > > > > given interval blocks everything until it completes, same for > > > > > > autocommands. You cannot say you implement preemptive multitasking > > > > > > if you have to wait for one task to complete before starting the > > > > > > other. It is not async feature. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > You can, of course, do some hacks with saving a state, exiting and > > > > > > resuming, but you will then be forced to *emulate* preemption > > > > > > without any support from vim. I used to have some simple emulation > > > > > > even without such patch. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Note though that I would really like it merged. But not with the > > > > > > current name. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > You received this message from the "vim_dev" maillist. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Do not top-post! Type your reply below the text you are replying > > > > > > > to. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > For more information, visit http://www.vim.org/maillist.php > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > --- > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > You received this message because you are subscribed to the > > > > > > > Google Groups "vim_dev" group. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > To unsubscribe from this group and stop receiving emails from it, > > > > > > > send an email to [email protected]. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > For more options, visit https://groups.google.com/groups/opt_out. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > ZyX, > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > The new patch addresses your criticism apart from changing the name. > > > > > I believe we obey Vim code conventions everywhere. We have also > > > > > implemented a monotonically increasing timer for unix and osx which > > > > > are the only two OSes we have on hand. Otherwise, we fall back to > > > > > gettimeofday. Async is only #defined if gettimeofday exists. > > > > > > > > > > > > > > > > > > > > > > > > > > > > You can take the code from python: since 3.3 it has monotonic() > > > > function defined in C code in time module: pymonotonic function in > > > > Modules/timemodule.c. It has implementation for windows as well. Linux > > > > implementation used CLOCK_MONOTONIC (or, with higher priority, > > > > CLOCK_HIRES which is not mentioned in my clock_gettime man page; I > > > > guess there is a reason for it) without _RAW, though I would write > > > > > > > > > > > > > > > > > > > > > > > > > > > > #ifdef CLOCK_MONOTONIC_RAW > > > > > > > > > > > > > > > > > > CLOCK_MONOTONIC_RAW > > > > > > > > > > > > > > > > > > #else > > > > > > > > > > > > > > > > > > CLOCK_MONOTONIC > > > > > > > > > > > > > > > > > > #endif > > > > > > > > > > > > > > > > > > in function arguments. But it is not as severe as issue with > > > > gettimeofday: you cannot see 2 centuries hop with CLOCK_MONOTONIC, > > > > maximum slightly increased/decreased second duration when NTP daemon > > > > does his adjustments. > > > > > > > > > > > > > > > > > > > > > > > > > > > > By the way, two pairs of figure braces may be removed from > > > > insert_timeout. Not that it is required by coding style, but this makes > > > > code look better. > > > > > > > > > > > > > > > > > > > Bram, > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > We now use long longs for keeping track of the timers. We have also > > > > > documented the new functions and some of their limitations. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Please let us know if you have further feedback. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -Matt > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > > > > > > > > > > > > > > -- > > > > > > > > > > > > > > > > > > > You received this message from the "vim_dev" maillist. > > > > > > > > > > > > > > > > > > > Do not top-post! Type your reply below the text you are replying to. > > > > > > > > > > > > > > > > > > > For more information, visit http://www.vim.org/maillist.php > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > --- > > > > > > > > > > > > > > > > > > > You received this message because you are subscribed to the Google > > > > > Groups "vim_dev" group. > > > > > > > > > > > > > > > > > > > To unsubscribe from this group and stop receiving emails from it, > > > > > send an email to [email protected]. > > > > > > > > > > > > > > > > > > > For more options, visit https://groups.google.com/groups/opt_out. > > > > > > > > > > > > > > > > ZyX, > > > > > > > > > > > > > > > > I added a monotonic timer for windows; I basically took the one from > > > python. I also changed all the make files to include the new stuff as > > > well. The patch is 1200 lines long now (37 files changed, 476 > > > insertions, 24 deletions). The current state includes monotonically > > > increasing timers for OsX, Win32, and *nix. It really doesn't make sense > > > to add any more features, but I'm happy to do cleanup as needed. > > > > > > > > > > > > > > > > > -Matt > > > > > > I was doing some work cleaning up the patch. It really does make sense to > > kill all intervals if one of them fails; its too annoying as an end user if > > a timeout fails every 50ms. The docstring for do_cmdline_cmd implies it > > should return FAIL if it can't evaluate "cmdline", but in practice it > > returns OK most of the time. For instance, evaluating a function that > > doesn't exist throws an error and returns OK. Some invalid expressions > > return OK, some, like "if (" don't. Does anyone know of an easy way to > > figure out of the expression could be evaluated and didn't throw? > > > I can suggest looking at VimTry* functions in src/if_py_both.h: they are used > to transform all vim errors into python exceptions. Purge the python stuff > and you will get C functions for wrapping arbitrary code into try/catch. > > > > -Matt > > > > > > -- > > > -- > > > You received this message from the "vim_dev" maillist. > > > Do not top-post! Type your reply below the text you are replying to. > > > For more information, visit http://www.vim.org/maillist.php > > > > > > --- > > > You received this message because you are subscribed to the Google Groups > > "vim_dev" group. > > > To unsubscribe from this group and stop receiving emails from it, send an > > email to [email protected]. > > > For more options, visit https://groups.google.com/groups/opt_out.
Zyx, Thanks for the help. Intervals are no longer run if they error of any sort (apart from a user interrupt which will likely happen accidentally). I was also forced to change configure.in as the monotonic timer on Linux needs to sometimes link against rt. I ran autoconf and also dumped those changes into auto/configure file. They run in both Linux and OsX. Originally, I had hopped that this patch will be 100 lines tops, but it is closer to 600. A good chunk of that is documentation and touching the various make files. I think we have addressed all the concerns (apart from changing the name). What would it take to get this merged? -Matt -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/groups/opt_out.
>From caa96d4f49a720bb81b291867b61d9ef2888cbf1 Mon Sep 17 00:00:00 2001 From: Geoff Greer <[email protected]> Date: Tue, 10 Sep 2013 03:54:58 -0700 Subject: [PATCH] Add asynchronous functions to Vim: settimeout, setinterval, and canceltimeout. --- Filelist | 2 + runtime/doc/eval.txt | 45 ++++++++++++++++++++- runtime/doc/options.txt | 11 ++++++ runtime/doc/tags | 5 +++ src/Make_bc3.mak | 1 + src/Make_bc5.mak | 1 + src/Make_cyg.mak | 1 + src/Make_dice.mak | 6 ++- src/Make_djg.mak | 1 + src/Make_ivc.mak | 5 +++ src/Make_manx.mak | 12 ++++-- src/Make_ming.mak | 1 + src/Make_morph.mak | 3 +- src/Make_mvc.mak | 3 ++ src/Make_os2.mak | 1 + src/Make_sas.mak | 4 ++ src/Make_vms.mms | 4 +- src/Makefile | 9 +++++ src/async.c | 89 ++++++++++++++++++++++++++++++++++++++++++ src/auto/configure | 51 ++++++++++++++++++++++++ src/configure.in | 7 ++++ src/eval.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ src/feature.h | 8 ++++ src/globals.h | 5 +++ src/gui.c | 31 +++++++++------ src/main.aap | 1 + src/option.c | 8 ++++ src/option.h | 3 ++ src/os_macosx.m | 16 ++++++++ src/os_unix.c | 40 +++++++++++++++++-- src/os_win32.c | 47 ++++++++++++++++++++++ src/os_win32.h | 1 + src/proto.h | 4 ++ src/proto/async.pro | 5 +++ src/proto/os_unix.pro | 1 + src/proto/os_win32.pro | 1 + src/structs.h | 14 +++++++ src/version.c | 5 +++ 38 files changed, 530 insertions(+), 24 deletions(-) create mode 100644 src/async.c create mode 100644 src/proto/async.pro diff --git a/Filelist b/Filelist index b324933..7f7d62e 100644 --- a/Filelist +++ b/Filelist @@ -7,6 +7,7 @@ SRC_ALL = \ src/arabic.c \ src/arabic.h \ src/ascii.h \ + src/async.c \ src/blowfish.c \ src/buffer.c \ src/charset.c \ @@ -94,6 +95,7 @@ SRC_ALL = \ src/testdir/python_after/*.py \ src/testdir/python_before/*.py \ src/proto.h \ + src/proto/async.pro \ src/proto/blowfish.pro \ src/proto/buffer.pro \ src/proto/charset.pro \ diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 60b01a8..a0dd86a 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.4. Last change: 2013 Aug 24 +*eval.txt* For Vim version 7.4. Last change: 2013 Sep 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1926,6 +1926,7 @@ server2client( {clientid}, {string}) serverlist() String get a list of available servers setbufvar( {expr}, {varname}, {val}) set {varname} in buffer {expr} to {val} setcmdpos( {pos}) Number set cursor position in command-line +setinterval( {nr},{string}) Number evaluate the expression {string} every {nr} milliseconds setline( {lnum}, {line}) Number set line {lnum} to {line} setloclist( {nr}, {list}[, {action}]) Number modify location list using {list} @@ -1936,6 +1937,7 @@ setreg( {n}, {v}[, {opt}]) Number set register to value and type settabvar( {nr}, {varname}, {val}) set {varname} in tab page {nr} to {val} settabwinvar( {tabnr}, {winnr}, {varname}, {val}) set {varname} in window {winnr} in tab page {tabnr} to {val} +settimeout( {nr}, {string}) Number evaluate the expression {string} after {nr} milliseconds setwinvar( {nr}, {varname}, {val}) set {varname} in window {nr} to {val} sha256( {string}) String SHA256 checksum of {string} shellescape( {string} [, {special}]) @@ -2281,6 +2283,15 @@ call({func}, {arglist} [, {dict}]) *call()* *E699* {dict} is for functions with the "dict" attribute. It will be used to set the local variable "self". |Dictionary-function| +canceltimeout({nr}) *canceltimeout()* + Cancel the timeout or interval with id, {nr}, preventing it + from every firing. + Also see |settimeout()| and |setinterval()|. + {only available when compiled with the |+async| feature} + Examples: > + let timeout_id = settimeout(5000, 'echo(2)') + echo canceltimeout(timeout_id) + ceil({expr}) *ceil()* Return the smallest integral value greater than or equal to {expr} as a |Float| (round up). @@ -5187,6 +5198,23 @@ setcmdpos({pos}) *setcmdpos()* Returns 0 when successful, 1 when not editing the command line. +setinterval({nr}, {string}) *setinterval()* + Immediately returns an interval id and evaluate the expression, + {string}, every {nr} milliseconds. Intervals do not pile up. + The timer's resolution defaults to 100ms and can be changed by + setting |ticktime|. Intervals can be canceled by calling + |canceltimeout({interval_id})|. + NOTE: Vim is single-threaded and all expressions are run within + the main thread. Therefore, expressions should return control + flow within a short amount of time. + Also see |settimeout()| and |canceltimeout()|. + {only available when compiled with the |+async| feature} + Examples: > + :call setinterval(1000, "call echo(2)") +< 2 + 2 + 2 + setline({lnum}, {text}) *setline()* Set line {lnum} of the current buffer to {text}. To insert lines use |append()|. @@ -5356,6 +5384,21 @@ settabwinvar({tabnr}, {winnr}, {varname}, {val}) *settabwinvar()* :call settabwinvar(3, 2, "myvar", "foobar") < This function is not available in the |sandbox|. +settimeout({nr}, {string}) *settimeout()* + Immediately returns an interval id and evaluate the expression, + {string}, once after {nr} milliseconds. The timer's + resolution defaults to 100ms and can be changed by setting + |ticktime|. Timeouts can be canceled by calling + |canceltimeout({interval_id})|. + NOTE: Vim is single-threaded and all expressions are run within + the main thread. Therefore, expressions should return control + flow within a short amount of time. + Also see |setinterval()| and |canceltimeout()|. + {only available when compiled with the |+async| feature} + Examples: > + :call settimeout(1000, "call echo(2)") +< 2 + setwinvar({nr}, {varname}, {val}) *setwinvar()* Like |settabwinvar()| for the current tab page. Examples: > diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 0688fcc..e7174ff 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -7253,6 +7253,17 @@ A jump table for the options with a short description can be found at |Q_op|. uses another default. Backticks cannot be used in this option for security reasons. + *'ticktime'* *'tt'* +'ticktime' 'tt' number (default 100) + global + {not in Vi} + This is the resolution for all timers set with |setinterval()| and + |settimeout()|. Decreasing this number will make the timers + more accurate but will also make Vim less efficient. To globally + disable all timers for debugging, set |ticktime| to -1. + Also see |setinterval()|, |settimeout()|, and |canceltimeout()|. + {only available when compiled with the |+async| feature} + *'tildeop'* *'top'* *'notildeop'* *'notop'* 'tildeop' 'top' boolean (default off) global diff --git a/runtime/doc/tags b/runtime/doc/tags index f32ea6f..3e8e0f7 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -1014,6 +1014,7 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME* 'tf' options.txt /*'tf'* 'tgst' options.txt /*'tgst'* 'thesaurus' options.txt /*'thesaurus'* +'ticktime' options.txt /*'ticktime'* 'tildeop' options.txt /*'tildeop'* 'timeout' options.txt /*'timeout'* 'timeoutlen' options.txt /*'timeoutlen'* @@ -1032,6 +1033,7 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME* 'ts' options.txt /*'ts'* 'tsl' options.txt /*'tsl'* 'tsr' options.txt /*'tsr'* +'tt' options.txt /*'tt'* 'ttimeout' options.txt /*'ttimeout'* 'ttimeoutlen' options.txt /*'ttimeoutlen'* 'ttm' options.txt /*'ttm'* @@ -4987,6 +4989,7 @@ c_Up cmdline.txt /*c_Up* c_digraph cmdline.txt /*c_digraph* c_wildchar cmdline.txt /*c_wildchar* call() eval.txt /*call()* +canceltimeout() eval.txt /*canceltimeout()* carriage-return intro.txt /*carriage-return* case change.txt /*case* catch-all eval.txt /*catch-all* @@ -7653,6 +7656,7 @@ set-option options.txt /*set-option* set-spc-auto spell.txt /*set-spc-auto* setbufvar() eval.txt /*setbufvar()* setcmdpos() eval.txt /*setcmdpos()* +setinterval() eval.txt /*setinterval()* setline() eval.txt /*setline()* setloclist() eval.txt /*setloclist()* setmatches() eval.txt /*setmatches()* @@ -7661,6 +7665,7 @@ setqflist() eval.txt /*setqflist()* setreg() eval.txt /*setreg()* settabvar() eval.txt /*settabvar()* settabwinvar() eval.txt /*settabwinvar()* +settimeout() eval.txt /*settimeout()* setting-guifont gui.txt /*setting-guifont* setting-guitablabel tabpage.txt /*setting-guitablabel* setting-tabline tabpage.txt /*setting-tabline* diff --git a/src/Make_bc3.mak b/src/Make_bc3.mak index 54c42ac..dbf653d 100644 --- a/src/Make_bc3.mak +++ b/src/Make_bc3.mak @@ -52,6 +52,7 @@ SPAWNL = spawnl.lib EXE_dependencies = \ blowfish.obj \ + async.obj \ buffer.obj \ charset.obj \ diff.obj \ diff --git a/src/Make_bc5.mak b/src/Make_bc5.mak index 8172c1f..d93cf47 100644 --- a/src/Make_bc5.mak +++ b/src/Make_bc5.mak @@ -577,6 +577,7 @@ vimwinmain = \ !endif vimobj = \ + $(OBJDIR)\async.obj \ $(OBJDIR)\blowfish.obj \ $(OBJDIR)\buffer.obj \ $(OBJDIR)\charset.obj \ diff --git a/src/Make_cyg.mak b/src/Make_cyg.mak index f955b4d..7daf32b 100644 --- a/src/Make_cyg.mak +++ b/src/Make_cyg.mak @@ -527,6 +527,7 @@ RCFLAGS = -O coff $(DEFINES) OBJ = \ $(OUTDIR)/blowfish.o \ + $(OUTDIR)/async.o \ $(OUTDIR)/buffer.o \ $(OUTDIR)/charset.o \ $(OUTDIR)/diff.o \ diff --git a/src/Make_dice.mak b/src/Make_dice.mak index e3a8b9e..056a280 100644 --- a/src/Make_dice.mak +++ b/src/Make_dice.mak @@ -26,6 +26,7 @@ LD = dcc ${CC} ${PRE} ${CFLAGS} $< -o $@ SRC = \ + async.c \ blowfish.c \ buffer.c \ charset.c \ @@ -72,7 +73,8 @@ SRC = \ window.c \ version.c -OBJ = o/blowfish.o \ +OBJ = o/async.o \ + o/blowfish.o \ o/buffer.o \ o/charset.o \ o/diff.o \ @@ -137,6 +139,8 @@ $(SYMS) : vim.h globals.h keymap.h macros.h ascii.h term.h os_amiga.h structs.h ########################################################################### +o/async.o: async.c $(SYMS) + o/blowfish.o: blowfish.c $(SYMS) o/buffer.o: buffer.c $(SYMS) diff --git a/src/Make_djg.mak b/src/Make_djg.mak index f2e7c82..ce97da1 100644 --- a/src/Make_djg.mak +++ b/src/Make_djg.mak @@ -19,6 +19,7 @@ INCL = vim.h globals.h option.h keymap.h macros.h ascii.h term.h os_msdos.h stru CFLAGS = -O2 -DMSDOS -Iproto $(DEFINES) -Wall -Dinterrupt= -Dfar= -DMAXMEM=512 -D_NAIVE_DOS_REGS OBJ = \ + obj/async.o \ obj/blowfish.o \ obj/buffer.o \ obj/charset.o \ diff --git a/src/Make_ivc.mak b/src/Make_ivc.mak index 16589ea..32c29b4 100644 --- a/src/Make_ivc.mak +++ b/src/Make_ivc.mak @@ -210,6 +210,7 @@ ALL : .\$(VIM).exe vimrun.exe install.exe uninstal.exe xxd/xxd.exe GvimExt/gvime LINK32_OBJS= \ $(EXTRAS) \ + "$(INTDIR)/async.obj" \ "$(INTDIR)/blowfish.obj" \ "$(INTDIR)/buffer.obj" \ "$(INTDIR)/charset.obj" \ @@ -327,6 +328,10 @@ GvimExt/gvimext.dll: GvimExt/gvimext.cpp GvimExt/gvimext.rc GvimExt/gvimext.h # Begin Source File +SOURCE=.\async.c +# End Source File +# Begin Source File + SOURCE=.\blowfish.c # End Source File # Begin Source File diff --git a/src/Make_manx.mak b/src/Make_manx.mak index 101c5c6..1a16a4c 100644 --- a/src/Make_manx.mak +++ b/src/Make_manx.mak @@ -34,7 +34,8 @@ SHELL = csh REN = $(SHELL) -c mv -f DEL = $(SHELL) -c rm -f -SRC = blowfish.c \ +SRC = async.c \ + blowfish.c \ buffer.c \ charset.c \ diff.c \ @@ -82,7 +83,8 @@ SRC = blowfish.c \ INCL = vim.h feature.h keymap.h macros.h ascii.h term.h structs.h os_amiga.h -OBJ = obj/blowfish.o \ +OBJ = obj/async.o \ + obj/blowfish.o \ obj/buffer.o \ obj/charset.o \ obj/diff.o \ @@ -128,7 +130,8 @@ OBJ = obj/blowfish.o \ obj/window.o \ $(TERMLIB) -PRO = proto/blowfish.pro \ +PRO = proto/async.pro \ + proto/blowfish.pro \ proto/buffer.pro \ proto/charset.pro \ proto/diff.pro \ @@ -218,6 +221,9 @@ CCNOSYM = $(CC) $(CFLAGS) -o $(OBJ): $(SYMS) +obj/async.o: async.c + $(CCSYM) $@ async.c + obj/blowfish.o: blowfish.c $(CCSYM) $@ blowfish.c diff --git a/src/Make_ming.mak b/src/Make_ming.mak index 7aa3994..46a7e14 100644 --- a/src/Make_ming.mak +++ b/src/Make_ming.mak @@ -502,6 +502,7 @@ endif LIB = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomdlg32 -lcomctl32 -lversion GUIOBJ = $(OUTDIR)/gui.o $(OUTDIR)/gui_w32.o $(OUTDIR)/gui_beval.o $(OUTDIR)/os_w32exe.o OBJ = \ + $(OUTDIR)/async.o \ $(OUTDIR)/blowfish.o \ $(OUTDIR)/buffer.o \ $(OUTDIR)/charset.o \ diff --git a/src/Make_morph.mak b/src/Make_morph.mak index aa8fbd9..66b74d6 100644 --- a/src/Make_morph.mak +++ b/src/Make_morph.mak @@ -24,7 +24,8 @@ RM = rm .c.o: ${CC} ${CFLAGS} $< -o $@ -SRC = blowfish.c \ +SRC = async.c \ + blowfish.c \ buffer.c \ charset.c \ diff.c \ diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index f23258b..7f90d65 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -525,6 +525,7 @@ INCL = vim.h os_win32.h ascii.h feature.h globals.h keymap.h macros.h \ $(NBDEBUG_INCL) OBJ = \ + $(OUTDIR)\async.obj \ $(OUTDIR)\blowfish.obj \ $(OUTDIR)\buffer.obj \ $(OUTDIR)\charset.obj \ @@ -1055,6 +1056,8 @@ testclean: !ENDIF $(CC) $(CFLAGS) $< +$(OUTDIR)/async.obj: $(OUTDIR) async.c $(INCL) + $(OUTDIR)/blowfish.obj: $(OUTDIR) blowfish.c $(INCL) $(OUTDIR)/buffer.obj: $(OUTDIR) buffer.c $(INCL) diff --git a/src/Make_os2.mak b/src/Make_os2.mak index 42dbdb3..102a17a 100644 --- a/src/Make_os2.mak +++ b/src/Make_os2.mak @@ -39,6 +39,7 @@ INCL = vim.h globals.h option.h keymap.h macros.h ascii.h term.h os_unix.h struc CFLAGS = -O2 -fno-strength-reduce -DOS2 -Wall -Iproto $(DEFINES) OBJ = \ + async.o \ blowfish.o \ buffer.o \ charset.o \ diff --git a/src/Make_sas.mak b/src/Make_sas.mak index bf57c0d..2258165 100644 --- a/src/Make_sas.mak +++ b/src/Make_sas.mak @@ -136,6 +136,7 @@ SRC = \ version.c OBJ = \ + async.o \ blowfish.o \ buffer.o \ charset.o \ @@ -183,6 +184,7 @@ OBJ = \ $(TERMLIB) PRO = \ + proto/async.pro \ proto/blowfish.pro \ proto/buffer.pro \ proto/charset.pro \ @@ -284,6 +286,8 @@ $(PRO): $(GST) vim.h $(CC) $(CFLAGS) GPFILE=proto/$*.pro $(PROPT) $*.c # dependencies +async.o: async.c +proto/async.pro: async.c blowfish.o: blowfish.c proto/blowfish.pro: blowfish.c buffer.o: buffer.c diff --git a/src/Make_vms.mms b/src/Make_vms.mms index 86b61d6..3f61421 100644 --- a/src/Make_vms.mms +++ b/src/Make_vms.mms @@ -304,7 +304,7 @@ ALL_CFLAGS_VER = /def=($(MODEL_DEF)$(DEFS)$(VMS_DEF)$(DEBUG_DEF)$(PERL_DEF)$(PYT ALL_LIBS = $(LIBS) $(GUI_LIB_DIR) $(GUI_LIB) \ $(PERL_LIB) $(PYTHON_LIB) $(TCL_LIB) $(SNIFF_LIB) $(RUBY_LIB) -SRC = blowfish.c buffer.c charset.c diff.c digraph.c edit.c eval.c ex_cmds.c ex_cmds2.c \ +SRC = async.c blowfish.c buffer.c charset.c diff.c digraph.c edit.c eval.c ex_cmds.c ex_cmds2.c \ ex_docmd.c ex_eval.c ex_getln.c if_xcmdsrv.c fileio.c fold.c getchar.c \ hardcopy.c hashtab.c main.c mark.c menu.c mbyte.c memfile.c memline.c message.c misc1.c \ misc2.c move.c normal.c ops.c option.c popupmnu.c quickfix.c regexp.c search.c sha256.c\ @@ -313,7 +313,7 @@ SRC = blowfish.c buffer.c charset.c diff.c digraph.c edit.c eval.c ex_cmds.c ex_ $(GUI_SRC) $(PERL_SRC) $(PYTHON_SRC) $(TCL_SRC) $(SNIFF_SRC) \ $(RUBY_SRC) $(HANGULIN_SRC) $(MZSCH_SRC) -OBJ = blowfish.obj buffer.obj charset.obj diff.obj digraph.obj edit.obj eval.obj \ +OBJ = async.obj blowfish.obj buffer.obj charset.obj diff.obj digraph.obj edit.obj eval.obj \ ex_cmds.obj ex_cmds2.obj ex_docmd.obj ex_eval.obj ex_getln.obj \ if_xcmdsrv.obj fileio.obj fold.obj getchar.obj hardcopy.obj hashtab.obj main.obj mark.obj \ menu.obj memfile.obj memline.obj message.obj misc1.obj misc2.obj \ diff --git a/src/Makefile b/src/Makefile index c830378..d6ee8c9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1424,6 +1424,7 @@ DEST_MAN_RU_U = $(DEST_MAN_TOP)/ru.UTF-8$(MAN1DIR) TAGS_INCL = *.h BASIC_SRC = \ + async.c \ blowfish.c \ buffer.c \ charset.c \ @@ -1513,6 +1514,7 @@ LINT_SRC = $(BASIC_SRC) $(GUI_SRC) $(HANGULIN_SRC) $(PYTHON_SRC) $(PYTHON3_SRC) #LINT_SRC = $(BASIC_SRC) OBJ_COMMON = \ + objects/async.o \ objects/buffer.o \ objects/blowfish.o \ objects/charset.o \ @@ -1582,6 +1584,7 @@ MEMFILE_TEST_OBJ = $(OBJ_COMMON) \ objects/memfile_test.o PRO_AUTO = \ + async.pro \ blowfish.pro \ buffer.pro \ charset.pro \ @@ -2484,6 +2487,9 @@ auto/pathdef.c: Makefile auto/config.mk objects: mkdir objects +objects/async.o: async.c + $(CCC) -o $@ async.c + objects/blowfish.o: blowfish.c $(CCC) -o $@ blowfish.c @@ -2830,6 +2836,9 @@ $(APPDIR)/Contents: ############################################################################### ### (automatically generated by 'make depend') ### Dependencies: +objects/async.o: async.c vim.h auto/config.h feature.h os_unix.h os_mac.h ascii.h \ + keymap.h term.h macros.h option.h structs.h regexp.h gui.h ex_cmds.h \ + proto.h proto/async.pro globals.h farsi.h arabic.h auto/osdef.h objects/blowfish.o: blowfish.c vim.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \ regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \ diff --git a/src/async.c b/src/async.c new file mode 100644 index 0000000..1f76b92 --- /dev/null +++ b/src/async.c @@ -0,0 +1,89 @@ +#include "vim.h" + +#ifdef FEAT_ASYNC + +/* + * Return monotonic time, if available. Fall back to gettimeofday otherwise. + */ + unsigned long long +get_monotonic_time(void) +{ + unsigned long long tm; +#ifdef MCH_MONOTONIC_TIME + tm = mch_monotonic_time(); +#else + struct timeval now; + gettimeofday(&now, NULL); + tm = now.tv_sec * 1000 + now.tv_usec/1000; +#endif + return tm; +} + + +/* + * Insert a new timeout into the timeout linked list. + * This is called by set_timeout() in eval.c + */ + void +insert_timeout(to) + timeout_T *to; /* timeout to insert */ +{ + timeout_T *cur = timeouts; + timeout_T *prev = NULL; + + if (timeouts == NULL) { + timeouts = to; + return; + } + while (cur != NULL) + { + if (cur->tm > to->tm) + { + if (prev) + { + prev->next = to; + } + else + { + timeouts = to; + } + to->next = cur; + return; + } + prev = cur; + cur = cur->next; + } + prev->next = to; + to->next = NULL; +} + +/* + * Execute timeouts that are due. + * This is called every ticktime milliseconds by low-level input functions. + */ + void +call_timeouts(void) +{ + unsigned long long tm = get_monotonic_time(); + timeout_T *tmp; + int retval; + + while (timeouts != NULL && timeouts->tm < tm) + { + retval = do_cmdline_cmd(timeouts->cmd); + tmp = timeouts; + timeouts = timeouts->next; + if (tmp->interval == -1 || retval == FAIL || (!got_int && (did_throw || did_emsg))) + { + free(tmp->cmd); + free(tmp); + } + else + { + tmp->tm = tm + tmp->interval; + insert_timeout(tmp); + } + } +} + +#endif diff --git a/src/auto/configure b/src/auto/configure index a9755a0..64ec51e 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -11072,6 +11072,57 @@ if test "x$vim_cv_getcwd_broken" = "xyes" ; then fi + +for ac_func in clock_gettime +do : + ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" +if test "x$ac_cv_func_clock_gettime" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CLOCK_GETTIME 1 +_ACEOF +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5 +$as_echo_n "checking for clock_gettime in -lrt... " >&6; } +if ${ac_cv_lib_rt_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rt_clock_gettime=yes +else + ac_cv_lib_rt_clock_gettime=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5 +$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; } +if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then : + LIBS="$LIBS -lrt" +fi +fi +done + for ac_func in bcmp fchdir fchown fsync getcwd getpseudotty \ getpwent getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \ memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \ diff --git a/src/configure.in b/src/configure.in index ed30bed..5f47547 100644 --- a/src/configure.in +++ b/src/configure.in @@ -3240,6 +3240,13 @@ if test "x$vim_cv_getcwd_broken" = "xyes" ; then AC_DEFINE(BAD_GETCWD) fi +AC_CHECK_FUNCS(clock_gettime, [], [ + AC_CHECK_LIB(rt, clock_gettime, [ + LIBS="$LIBS -lrt" + ]) +]) + + dnl Check for functions in one big call, to reduce the size of configure. dnl Can only be used for functions that do not require any include. AC_CHECK_FUNCS(bcmp fchdir fchown fsync getcwd getpseudotty \ diff --git a/src/eval.c b/src/eval.c index 807efe2..7259ba0 100644 --- a/src/eval.c +++ b/src/eval.c @@ -674,6 +674,11 @@ struct funccall_S static void f_setloclist __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setmatches __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setpos __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_ASYNC +static void f_canceltimeout __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_setinterval __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_settimeout __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv)); static void f_settabvar __ARGS((typval_T *argvars, typval_T *rettv)); @@ -7861,6 +7866,9 @@ struct funccall_S {"byte2line", 1, 1, f_byte2line}, {"byteidx", 2, 2, f_byteidx}, {"call", 2, 3, f_call}, +#ifdef FEAT_ASYNC + {"canceltimeout", 1, 1, f_canceltimeout}, +#endif #ifdef FEAT_FLOAT {"ceil", 1, 1, f_ceil}, #endif @@ -8059,6 +8067,9 @@ struct funccall_S {"serverlist", 0, 0, f_serverlist}, {"setbufvar", 3, 3, f_setbufvar}, {"setcmdpos", 1, 1, f_setcmdpos}, +#ifdef FEAT_ASYNC + {"setinterval", 2, 2, f_setinterval}, +#endif {"setline", 2, 2, f_setline}, {"setloclist", 2, 3, f_setloclist}, {"setmatches", 1, 1, f_setmatches}, @@ -8067,6 +8078,9 @@ struct funccall_S {"setreg", 2, 3, f_setreg}, {"settabvar", 3, 3, f_settabvar}, {"settabwinvar", 4, 4, f_settabwinvar}, +#ifdef FEAT_ASYNC + {"settimeout", 2, 2, f_settimeout}, +#endif {"setwinvar", 3, 3, f_setwinvar}, #ifdef FEAT_CRYPT {"sha256", 1, 1, f_sha256}, @@ -12416,6 +12430,9 @@ struct funccall_S #ifdef FEAT_RELTIME "reltime", #endif +#ifdef FEAT_ASYNC + "async", +#endif #ifdef FEAT_QUICKFIX "quickfix", #endif @@ -16589,6 +16606,91 @@ struct funccall_S #endif } +#ifdef FEAT_ASYNC +static int timeout_id = 0; + + static void +set_timeout(argvars, rettv, interval) + typval_T *argvars; + typval_T *rettv; + int interval; +{ + long i = get_tv_number(&argvars[0]); + char_u *cmd = get_tv_string(&argvars[1]); + rettv->v_type = VAR_NUMBER; + + if (i < 0) { + rettv->vval.v_number = -1; + EMSG2(_(e_invarg2), "Interval cannot be negative."); + return; + } + + timeout_T *to = malloc(sizeof(timeout_T)); + to->id = timeout_id++; + to->tm = get_monotonic_time() + i; + rettv->vval.v_number = to->id; + to->cmd = (char_u*)strdup((char*)cmd); + to->interval = interval ? i : -1; + to->next = NULL; + + insert_timeout(to); +} + + static void +f_setinterval(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + set_timeout(argvars, rettv, TRUE); +} + + static void +f_settimeout(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + set_timeout(argvars, rettv, FALSE); +} + + static void +f_canceltimeout(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + long id = get_tv_number(&argvars[0]); + if (id < 0) { + rettv->vval.v_number = -1; + EMSG2(_(e_invarg2), "Timeout id cannot be negative."); + return; + } + + timeout_T *tmp = timeouts; + timeout_T *prev = NULL; + timeout_T *next; + while (tmp != NULL) { + next = tmp->next; + if (tmp->id == id) { + if (prev) { + prev->next = next; + } else { + timeouts = next; + } + free(tmp->cmd); + free(tmp); + rettv->vval.v_number = 0; + rettv->v_type = VAR_NUMBER; + return; + } else { + prev = tmp; + } + tmp = next; + } + rettv->vval.v_number = 1; + rettv->v_type = VAR_NUMBER; + EMSG2(_(e_invarg2), "Timeout id not found."); +} +#endif + /* * "setpos()" function */ diff --git a/src/feature.h b/src/feature.h index d4b9aea..d12a3d2 100644 --- a/src/feature.h +++ b/src/feature.h @@ -467,6 +467,14 @@ #endif /* + * +async settimeout and setinterval functions. + */ +#if defined(FEAT_NORMAL) && defined(MSWIN) || defined(MACOS_X) || \ + defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) +# define FEAT_ASYNC +#endif + +/* * +diff Displaying diffs in a nice way. * Requires +windows and +autocmd. */ diff --git a/src/globals.h b/src/globals.h index feb1dd4..615cce9 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1626,3 +1626,8 @@ #ifdef FEAT_ARABIC # include "arabic.h" #endif + +/* + * For keeping track of timeouts. + */ +EXTERN timeout_T *timeouts INIT(= NULL); diff --git a/src/gui.c b/src/gui.c index b667ba3..7387359 100644 --- a/src/gui.c +++ b/src/gui.c @@ -2863,6 +2863,7 @@ enum { long wtime; { int retval; + int i = 0; #ifdef FEAT_MENU /* @@ -2898,18 +2899,31 @@ enum { gui_mch_start_blink(); retval = FAIL; + + i = 0; + while (i < p_ut) { +#ifdef FEAT_ASYNC + retval = gui_mch_wait_for_chars(p_tt); + call_timeouts(); + i += p_tt; +#else + retval = gui_mch_wait_for_chars(p_ut); + i += p_ut; +#endif + if (retval == OK) { + break; + } + } + +#ifdef FEAT_AUTOCMD /* * We may want to trigger the CursorHold event. First wait for * 'updatetime' and if nothing is typed within that time put the * K_CURSORHOLD key in the input buffer. */ - if (gui_mch_wait_for_chars(p_ut) == OK) - retval = OK; -#ifdef FEAT_AUTOCMD - else if (trigger_cursorhold()) + if (retval == FAIL && trigger_cursorhold()) { char_u buf[3]; - /* Put K_CURSORHOLD in the input buffer. */ buf[0] = CSI; buf[1] = KS_EXTRA; @@ -2920,13 +2934,6 @@ enum { } #endif - if (retval == FAIL) - { - /* Blocking wait. */ - before_blocking(); - retval = gui_mch_wait_for_chars(-1L); - } - gui_mch_stop_blink(); return retval; } diff --git a/src/main.aap b/src/main.aap index 3c91d39..bd53ce0 100644 --- a/src/main.aap +++ b/src/main.aap @@ -290,6 +290,7 @@ testclean {virtual}: # Some are optional and depend on configure. # "version.c" is missing, it's always compiled (see below). Source = + async.c blowfish.c buffer.c charset.c diff --git a/src/option.c b/src/option.c index bf65556..b78809f 100644 --- a/src/option.c +++ b/src/option.c @@ -2590,6 +2590,14 @@ struct vimoption (char_u *)NULL, PV_NONE, #endif {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {"ticktime", "tt", P_NUM|P_VI_DEF, +#ifdef FEAT_ASYNC + (char_u *)&p_tt, PV_NONE, +#else + (char_u *)NULL, PV_NONE, +#endif + {(char_u *)100L, (char_u *)0L} SCRIPTID_INIT}, + {"tildeop", "top", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_to, PV_NONE, {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, diff --git a/src/option.h b/src/option.h index 167b562..ae2ba22 100644 --- a/src/option.h +++ b/src/option.h @@ -795,6 +795,9 @@ #ifdef FEAT_INS_EXPAND EXTERN char_u *p_tsr; /* 'thesaurus' */ #endif +#ifdef FEAT_ASYNC +EXTERN long p_tt; /* 'ticktime' */ +#endif EXTERN int p_ttimeout; /* 'ttimeout' */ EXTERN long p_ttm; /* 'ttimeoutlen' */ EXTERN int p_tbi; /* 'ttybuiltin' */ diff --git a/src/os_macosx.m b/src/os_macosx.m index d919f63..1b8c5b5 100644 --- a/src/os_macosx.m +++ b/src/os_macosx.m @@ -23,6 +23,22 @@ #include "vim.h" #import <Cocoa/Cocoa.h> +#include <mach/mach.h> +#include <mach/mach_time.h> + + +#define MCH_MONOTONIC_TIME + unsigned long long +mch_monotonic_time(void) +{ + mach_timebase_info_data_t info; + + if (mach_timebase_info(&info) != KERN_SUCCESS) + abort(); + + return (mach_absolute_time() * info.numer / info.denom) / 1000000; +} + /* * Clipboard support for the console. diff --git a/src/os_unix.c b/src/os_unix.c index cc02653..bd2d6dc 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -892,6 +892,17 @@ catch_sigpwr SIGDEFARG(sigarg) } #endif +#if !defined(MACOS_X_UNIX) +#define MCH_MONOTONIC_TIME + unsigned long long +mch_monotonic_time(void) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; +} +#endif + #ifdef SET_SIG_ALARM /* * signal function for alarm(). @@ -5057,7 +5068,7 @@ sigcont_handler SIGDEFARG(sigarg) #ifdef FEAT_NETBEANS_INTG int nb_fd = netbeans_filedesc(); #endif -#if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME) +#if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME) || defined(FEAT_ASYNC) static int busy = FALSE; /* May retry getting characters after an event was handled. */ @@ -5072,18 +5083,24 @@ sigcont_handler SIGDEFARG(sigarg) if (msec > 0 && ( # ifdef FEAT_XCLIPBOARD xterm_Shell != (Widget)0 -# if defined(USE_XSMP) || defined(FEAT_MZSCHEME) +# if defined(USE_XSMP) || defined(FEAT_MZSCHEME) || defined(FEAT_ASYNC) || # endif # endif # ifdef USE_XSMP xsmp_icefd != -1 -# ifdef FEAT_MZSCHEME +# if defined(FEAT_MZSCHEME) || defined(FEAT_ASYNC) || # endif # endif # ifdef FEAT_MZSCHEME (mzthreads_allowed() && p_mzq > 0) +# ifdef FEAT_ASYNC + || +# endif +# endif +# ifdef FEAT_ASYNC + TRUE # endif )) gettimeofday(&start_tv, NULL); @@ -5130,6 +5147,12 @@ sigcont_handler SIGDEFARG(sigarg) mzquantum_used = TRUE; } # endif +# ifdef FEAT_ASYNC + call_timeouts(); + if (p_tt > 0 && (msec < 0 || msec > p_tt)) { + towait = p_tt; + } +# endif fds[0].fd = fd; fds[0].events = POLLIN; nfd = 1; @@ -5257,6 +5280,12 @@ sigcont_handler SIGDEFARG(sigarg) mzquantum_used = TRUE; } # endif +# ifdef FEAT_ASYNC + call_timeouts(); + if (p_tt > 0 && (msec < 0 || msec > p_tt)) { + towait = p_tt; + } +# endif # ifdef __EMX__ /* don't check for incoming chars if not in raw mode, because select() * always returns TRUE then (in some version of emx.dll) */ @@ -5369,6 +5398,10 @@ sigcont_handler SIGDEFARG(sigarg) /* loop if MzThreads must be scheduled and timeout occurred */ finished = FALSE; # endif +# ifdef FEAT_ASYNC + if (ret == 0 && msec > p_tt) + finished = FALSE; +# endif # ifdef FEAT_SNIFF if (ret < 0 ) @@ -7367,5 +7400,4 @@ sig_sysmouse SIGDEFARG(sigarg) 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233, }; - #endif diff --git a/src/os_win32.c b/src/os_win32.c index f36dfb3..335bbc1 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -29,6 +29,7 @@ #include <sys/types.h> #include <signal.h> #include <limits.h> +#include <math.h> /* cproto fails on missing include files */ #ifndef PROTO @@ -634,6 +635,52 @@ typedef DWORD (WINAPI *PGNSECINFOW) (LPWSTR, SE_OBJECT_TYPE, } } + unsigned long long +mch_monotonic_time(void) +{ + static ULONGLONG (*GetTickCount64) (void) = NULL; + static ULONGLONG (CALLBACK *_GetTickCount64)(void); + static int has_getickcount64 = -1; + ULONGLONG result; + OSVERSIONINFO ovi; + + ovi.dwOSVersionInfoSize = sizeof(ovi); + GetVersionEx(&ovi); + + if (has_getickcount64 == -1) + { + /* GetTickCount64() was added to Windows Vista */ + if (ovi.dwMajorVersion >= 6) + { + HINSTANCE hKernel32 = GetModuleHandleW(L"KERNEL32"); + *(FARPROC*)&_GetTickCount64 = GetProcAddress(hKernel32, + "GetTickCount64"); + has_getickcount64 = (_GetTickCount64 != NULL); + } + else + has_getickcount64 = 0; + } + + if (has_getickcount64) + { + result = _GetTickCount64(); + } + else + { + static DWORD last_ticks = 0; + static DWORD n_overflow = 0; + DWORD ticks; + + ticks = GetTickCount(); + if (ticks < last_ticks) + n_overflow++; + last_ticks = ticks; + + result = (unsigned long long)ldexp(n_overflow, 32); + result += ticks; + } + return result; +} /* * Return TRUE when running on Windows 95 (or 98 or ME). * Only to be used after mch_init(). diff --git a/src/os_win32.h b/src/os_win32.h index 58b179f..9145527 100644 --- a/src/os_win32.h +++ b/src/os_win32.h @@ -56,6 +56,7 @@ #define HAVE_ST_MODE /* have stat.st_mode */ #define FEAT_SHORTCUT /* resolve shortcuts */ +#define MCH_MONOTONIC_TIME /* for async */ #if (!defined(__BORLANDC__) || __BORLANDC__ >= 0x550) \ && (!defined(_MSC_VER) || _MSC_VER > 1020) diff --git a/src/proto.h b/src/proto.h index 191ecd8..135aff9 100644 --- a/src/proto.h +++ b/src/proto.h @@ -293,3 +293,7 @@ # define _PROTO_H #endif #endif /* !PROTO && !NOPROTO */ + +#ifdef FEAT_ASYNC +# include "async.pro" +#endif \ No newline at end of file diff --git a/src/proto/async.pro b/src/proto/async.pro new file mode 100644 index 0000000..006475f --- /dev/null +++ b/src/proto/async.pro @@ -0,0 +1,5 @@ +/* async.c */ +unsigned long long get_monotonic_time __ARGS((void)); +void insert_timeout __ARGS((timeout_T *to)); +void call_timeouts __ARGS((void)); +/* vim: set ft=c : */ diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro index e4cad51..632179e 100644 --- a/src/proto/os_unix.pro +++ b/src/proto/os_unix.pro @@ -6,6 +6,7 @@ int mch_char_avail __ARGS((void)); long_u mch_total_mem __ARGS((int special)); void mch_delay __ARGS((long msec, int ignoreinput)); int mch_stackcheck __ARGS((char *p)); +unsigned long long mch_monotonic_time __ARGS((void)); void mch_startjmp __ARGS((void)); void mch_endjmp __ARGS((void)); void mch_didjmp __ARGS((void)); diff --git a/src/proto/os_win32.pro b/src/proto/os_win32.pro index a4c590f..5db7ba2 100644 --- a/src/proto/os_win32.pro +++ b/src/proto/os_win32.pro @@ -55,4 +55,5 @@ void free_cmd_argsW __ARGS((void)); void used_file_arg __ARGS((char *name, int literal, int full_path, int diff_mode)); void set_alist_count __ARGS((void)); void fix_arg_enc __ARGS((void)); +unsigned long long mch_monotonic_time __ARGS((void)); /* vim: set ft=c : */ diff --git a/src/structs.h b/src/structs.h index f74d218..8a0fb2d 100644 --- a/src/structs.h +++ b/src/structs.h @@ -2540,3 +2540,17 @@ struct VimMenu UINT32_T state[8]; char_u buffer[64]; } context_sha256_T; + +#ifdef FEAT_ASYNC +/* + * Used for async settimeout/interval. + */ +struct timeout_T { + int id; /* timeout/interval id */ + int interval; /* interval period if interval, otherwise -1 */ + unsigned long long tm; /* time to fire (epoch milliseconds) */ + char_u *cmd; /* vim command to run */ + struct timeout_T *next; /* pointer to next timeout in linked list */ +}; +typedef struct timeout_T timeout_T; +#endif diff --git a/src/version.c b/src/version.c index ef3f9b1..f98a1b5 100644 --- a/src/version.c +++ b/src/version.c @@ -77,6 +77,11 @@ #else "-arabic", #endif +#ifdef FEAT_ASYNC + "+async", +#else + "-async", +#endif #ifdef FEAT_AUTOCMD "+autocmd", #else -- 1.8.4
