Improve workers API, fix lost sync. (#1029)
This commit is contained in:
@@ -158,9 +158,9 @@ class Worker {
|
|||||||
void putJob(Job job, bool toFront) {
|
void putJob(Job job, bool toFront) {
|
||||||
Locker locker(&lock_);
|
Locker locker(&lock_);
|
||||||
if (toFront)
|
if (toFront)
|
||||||
queue_.push_front(job);
|
queue_.push_front(job);
|
||||||
else
|
else
|
||||||
queue_.push_back(job);
|
queue_.push_back(job);
|
||||||
pthread_cond_signal(&cond_);
|
pthread_cond_signal(&cond_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,8 +340,11 @@ void Future::storeResultUnlocked(KNativePtr result) {
|
|||||||
Locker locker(&lock_);
|
Locker locker(&lock_);
|
||||||
state_ = COMPUTED;
|
state_ = COMPUTED;
|
||||||
result_ = result;
|
result_ = result;
|
||||||
|
// Beware here: although manual clearly says that pthread_cond_signal() could be called outside
|
||||||
|
// of the taken lock, it's not on OSX (as of 10.13.1). If moved outside of the lock,
|
||||||
|
// some notifications gets missed.
|
||||||
|
pthread_cond_signal(&cond_);
|
||||||
}
|
}
|
||||||
pthread_cond_signal(&cond_);
|
|
||||||
theState()->signalAnyFuture();
|
theState()->signalAnyFuture();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,11 +353,13 @@ void Future::cancelUnlocked() {
|
|||||||
Locker locker(&lock_);
|
Locker locker(&lock_);
|
||||||
state_ = CANCELLED;
|
state_ = CANCELLED;
|
||||||
result_ = nullptr;
|
result_ = nullptr;
|
||||||
|
pthread_cond_signal(&cond_);
|
||||||
}
|
}
|
||||||
pthread_cond_signal(&cond_);
|
|
||||||
theState()->signalAnyFuture();
|
theState()->signalAnyFuture();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Defined in RuntimeUtils.kt.
|
||||||
|
extern "C" void ReportUnhandledException(KRef e);
|
||||||
|
|
||||||
void* workerRoutine(void* argument) {
|
void* workerRoutine(void* argument) {
|
||||||
Worker* worker = reinterpret_cast<Worker*>(argument);
|
Worker* worker = reinterpret_cast<Worker*>(argument);
|
||||||
@@ -374,9 +379,14 @@ void* workerRoutine(void* argument) {
|
|||||||
// so we don't use ObjHolder.
|
// so we don't use ObjHolder.
|
||||||
// It is so, as ownership is transferred.
|
// It is so, as ownership is transferred.
|
||||||
KRef resultRef = nullptr;
|
KRef resultRef = nullptr;
|
||||||
job.function(argument, &resultRef);
|
KNativePtr result = nullptr;
|
||||||
// Transfer the result.
|
try {
|
||||||
KNativePtr result = transfer(resultRef, job.transferMode);
|
job.function(argument, &resultRef);
|
||||||
|
// Transfer the result.
|
||||||
|
result = transfer(resultRef, job.transferMode);
|
||||||
|
} catch (ObjHolder& e) {
|
||||||
|
ReportUnhandledException(e.obj());
|
||||||
|
}
|
||||||
// Notify the future.
|
// Notify the future.
|
||||||
job.future->storeResultUnlocked(result);
|
job.future->storeResultUnlocked(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ class Future<T> internal constructor(val id: FutureId) {
|
|||||||
/**
|
/**
|
||||||
* Blocks execution until the future is ready.
|
* Blocks execution until the future is ready.
|
||||||
*/
|
*/
|
||||||
fun consume(code: (T) -> Unit) {
|
fun <R> consume(code: (T) -> R) =
|
||||||
when (state) {
|
when (state) {
|
||||||
FutureState.SCHEDULED, FutureState.COMPUTED -> {
|
FutureState.SCHEDULED, FutureState.COMPUTED -> {
|
||||||
val value = @Suppress("UNCHECKED_CAST") (consumeFuture(id) as T)
|
val value = @Suppress("UNCHECKED_CAST") (consumeFuture(id) as T)
|
||||||
@@ -100,18 +100,13 @@ class Future<T> internal constructor(val id: FutureId) {
|
|||||||
FutureState.CANCELLED ->
|
FutureState.CANCELLED ->
|
||||||
throw IllegalStateException("Future is cancelled")
|
throw IllegalStateException("Future is cancelled")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val state: FutureState
|
val state: FutureState
|
||||||
get() = FutureState.values()[stateOfFuture(id)]
|
get() = FutureState.values()[stateOfFuture(id)]
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?) = (other is Future<*>) && (id == other.id)
|
||||||
return (other is Future<*>) && (id == other.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode() = id
|
||||||
return id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -145,13 +140,9 @@ class Worker(val id: WorkerId) {
|
|||||||
*/
|
*/
|
||||||
throw RuntimeException("Shall not be called directly")
|
throw RuntimeException("Shall not be called directly")
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?) = (other is Worker) && (id == other.id)
|
||||||
return (other is Worker) && (id == other.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode() = id
|
||||||
return id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user