blob: aa164f7e4cf6e1051a9fbef63e014d442b47c343 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
lua-llthreads2
==============
[](LICENSE)
[](https://travis-ci.org/moteus/lua-llthreads2)
[](https://ci.appveyor.com/project/moteus/lua-llthreads2)
This is full dropin replacement for [llthreads](https://github.com/Neopallium/lua-llthreads) library.
## Incompatibility list with origin llthreads library
* does not support Lua 5.0
* does not support ffi interface (use Lua C API for LuaJIT)
* returns nil instead of false on error
* start method returns self instead of true on success
## Additional
* thread:join() method support zero timeout to check if thread alive (does not work on Windows with pthreads)
* thread:join() method support arbitrary timeout on Windows threads
* thread:alive() method return whether the thread is alive (does not work on Windows with pthreads)
* set_logger function allow logging errors (crash Lua VM) in current llthread's threads
* thread:start() has additional parameter which control in which thread child Lua VM will be destroyed
* allow pass cfunctions to child thread (e.g. to initialize Lua state)
## Thread start arguments
| `detached` | `joinable` | join returns | child state closes by | gc calls | detach on |
|:----------:|:----------:|:------------:|:---------------------:|:--------:|:---------:|
| false | false | `true` | child | join | `<NEVER>` |
| false(\*)| true(\*) | Lua values | parent | join \* | `<NEVER>` |
| true | false(\*) | raise error | child | `<NONE>` | start |
| true | true | `true` | child | detach | gc |
## Usage
### Use custom logger
In this example I use [lua-log](https://github.com/moteus/lua-log) library.
``` Lua
-- This is child thread.
local llthreads = require "llthreads2"
-- Send logs using ZMQ
local LOG = require"log".new(
require "log.writer.net.zmq".new("tcp://127.0.0.1:5555")
)
llthread.set_logger(function(msg) LOG.error(msg) end)
-- This error with traceback will be passed to logger
error("SOME ERROR")
```
### Start attached thread collectd in child thread
``` Lua
-- This is main thread.
local thread = require "llthreads2".new[[
require "utils".sleep(5)
]]
-- We tell that we start attached thread but child Lua State shuld be close in child thread.
-- If `thread` became garbage in main thread then finallizer calls thread:join()
-- and main thread may hungup. But because of child state closes in child thread all objects
-- in this state can be destroyed and we can prevent deadlock.
thread:start(false, false)
-- We can call join.
-- Because of Lua state destroys in child thread we can not get
-- returned Lua values so we just returns `true`.
thread:join()
```
### Start detached joinable thread
``` Lua
-- This is main thread.
local thread = require "llthreads2".new[[
require "utils".sleep(5)
]]
-- We tell that we start detached joinable thread. In fact we start attached
-- thread but if `thread` became garbage in main thread then finallizer just
-- detach child thread and main thread may not hungup.
thread:start(true, true)
-- We can call join.
-- Because of Lua state destroys in child thread we can not get
-- returned Lua values so we just returns `true`.
thread:join()
```
### Pass to child thread host application`s library loader
If you close parent Lua state then some dynamic library may be unloaded
and cfunction in child Lua state (thread) became invalid.
``` Lua
-- `myhost.XXX` modules is built-in modules in host application
-- host application registers cfunction as module loader
local preload = {}
preload[ 'myhost.logger' ] = package.preload[ 'myhost.logger' ]
preload[ 'myhost.config' ] = package.preload[ 'myhost.config' ]
llthreads.new([[
-- registers preload
local preload = ...
for name, fn in pairs(preload) do package.preload[name] = fn end
local log = require 'myhost.logger'
]], preload):start(true)
```
### Wait while thread is alive
``` Lua
local thread = require "llthreads2".new[[
require "utils".sleep(5)
return 1
]]
thread:start()
-- we can not use `thread:join(0)` because we can not call it twice
-- so all returned values will be lost
while thread:alive() do
-- do some work
end
local ok, ret = thread:join() -- true, 1
```
### Use `ex` module
``` Lua
local Threads = require "llthreads2.ex"
local ok, v = Threads.new(function()
return 1
end):start():join()
assert(v == 1)
local thread = Threads.new({
-- this thread code gets changed arguments
function(a, b)
assert(1 == a)
assert(2 == b)
print("Done")
end;
-- prelude can change thread arguments
prelude = function(a, b)
assert("1" == a)
assert(nil == b)
return tonumber(a), 2
end;
}, "1")
thread:start():join()
```
[](https://bitdeli.com/free "Bitdeli Badge")
|