Multi interface thoughts

Multi-interface

libcurl's multi interface introduces several new abilities that the easy interface refuses to offer. They are mainly:

From TclCurl's point of view, supporting the interface will give us two main benefits:

For the time being, if you want to take a look at libcurl's multi-interface you will have to download the man pages from the cvs.

Interface proposal

The following are my first thoughts about how the interface should look like, as usual I hardly know what I am talking about, so please, feel free to tell me what I fool I am. (By the way, I am not kidding)

To use the multi interface, we should first first create a 'multi handle' with curl::multi::init, or maybe curl::multiInit, this procedure will return the handle to use as input to all further procedures.

Each single transfer is built up with an 'easy' handle, the kind we have been using so far with TclCurl, you must create them and setup the appropriate options for each of them. Then we add them to the 'multi stack' using the addHandle command.

When the easy handles are setup for a transfer we get to transfer something with the perform command.

If we want to stop a transfer before it is completed, we can use the removeHandle command. Once removed from the multi handle, we can again use other easy interface functions.

Adding the easy handles to the multi handle does not start any transfer. Remember that one of the main ideas with this interface is to let your application drive. You drive the transfers by invoking perform. TclCurl will then transfer data if there is anything available to transfer. It'll use the callbacks and everything else we have setup in the individual easy handles. It'll transfer data on all current transfers in the multi stack that are ready to transfer anything. It may be all, it may be none.

Applications can acquire knowledge from TclCurl when it would like to get invoked to transfer data, so that you don't have to busy-loop and call that perform like a mad man! fdset will return the number of transfers that want to do something at the time. This should make it easy for our programs to wait for input or perhaps timeout every now and then.

perform will have to tell us how many transfers are active, so that it they drop to zero, we will know they are all done. 'done' does not mean successful. One or more of the transfers may have failed.

To get information about completed transfers, to figure out success or not and similar, getinfo should be called. It can return a message about a current or previous transfer. Repeated invokes of the function get more messages until the message queue is empty.

When all transfers in the multi stack are done, cleanup the multi handle with cleanup or maybe simply cleanup. Be careful and please note that you MUST invoke separate cleanup calls on every single easy handle to clean them up properly.

Example

It may be easier to know what I am talking about with a little example:

	set multiHandle [curl::multi::init]
	set easyHandle1 [curl::init]
	set easyHandle2 [curl::init]

	$easyHandle1 configure -url http://personal1.iddeo.es/tclcurl/download/tarball/TclCurl-1.0.tar.gz
	$easyHandle1 configure -url http://personal1.iddeo.es/tclcurl/english/index.html

	$multiHandle addHandle $easyHandle1
	$multlHandle addHandle $easyHandle2

	for {set running 1} {$running>0} {} {
	    # Whatever you code should do
	    set running [$multiHandle perform]
	}

	$multiHandle cleanup
	$easyHandle1 cleanup
	$easyHandle2 cleanup

Ramblings

The example may look quite simple, specially compared to using threads, but it is still a lot of work if you only want to do a simple transfer while keeping the GUI responsive, we need something like curl::transfer, a procedure that returns inmediately and takes care of the transfer on its own.

So, what do you think?


Andrés García