milochristiansen / lua

A Lua 5.3 VM and compiler written in Go.
zlib License
916 stars 30 forks source link

How to do with goroutines? #9

Closed syoshin closed 6 years ago

syoshin commented 6 years ago

I want to put some volatile code into lua functions, these lua functions will be called by go. How to preserve thread safety? Or there is some other way to achieve similar requirements?

milochristiansen commented 6 years ago

Internally, no particular effort at thread safety is made, since running more than one thread at a time with a given VM is completely impossible.

To run multiple threads you need multiple VMs, and VMs cannot share data. However, you can give each VM access to native values that are shared, and if you make sure access to these values is properly syncronized everything should work fine. For functions this is easy, just add a native function to all VMs and do all your locking and such inside the function. For data values you can use metatables, but this is more complicated.

The lua/supermeta package has some generic metatables that you may find useful. They are not thread safe, but they do have all the basic functionality needed to expose native values of most types, so all you would need to do is add mutexs in the proper places. This would be fairly easy to do, but still not as easy as a set of simple native functions...

Basically you need to make sure you never pass a userdata value to a VM without making sure it cannot be read without syncronization. Any global data needed by all threads/VMs will have to be stored outside the VM and accessed via function calls containing the required syncronization, either by providing the functions directly or via a metatable.

I'll leave this open for a few days if you have any questions.

syoshin commented 6 years ago

Yes, there is no general solution for the moment. I tend to use a sync.Mutex when call a lua function in goroutines, be careful to avoid deadlock. Thank you!

syoshin commented 6 years ago

Use a sync.Mutex in a lua native function may loss the goroutines advantage, if something block in lua function. Running a vm in a separate goroutine and passing data through channel maybe better. In this case, the vm serves as a service.

milochristiansen commented 6 years ago

That would work as well, provided you are OK with only running one script at a time. The best way to integrate the VM is different depending on what exactly your needs are.