I tried making for cycle multithreaded, but I got this bug (or is this a feature?). First the code:
@tool
extends EditorScript
var mutex:= Mutex.new()
var threads_pool: Array[Thread] = []
func _run() -> void:
var threads_count = OS.get_processor_count()
for t in threads_count:
threads_pool.append(Thread.new())
var n:= 0.0
var f = func() -> void:
mutex.lock()
print(n, " before")
n += 1
print(n, " after")
mutex.unlock()
for i in range(0, 100, threads_count):
print(n)
for t in threads_count:
if i + t >= 100:
break
threads_pool[t].start(f.bind())
for t in threads_count:
if i + t >= 100:
break
threads_pool[t].wait_to_finish()
print(n)
Variable n is recognized by f Callable, because it will give error if i remove:
But when the threads are running it sees n, but each new thread sees it as 0.0, it never gets updated.
If I make n global it will update, is it a bug or a feature I need to learn??
Lambdas capture by the same logic other variable assignments do. If the value doesn’t have .duplicate() then it will be copied by default, such as float, int, Vector2, most anything not RefCounted or Nodes. You probably get this relevant script warning:
(CONFUSABLE_CAPTURE_REASSIGNMENT):Reassigning lambda capture does not modify the outer local variable “n”.
If you want to use something cleaner than array subscripts use a class object. E.g.
### your other code here...
class Foo:
var n:float = 0
func _ready():
var threads_count = OS.get_processor_count()
print(threads_count)
for t in threads_count:
threads_pool.append(Thread.new())
var obj := Foo.new()
var f = func() -> void:
mutex.lock()
print(obj.n, " before")
obj.n += 1.0
print(obj.n, " after")
mutex.unlock()
for i in range(0, 100, threads_count):
print(obj.n)
for t in threads_count:
if i + t >= 100:
break
threads_pool[t].start(f.bind())
for t in threads_count:
if i + t >= 100:
break
threads_pool[t].wait_to_finish()
print(obj.n)