[prev in list] [next in list] [prev in thread] [next in thread] 

List:       vim-dev
Subject:    Using threading to remove blocking
From:       Vince Negri <vnegri () asl-electronics ! co ! uk>
Date:       2002-11-14 8:53:29
[Download RAW message or body]

Just to recap the idea floated here about using
threading to get the main vim loop detached from
GUI event processing....

Vim has got an internal queue where keypresses
(and other events which are treated as user input, like
mouse clicks) are stored. At the moment, if the
queue is empty it spins, despatching incoming GUI
messages in the meantime. However this is not allowable
behaviour for an in-process component.

If we first look at the basic structure of a
"Normal" event-driven GUI app:
-----------------------------------------
Canonical Windows/QT/GTK+ app:

while(1)
{
	wait for a GUI message;
	
	process_the_message;
}

-----------------------------------------


Vim works in a slightly different way, so that
it can keep as much common code with non-event
driven frameworks (console versions) as possible:
-----------------------------------------
Vim:

mainloop()
{
	while (1)
	{
		if there are queued keys
			action them;
		else
			wait_for_key();
	}
}

wait_for_key()
{
	while (no keys in queue)
	{
		wait for a GUI message;
		if (its a key)
			put it on the queue;
		else
			process_the_message;
	}
}
-----------------------------------------


To make a non-blocking build, the old
mainloop() has to go into a thread, so that
it can wait (in a cpu-friendly manner) for
the next event without having to take over
message dispatch.

-----------------------------------------
Non-blocking Vim (as app):

void main()
{
	createthread(mainloop);

	while(1)
	{
		wait for a GUI message;
		if (its a key)
		{
			EnterCriticalSection;
			put it on the queue;
			LeaveCriticalSection;
		}
		else
			process_the_message;
	}
}

mainloop()
{
	while (1)
	{
		EnterCriticalSection;
		pull keys off queue if any;
		LeaveCriticalSection;
		if there were queued keys
			action them;
		else
			sleep, waiting on key queue;
	}
}
-----------------------------------------

To use this as a component, we put the
createthread(mainloop) call into our
init_component() routine and then the

		if (its a key)
		{
			EnterCriticalSection;
			put it on the queue;
			LeaveCriticalSection;
		}
		else
			process_the_message;

code fragment becomes the component's
main messageproc. The part of the component
running its parent's thread is then no
longer a loop, just a procedure to which
the parent passes messages. If Vim is waiting
for a key, that is going on in the background
thread.

Obviously the actual implementation might need
a few more critical sections added here and there,
but I hope you can see that this build variant
could be accommodated inside the main code tree
without disrupting existing builds, or having to
turn Vim inside out.

Vince 

Legal Disclaimer: Any views expressed by the sender of this message are
not necessarily those of Application Solutions Ltd. Information in this 
e-mail may be confidential and is for the use of the intended recipient
only, no mistake in transmission is intended to waive or compromise such 
privilege. Please advise the sender if you receive this e-mail by mistake.

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic