Skip to content

Commit 8d08a28

Browse files
Aidan63Simn
andauthored
[cpp] Managed extern for typed mutex and condition (#12529)
* managed extern for typed mutex and condition * add more Condition tests and fix some deprecations while I'm here * wait for thread creation like a real programmer * make sure we wait while collecting --------- Co-authored-by: Simon Krajewski <[email protected]>
1 parent 1e45f4c commit 8d08a28

File tree

4 files changed

+88
-26
lines changed

4 files changed

+88
-26
lines changed
Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,47 @@
11
package sys.thread;
22

3+
@:include("hx/thread/ConditionVariable.hpp")
4+
@:cpp.ManagedType({ namespace : [ "hx", "thread" ], flags : [ StandardNaming ] })
5+
private extern class ConditionVariable {
6+
function new():Void;
7+
8+
public function acquire():Void;
9+
public function tryAcquire():Bool;
10+
public function release():Void;
11+
public function wait():Void;
12+
public function signal():Void;
13+
public function broadcast():Void;
14+
}
15+
316
@:coreApi
417
class Condition {
5-
var c:Dynamic;
18+
final c:ConditionVariable;
19+
620
public function new():Void {
7-
c = untyped __global__.__hxcpp_condition_create();
21+
c = new ConditionVariable();
822
}
923

1024
public function acquire():Void {
11-
untyped __global__.__hxcpp_condition_acquire(c);
25+
c.acquire();
1226
}
1327

1428
public function tryAcquire():Bool {
15-
return untyped __global__.__hxcpp_condition_try_acquire(c);
29+
return c.tryAcquire();
1630
}
1731

1832
public function release():Void {
19-
untyped __global__.__hxcpp_condition_release(c);
33+
c.release();
2034
}
2135

2236
public function wait():Void {
23-
untyped __global__.__hxcpp_condition_wait(c);
37+
c.wait();
2438
}
2539

2640
public function signal():Void {
27-
untyped __global__.__hxcpp_condition_signal(c);
41+
c.signal();
2842
}
2943

3044
public function broadcast():Void {
31-
untyped __global__.__hxcpp_condition_broadcast(c);
45+
c.broadcast();
3246
}
3347
}

std/cpp/_std/sys/thread/Mutex.hx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,33 @@
2222

2323
package sys.thread;
2424

25+
@:include("hx/thread/RecursiveMutex.hpp")
26+
@:cpp.ManagedType({ namespace : [ "hx", "thread" ], flags : [ StandardNaming ] })
27+
private extern class RecursiveMutex {
28+
function new():Void;
29+
30+
function acquire():Void;
31+
function tryAcquire():Bool;
32+
function release():Void;
33+
}
34+
2535
@:coreApi
2636
class Mutex {
27-
var m:Dynamic;
37+
final m:RecursiveMutex;
2838

2939
public function new() {
30-
m = untyped __global__.__hxcpp_mutex_create();
40+
m = new RecursiveMutex();
3141
}
3242

3343
public function acquire():Void {
34-
untyped __global__.__hxcpp_mutex_acquire(m);
44+
m.acquire();
3545
}
3646

3747
public function tryAcquire():Bool {
38-
return untyped __global__.__hxcpp_mutex_try(m);
48+
return m.tryAcquire();
3949
}
4050

4151
public function release():Void {
42-
untyped __global__.__hxcpp_mutex_release(m);
52+
m.release();
4353
}
4454
}

tests/threads/src/cases/TestCondition.hx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package cases;
22

3+
import utest.Assert;
34
import sys.thread.Condition;
45
import sys.thread.Thread;
56

@@ -14,6 +15,43 @@ class TestCondition extends utest.Test {
1415
});
1516
cond.wait();
1617
cond.release();
18+
Assert.pass();
19+
}
20+
21+
function testTryAcquire() {
22+
final cond = new Condition();
23+
Assert.isTrue(cond.tryAcquire());
24+
// I would prefer to specify it to be not recursive...
25+
// Assert.isFalse(cond.tryAcquire());
26+
cond.release();
27+
}
28+
29+
function testGCDuringWait() {
30+
final cond = new Condition();
31+
32+
cond.acquire();
33+
Thread.create(() -> {
34+
cond.acquire();
35+
cond.signal();
36+
cond.wait();
37+
cond.release();
38+
});
39+
// wait for signal from thread
40+
cond.wait();
41+
42+
#if cpp
43+
cpp.vm.Gc.run(true);
44+
#elseif hl
45+
hl.Gc.major();
46+
#elseif interp
47+
eval.vm.Gc.full_major();
48+
#elseif neko
49+
neko.vm.Gc.run(true);
50+
#end
51+
52+
cond.signal();
53+
cond.release();
54+
1755
utest.Assert.pass();
1856
}
1957
}

tests/threads/src/cases/TestEvents.hx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@ class TestEvents extends utest.Test {
99
var e3 = null;
1010
var e2 = null;
1111
var e1 = null;
12-
e2 = events.repeat(() -> {
12+
e2 = events.addTimer(() -> {
1313
checks.push(2);
14-
events.cancel(e1);
15-
events.cancel(e2);
16-
events.cancel(e3);
17-
}, 20);
18-
e1 = events.repeat(() -> checks.push(1), 10);
19-
e3 = events.repeat(() -> checks.push(3), 30);
14+
e1.stop();
15+
e2.stop();
16+
e3.stop();
17+
}, 20 / 1000);
18+
e1 = events.addTimer(() -> checks.push(1), 10 / 1000);
19+
e3 = events.addTimer(() -> checks.push(3), 30 / 1000);
2020
Sys.sleep(0.1);
2121

2222
var checker = null;
23-
checker = events.repeat(() -> {
23+
checker = events.addTimer(() -> {
2424
same([1, 2], checks);
2525
async.done();
26-
events.cancel(checker);
27-
}, 100);
26+
checker.stop();
27+
}, 100 / 1000);
2828
}
2929

3030
function testRun(async:Async) {
@@ -52,14 +52,14 @@ class TestEvents extends utest.Test {
5252
function test(thread:Thread, done:()->Void) {
5353
var timesExecuted = 0;
5454
var eventHandler = null;
55-
eventHandler = thread.events.repeat(() -> {
55+
eventHandler = thread.events.addTimer(() -> {
5656
++timesExecuted;
5757
isTrue(thread == Thread.current());
5858
if(timesExecuted >= 3) {
59-
thread.events.cancel(eventHandler);
59+
eventHandler.stop();
6060
done();
6161
}
62-
}, 50);
62+
}, 50 / 1000);
6363
}
6464

6565
var mainThread = Thread.current();

0 commit comments

Comments
 (0)