Skip to content

Commit

Permalink
Semaphores and condition variables. (#10503)
Browse files Browse the repository at this point in the history
* Semaphores and condition variables.

* Update Ocaml version

* Fix tests for neko and conditons for C#.

* Fix MacOS CI.

* Disable semaphores and condition variables for eval.
Also revert changes to Ocaml version.

* Implement semaphore using luv.

* Cleanup luv objects.
Remove timing dependent test case that fails sometimes.

* Make C# use System.Threading.Semaphore.
Remove commented out code from the .ml files.

* Remove more unused code.

* Add Semaphore and Condition to cppia HostClasses.
  • Loading branch information
Apprentice-Alchemist authored Feb 14, 2022
1 parent 3d940a9 commit bc6fb5c
Show file tree
Hide file tree
Showing 17 changed files with 512 additions and 0 deletions.
33 changes: 33 additions & 0 deletions std/cpp/_std/sys/thread/Condition.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package sys.thread;

@:coreApi
class Condition {
var c:Dynamic;
public function new():Void {
c = untyped __global__.__hxcpp_condition_create();
}

public function acquire():Void {
untyped __global__.__hxcpp_condition_acquire(c);
}

public function tryAcquire():Bool {
return untyped __global__.__hxcpp_condition_try_acquire(c);
}

public function release():Void {
untyped __global__.__hxcpp_condition_release(c);
}

public function wait():Void {
untyped __global__.__hxcpp_condition_wait(c);
}

public function signal():Void {
untyped __global__.__hxcpp_condition_signal(c);
}

public function broadcast():Void {
untyped __global__.__hxcpp_condition_broadcast(c);
}
}
22 changes: 22 additions & 0 deletions std/cpp/_std/sys/thread/Semaphore.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package sys.thread;

@:coreApi
class Semaphore {
var m:Dynamic;

public function new(value:Int) {
m = untyped __global__.__hxcpp_semaphore_create(value);
}

public function acquire():Void {
untyped __global__.__hxcpp_semaphore_acquire(m);
}

public function tryAcquire(?timeout:Float):Bool {
return untyped __global__.__hxcpp_semaphore_try_acquire(m, timeout == null ? 0 : (timeout:Float));
}

public function release():Void {
untyped __global__.__hxcpp_semaphore_release(m);
}
}
2 changes: 2 additions & 0 deletions std/cpp/cppia/HostClasses.hx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class HostClasses {
"sys.thread.Mutex",
"sys.thread.Thread",
"sys.thread.Tls",
"sys.thread.Semaphore",
"sys.thread.Condition",
"cpp.vm.ExecutionTrace",
"cpp.vm.Gc",
"cpp.vm.Profiler",
Expand Down
37 changes: 37 additions & 0 deletions std/cs/_std/sys/thread/Condition.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package sys.thread;

import cs.system.threading.Monitor;

@:coreApi
@:access(sys.thread.Mutex)
class Condition {
final object:cs.system.Object;

public function new():Void {
this.object = new cs.system.Object();
}

public function acquire():Void {
Monitor.Enter(object);
}

public function tryAcquire():Bool {
return Monitor.TryEnter(object);
}

public function release():Void {
Monitor.Exit(object);
}

public function wait():Void {
Monitor.Wait(object);
}

public function signal():Void {
Monitor.Pulse(object);
}

public function broadcast():Void {
Monitor.PulseAll(object);
}
}
22 changes: 22 additions & 0 deletions std/cs/_std/sys/thread/Semaphore.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package sys.thread;

@:coreApi
class Semaphore {
final native:cs.system.threading.Semaphore;

public function new(value:Int):Void {
this.native = new cs.system.threading.Semaphore(value, 0x7FFFFFFF);
}

public function acquire():Void {
native.WaitOne();
}

public function tryAcquire(?timeout:Float):Bool {
return native.WaitOne(timeout == null ? 0 : Std.int(timeout * 1000));
}

public function release():Void {
native.Release();
}
}
41 changes: 41 additions & 0 deletions std/eval/_std/sys/thread/Condition.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package sys.thread;

@:coreApi class Condition {
final cond:eval.luv.Condition;
final mutex:eval.luv.Mutex;

public function new():Void {
cond = eval.luv.Condition.init().resolve();
mutex = eval.luv.Mutex.init(true).resolve();
eval.vm.Gc.finalise(destroy, this);
}

static function destroy(cond:Condition):Void {
cond.cond.destroy();
cond.mutex.destroy();
}

public function acquire():Void {
mutex.lock();
}

public function tryAcquire():Bool {
return mutex.tryLock().isOk();
}

public function release():Void {
mutex.unlock();
}

public function wait():Void {
cond.wait(mutex);
}

public function signal():Void {
cond.signal();
}

public function broadcast():Void {
cond.broadcast();
}
}
36 changes: 36 additions & 0 deletions std/eval/_std/sys/thread/Semaphore.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package sys.thread;

@:coreApi class Semaphore {
final native:eval.luv.Semaphore;

public function new(value:Int):Void {
native = eval.luv.Semaphore.init(value).resolve();
eval.vm.Gc.finalise(destroy, this);
}

static function destroy(sem:Semaphore):Void {
sem.native.destroy();
}

public function acquire():Void {
native.wait();
}

public function tryAcquire(?timeout:Float):Bool {
if (timeout == null) {
return native.tryWait().isOk();
} else {
var t = Sys.time() + timeout;
while (Sys.time() < t) {
if (native.tryWait().isOk()) {
return true;
}
}
return false;
}
}

public function release():Void {
native.post();
}
}
32 changes: 32 additions & 0 deletions std/hl/_std/sys/thread/Condition.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package sys.thread;

abstract Condition(hl.Abstract<"hl_condition">) {
public function new():Void {
this = alloc();
}

@:hlNative("std", "condition_acquire")
public function acquire():Void {}

@:hlNative("std", "condition_try_acquire")
public function tryAcquire():Bool {
return false;
}

@:hlNative("std", "condition_release")
public function release():Void {}

@:hlNative("std", "condition_wait")
public function wait():Void {}

@:hlNative("std", "condition_signal")
public function signal():Void {}

@:hlNative("std", "condition_broadcast")
public function broadcast():Void {}

@:hlNative("std", "condition_alloc")
static function alloc():hl.Abstract<"hl_condition"> {
return null;
}
}
23 changes: 23 additions & 0 deletions std/hl/_std/sys/thread/Semaphore.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package sys.thread;

abstract Semaphore(hl.Abstract<"hl_semaphore">) {
public function new(value:Int):Void {
this = alloc(value);
}

@:hlNative("std", "semaphore_acquire")
public function acquire():Void {}

@:hlNative("std", "semaphore_release")
public function release():Void {}

@:hlNative("std", "semaphore_try_acquire")
public function tryAcquire(?timeout:Float):Bool {
return false;
}

@:hlNative("std", "semaphore_alloc")
static function alloc(value:Int):hl.Abstract<"hl_semaphore"> {
return null;
}
}
45 changes: 45 additions & 0 deletions std/java/_std/sys/thread/Condition.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package sys.thread;

import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition as NativeCondition;

@:access(sys.thread.Mutex)
@:coreApi
@:native('haxe.java.vm.Condition')
class Condition {
final lock:ReentrantLock;
final native:NativeCondition;

public function new():Void {
this.lock = new ReentrantLock();
this.native = lock.newCondition();
}

public function acquire():Void {
lock.lock();
}

public function tryAcquire():Bool {
return this.lock.tryLock();
}

public function release():Void {
lock.unlock();
}

// without the @:native, you get "java.lang.VerifyError: class sys.thread.Condition overrides final method java.lang.Object.wait()V" on jvm
// and "wait() in Condition cannot override wait() in Object" from javac

@:native("waitOn")
public function wait():Void {
native.await();
}

public function signal():Void {
native.signal();
}

public function broadcast():Void {
native.signalAll();
}
}
25 changes: 25 additions & 0 deletions std/java/_std/sys/thread/Semaphore.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package sys.thread;

import java.util.concurrent.TimeUnit;

@:coreApi
@:native('haxe.java.vm.Semaphore')
class Semaphore {
final native:java.util.concurrent.Semaphore;

public function new(value:Int):Void {
this.native = new java.util.concurrent.Semaphore(value);
}

public function acquire():Void {
native.acquire();
}

public function tryAcquire(?timeout:Float):Bool {
return timeout == null ? native.tryAcquire() : native.tryAcquire(haxe.Int64.fromFloat(timeout * 1000000000),TimeUnit.NANOSECONDS);
}

public function release():Void {
native.release();
}
}
34 changes: 34 additions & 0 deletions std/python/_std/sys/thread/Condition.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package sys.thread;

@:coreApi
class Condition {
final cond:python.lib.threading.Condition;

public function new():Void {
this.cond = new python.lib.threading.Condition();
}

public function acquire():Void {
cond.acquire();
}

public function tryAcquire():Bool {
return cond.acquire(false);
}

public function release():Void {
cond.release();
}

public function wait():Void {
cond.wait();
}

public function signal():Void {
cond.notify();
}

public function broadcast():Void {
cond.notify_all();
}
}
24 changes: 24 additions & 0 deletions std/python/_std/sys/thread/Semaphore.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package sys.thread;

import python.lib.threading.Semaphore as NativeSemaphore;

@:coreApi
class Semaphore {
final semaphore:NativeSemaphore;

public function new(value:Int):Void {
this.semaphore = new NativeSemaphore(value);
}

public function acquire():Void {
semaphore.acquire();
}

public function tryAcquire(?timeout:Float):Bool {
return timeout == null ? semaphore.acquire(false) : semaphore.acquire(true, timeout);
}

public function release():Void {
semaphore.release();
}
}
Loading

0 comments on commit bc6fb5c

Please sign in to comment.