lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On 10/31/11, PooshhMao <pooshhmao@gmail.com> wrote:
> Hi,
>
> I'm trying to wrap my head around how to use coroutines properly.
> A function in my program iterates over a directory and inserts all found
> files into a
> table. Next, I need to do some stuff with this table, and iterate over
> it to insert the files into an SQL database.
> /
> *--FUNCTIONAL NON-COROUTINE VERSION*
>
> local D,P=Database,ProgressBar
> local Files=IterateDir() *--returns the table*
>
> if D:transaction() then *--prepare database for transaction*
> //    P:setMaximum(#Files) *--set the progressbar maximum value to the
> amount of files in the table*/
> /        for FileName,Extension in pairs(Files)do
>              D:exec('insert into
> Files("'..Filename..'","'..Extension..'")') *--execute SQL query*
>              P:setValue(ProgressBar:value()+1) *--step the progressbar
> *end*
> *            if D:commit() then *--commit the database*
>                  print'Operation finished, database updated succesfully'
>                  P:reset() *--reset the progressbar*
>              end
> end/
>
> Using some examples I've found on the internet, I'm trying to wrap the
> loop in a coroutine, however I'm not quite sure
> how to implement coroutine.yield() in this case (hence Lua returns the
> error 'cannot resume dead coroutine')
> /
> *--DYSFUNCTIONAL COROUTINE VERSION*
>
> local D,P=Database,ProgressBar
> local Files=IterateDir() *--returns the table*/
>
> local Routine=coroutine.wrap(function(FileName,Extension)
> /D:exec('insert into Files("'..Filename..'","'..Extension..'")')
> *--execute SQL query*
> P:setValue(ProgressBar:value()+1) *--step the progressbar*/
> coroutine.yield()
> end)
>
>
> /if D:transaction() then *--prepare database for transaction
> *//P:setMaximum(#Files) *--set the progressbar maximum value to the
> amount of files in the table*/
>
>      for FileName,Exension in pairs(Files)do Routine(File,Extension)end
> /
>      if D:commit() then *--commit the database*
>          print'Operation finished, database updated succesfully'
>          P:reset() *--reset the progressbar*
>      end/
>
> end
>
> Can somebody help me get the second version working?
>
> Ultimately, I would like to use true OS threads but as I understand it I
> need to wait until LuaJIT FFI supports callbacks, or I need
> to use an additional module (I would like to keep dependencies to a minimum)
>
> Thanks in advance
>
> Ralf
>
>

I believe you are assuming that coroutines are essenctially threads
with another name and that is not the case.

Essentially, when you say
        co = coroutine.wrap(function ... )
it means that when you call co for the first time program execution
will exit the function in the first coroutine.yield and when you call
co for the second time program execution will enter the function in
that coroutine.yield. Note that the paralelism is in the way you
structure the program, not in the execution flow.

In your line
        for FileName,Exension in pairs(Files)do Routine(File,Extension)end
you are calling the same Routine multiple times and, according to its
definition, that function will terminate on its second invocation,
hence the error.

To accomplish what you intend (use them as "fibers" or "green
threads"), you need
 - a dispatcher that creates and resumes coroutines
 - non-blocking coroutines that yield to the dispatcher when they become idle

Check here for examples: http://www.lua.org/pil/9.4.html
http://keplerproject.github.com/copas/ is what you want, I think.