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

-- 
-- 
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 fcaa67ea4973385875f37749e00fd80cf3ba55d7 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             |  88 +++++++++++++++++++++++++++++++++++++++++
 src/async.h             |   5 +++
 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 +++
 37 files changed, 476 insertions(+), 24 deletions(-)
 create mode 100644 src/async.c
 create mode 100644 src/async.h
 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..d5ceb51 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
 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..f8cab24
--- /dev/null
+++ b/src/async.c
@@ -0,0 +1,88 @@
+#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;
+
+	while (timeouts != NULL && timeouts->tm < tm)
+	{
+		do_cmdline_cmd(timeouts->cmd);
+		tmp = timeouts;
+		timeouts = timeouts->next;
+		if (tmp->interval == -1)
+		{
+			free(tmp->cmd);
+			free(tmp);
+		} 
+		else
+		{
+			tmp->tm = tm + tmp->interval;
+			insert_timeout(tmp);
+		}
+	}
+}
+
+#endif
diff --git a/src/async.h b/src/async.h
new file mode 100644
index 0000000..89ec60f
--- /dev/null
+++ b/src/async.h
@@ -0,0 +1,5 @@
+
+EXTERN timeout_T *timeouts INIT(= NULL);
+
+void insert_timeout(timeout_T *to);
+void call_timeouts(void);
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 @@ static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
 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 @@ static struct fst
     {"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 @@ static struct fst
     {"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 @@ static struct fst
     {"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 @@ f_has(argvars, rettv)
 #ifdef FEAT_RELTIME
 	"reltime",
 #endif
+#ifdef FEAT_ASYNC
+    "async",
+#endif
 #ifdef FEAT_QUICKFIX
 	"quickfix",
 #endif
@@ -16589,6 +16606,91 @@ f_setmatches(argvars, rettv)
 #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 @@ EXTERN char *ignoredp;
 #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 @@ gui_wait_for_chars(wtime)
     long    wtime;
 {
     int	    retval;
+    int i = 0;
 
 #ifdef FEAT_MENU
     /*
@@ -2898,18 +2899,31 @@ gui_wait_for_chars(wtime)
     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 @@ gui_wait_for_chars(wtime)
     }
 #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 @@ static 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 @@ EXTERN char_u	*p_titlestring;	/* 'titlestring' */
 #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 @@ RealWaitForChar(fd, msec, check_for_gpm)
 #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 @@ RealWaitForChar(fd, msec, check_for_gpm)
     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 @@ RealWaitForChar(fd, msec, check_for_gpm)
 	    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 @@ RealWaitForChar(fd, msec, check_for_gpm)
 	    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 @@ select_eintr:
 	    /* 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 @@ char CtrlCharTable[]=
       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 @@ PlatformId(void)
     }
 }
 
+	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 @@ void clip_mch_set_selection(VimClipboard *cbd);
 # 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 @@ typedef struct {
   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 @@ static char *(features[]) =
 #else
 	"-arabic",
 #endif
+#ifdef FEAT_ASYNC
+	"+async",
+#else
+	"-async",
+#endif
 #ifdef FEAT_AUTOCMD
 	"+autocmd",
 #else
-- 
1.8.2.2

Raspunde prin e-mail lui