Improve workers API, fix lost sync. (#1029)

This commit is contained in:
Nikolay Igotti
2017-11-13 16:42:00 +03:00
committed by GitHub
parent 1c8616541e
commit afe0780d28
2 changed files with 22 additions and 21 deletions
+17 -7
View File
@@ -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);
} }
+5 -14
View File
@@ -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
}
} }
/** /**