/*
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.agera;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.concurrent.Executor;
import static com.google.android.agera.Functions.identityFunction;
import static com.google.android.agera.Observables.compositeObservable;
import static com.google.android.agera.Preconditions.checkNotNull;
import static com.google.android.agera.Preconditions.checkState;
import static com.google.android.agera.RepositoryConfig.CANCEL_FLOW;
import static com.google.android.agera.RepositoryConfig.RESET_TO_INITIAL_VALUE;
import static com.google.android.agera.RepositoryConfig.SEND_INTERRUPT;
import static com.google.android.agera.WorkerHandler.MSG_CALL_ACKNOWLEDGE_CANCEL;
import static com.google.android.agera.WorkerHandler.MSG_CALL_MAYBE_START_FLOW;
import static com.google.android.agera.WorkerHandler.workerHandler;
import static java.lang.Thread.currentThread;
@SuppressWarnings({ "rawtypes", "unchecked" })
final class CompiledRepository extends BaseObservable
implements Repository, Updatable, Runnable {
@NonNull
static Repository compiledRepository(
@NonNull final Object initialValue,
@NonNull final List<Observable> eventSources,
final int frequency,
@NonNull final List<Object> directives,
@NonNull final Merger<Object, Object, Boolean> notifyChecker,
@RepositoryConfig final int concurrentUpdateConfig,
@RepositoryConfig final int deactivationConfig) {
final Object[] directiveArray = directives.toArray();
return new CompiledRepository(initialValue, compositeObservable(frequency,
eventSources.toArray(new Observable[eventSources.size()])),
directiveArray, notifyChecker, deactivationConfig, concurrentUpdateConfig);
}
//region Invariants
// 初始值
@NonNull
private final Object initialValue;
// 事件源
@NonNull
private final Observable eventSource;
// 所有指令
@NonNull
private final Object[] directives;
/*
* 实质上为一个 ObjectsUnequalMerger
* 用于判断 传入的两个流数据 是否 相等
* 判断后 合并出对应的 true or false
*/
@NonNull
private final Merger<Object, Object, Boolean> notifyChecker;
// 失效配置
@RepositoryConfig
private final int deactivationConfig;
// 并发更新配置
@RepositoryConfig
private final int concurrentUpdateConfig;
// WorkerHandler
@NonNull
private final WorkerHandler workerHandler;
CompiledRepository(
@NonNull final Object initialValue,
@NonNull final Observable eventSource,
@NonNull final Object[] directives,
@NonNull final Merger<Object, Object, Boolean> notifyChecker,
@RepositoryConfig final int deactivationConfig,
@RepositoryConfig final int concurrentUpdateConfig) {
this.initialValue = initialValue;
this.currentValue = initialValue;
this.intermediateValue = initialValue; // non-final field but with @NonNull requirement
this.eventSource = eventSource;
this.directives = directives;
this.notifyChecker = notifyChecker;
this.deactivationConfig = deactivationConfig;
this.concurrentUpdateConfig = concurrentUpdateConfig;
this.workerHandler = workerHandler();
}
//endregion Invariants
//region Data processing flow states
/**
* 运行状态
*
* IDLE:闲置
* RUNNING:运行
* CANCEL_REQUESTED:取消请求
* PAUSED_AT_GO_TO:子线程暂停
* PAUSED_AT_GO_LAZY:懒加载暂停
* RUNNING_LAZILY:懒加载运行
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({ IDLE, RUNNING, CANCEL_REQUESTED, PAUSED_AT_GO_TO, PAUSED_AT_GO_LAZY, RUNNING_LAZILY })
private @interface RunState {}
private static final int IDLE = 0;
private static final int RUNNING = 1;
private static final int CANCEL_REQUESTED = 2;
private static final int PAUSED_AT_GO_TO = 3;
private static final int PAUSED_AT_GO_LAZY = 4;
private static final int RUNNING_LAZILY = 5;
// 记录 运行状态,默认为:闲置
@RunState
private int runState = IDLE;
// 记录 是否需要重启
private boolean restartNeeded;
/*
* 最后一个 goTo()/goLazy() 指令的 index
* 如果重启,则为 -1 或者 其他指令
*/
/** Index of the last goTo()/goLazy() directive, for resuming, or -1 for other directives. */
private int lastDirectiveIndex = -1;
// 当前值
/** The current value to be exposed through the repository's get method. */
@NonNull
private Object currentValue;
// 中间值
/** The intermediate value computed by the executed part of the flow. */
@NonNull
private Object intermediateValue;
// 当前线程
/** The thread currently running a directive that can be interrupted. */
@Nullable
private Thread currentThread;
//endregion Data processing flow states
//region Starting and requesting cancellation
// - All methods in this region are called from the Worker Looper thread, but reading and writing
// states that might be accessed from a different thread are still synchronized.
/**
* 如果身为 BaseObservable ,被观察者 被激活时( 成功添加一个观察者后 )
* 为 事件源 添加 观察者,为 此 CompiledRepository
* 然后执行 maybeStartFlow()
*/
@Override
protected void observableActivated() {
eventSource.addUpdatable(this);
maybeStartFlow();
}
/**
* 如果身为 BaseObservable ,被观察者 被失效时( 成功删除一个观察者后 )
* 为 事件源 删除 观察者,为 此 CompiledRepository
* 然后执行 maybeCancelFlow(...)
*/
@Override
protected void observableDeactivated() {
eventSource.removeUpdatable(this);
maybeCancelFlow(deactivationConfig, false);
}
/**
* 同时调用
* 1. 可能取消流
* 2. 可能开始流
*/
@Override
public void update() {
maybeCancelFlow(concurrentUpdateConfig, true);
maybeStartFlow();
}
/**
* Called on the worker looper thread. Starts the data processing flow if it's not running.
* This
* also cancels the lazily-executed part of the flow if the run state is "paused at lazy".
*
* 如果 运行状态为下面一个状态
* 1. 闲置
* 2. 懒加载暂停
*
* 那么重置状态为:运行
* 标记不需要 重启
*
* --------------------
*
* 3.否则 判断 当前运行状态 是否为 取消请求
* 是的话,标记需要 重启
*
* --------------------
*
* 最后都
*
* 中间值存放当前值
* 开始运行 流 runFlowFrom(...)
*/
void maybeStartFlow() {
synchronized (this) {
if (runState == IDLE || runState == PAUSED_AT_GO_LAZY) {
runState = RUNNING;
lastDirectiveIndex = -1; // this could be pointing at the goLazy directive
restartNeeded = false;
} else {
if (runState == CANCEL_REQUESTED) {
// flow may still be processing the previous deactivation;
// make sure to restart
restartNeeded = true;
}
return; // flow already running, do not continue.
}
}
intermediateValue = currentValue;
runFlowFrom(0, false);
}
/**
* Called on the worker looper thread. Depending on the {@code config}, cancels the data
* processing flow, resets the value, and/or sends the interrupt signal to the thread currently
* processing a getFrom/mergeIn/transform instruction of the flow.
*
* @param scheduleRestart Whether to schedule a restart if a current flow is canceled.
*
* 如果 运行状态为
* 1. 运行
* 2. 子线程暂停
* 3. 并且,仓库配置不为 CONTINUE_FLOW
*
* 那么重置状态为:取消请求
*
* 4. 如果,仓库配置为 SEND_INTERRUPT,并且当前线程 存在,那么线程停止
* 5. 如果,仓库配置为 RESET_TO_INITIAL_VALUE,并且 不重启,那么重置到初始值
*/
private void maybeCancelFlow(
@RepositoryConfig final int config, final boolean scheduleRestart) {
synchronized (this) {
if (runState == RUNNING || runState == PAUSED_AT_GO_TO) {
restartNeeded = scheduleRestart;
// If config forbids cancellation, exit now after scheduling the restart, to skip the
// cancellation request.
if ((config & CANCEL_FLOW) == 0) {
return;
}
runState = CANCEL_REQUESTED;
if ((config & SEND_INTERRUPT) == SEND_INTERRUPT && currentThread != null) {
currentThread.interrupt();
}
}
// Resetting to the initial value should be done even if the flow is not running.
if (!scheduleRestart && (config & RESET_TO_INITIAL_VALUE) == RESET_TO_INITIAL_VALUE) {
setNewValueLocked(initialValue);
}
}
}
//endregion Starting and requesting cancellation
//region Acknowledging cancellation and restarting
// - Apart from handleMessage(), other methods in this region can be called from a thread that is
// not the Worker Looper thread.
/**
* Checks if the current data processing flow has been requested cancellation. Acknowledges the
* request if so. This must be called while locked in a synchronized context.
*
* @return Whether the data processing flow is cancelled.
*
* 如果是 取消请求 状态
* 则调用 CompiledRepository.acknowledgeCancel()
*/
private boolean checkCancellationLocked() {
if (runState == CANCEL_REQUESTED) {
workerHandler.obtainMessage(MSG_CALL_ACKNOWLEDGE_CANCEL, this).sendToTarget();
return true;
}
return false;
}
/**
* Called by the worker handler.
*
* 如果是 取消请求 状态
* 然后:
* 1. 将运行状态 设置为 闲置状态
* 2. 中间值赋上初始值
* 3. 标记为需要重启
*
* 然后开始重启流 maybeStartFlow()
*/
void acknowledgeCancel() {
boolean shouldStartFlow = false;
synchronized (this) {
if (runState == CANCEL_REQUESTED) {
runState = IDLE;
intermediateValue
= initialValue; // GC the intermediate value but keep field non-null.
shouldStartFlow = restartNeeded;
}
}
if (shouldStartFlow) {
maybeStartFlow();
}
}
/**
* Checks if the data processing flow needs restarting, and restarts it if so. This must be
* called
* while locked in a synchronized context and after the previous data processing flow has
* completed.
*
* 如果 已经标记了 需要重启
* 那么调用 CompiledRepository.maybeStartFlow()
*/
private void checkRestartLocked() {
if (restartNeeded) {
workerHandler.obtainMessage(MSG_CALL_MAYBE_START_FLOW, this).sendToTarget();
}
}
//endregion Acknowledging cancellation and restarting
//region Running directives
// The directive creation methods are interleaved here so the index-to-operator relation is clear.
private static final int END = 0;
private static final int GET_FROM = 1;
private static final int MERGE_IN = 2;
private static final int TRANSFORM = 3;
private static final int CHECK = 4;
private static final int GO_TO = 5;
private static final int GO_LAZY = 6;
private static final int SEND_TO = 7;
private static final int BIND = 8;
private static final int FILTER_SUCCESS = 9;
private static final int FILTER_FAILURE = 10;
/**
* @param asynchronously Whether this flow is run asynchronously. True after the first goTo and
* before goLazy. This is to omit unnecessarily locking the synchronized context to check for
* cancellation, because if the flow is run synchronously, cancellation requests theoretically
* cannot be delivered here.
*
* 获得所有 操作符指令 的 数组
* 开始遍历数组
* 1. 检查是否取消请求,是的话,直接退出循环
* 2. 子线程加载,调用 setPausedAtGoToLocked(...) ,从 子线程暂停 到 恢复 流执行
* 3. 懒加载
*
* 接着:
* 1. 检查运行状态是否是 取消请求,是的话 break
* 2. 如果是子线程执行的话,setPausedAtGoToLocked(...)
* 3. 如果是懒加载的话,setLazyAndEndFlowLocked(...)
*
* 最后:
* 分发指令,运行 不同的 操作符操作
*/
private void runFlowFrom(final int index, final boolean asynchronously) {
final Object[] directives = this.directives;
final int length = directives.length;
int i = index;
while (0 <= i && i < length) {
final int directiveType = (Integer) directives[i];
if (asynchronously || directiveType == GO_TO || directiveType == GO_LAZY) {
// Check cancellation before running the next directive. This needs to be done while locked.
// For goTo and goLazy, because they need to change the states and suspend the flow, they
// need the lock and are therefore treated specially here.
synchronized (this) {
if (checkCancellationLocked()) {
break;
}
if (directiveType == GO_TO) {
setPausedAtGoToLocked(i);
// the actual executor delivery is done below, outside the lock, to eliminate any
// deadlock possibility.
} else if (directiveType == GO_LAZY) {
setLazyAndEndFlowLocked(i);
return;
}
}
}
// A table-switch on a handful of options is a good compromise in code size and runtime
// performance comparing to a full-fledged double-dispatch pattern with subclasses.
switch (directiveType) {
case GET_FROM:
i = runGetFrom(directives, i);
break;
case MERGE_IN:
i = runMergeIn(directives, i);
break;
case TRANSFORM:
i = runTransform(directives, i);
break;
case CHECK:
i = runCheck(directives, i);
break;
case GO_TO:
i = runGoTo(directives, i);
break;
case SEND_TO:
i = runSendTo(directives, i);
break;
case BIND:
i = runBindWith(directives, i);
break;
case FILTER_SUCCESS:
i = runFilterSuccess(directives, i);
break;
case FILTER_FAILURE:
i = runFilterFailure(directives, i);
break;
case END:
i = runEnd(directives, i);
break;
// Missing GO_LAZY but it has already been dealt with in the synchronized block above.
}
}
}
/**
* 添加 getFrom 指令
* 到 指令集合 里
*
* getFrom 所在集合的位置,后面紧跟着
* getFrom 需要的 Supplier
*
* @param supplier getFrom 需要的 Supplier
* @param directives 指令集合
*/
static void addGetFrom(@NonNull final Supplier supplier,
@NonNull final List<Object> directives) {
directives.add(GET_FROM);
directives.add(supplier);
}
/**
* 开始 运行 getFrom(...) 操作符
*
* @param directives 指令集合
* @param index 索引
* @return 下个指令,由于一个指令,后紧跟着,指令需要的角色( Supplier,Function,Merger... )
* 所以要 +2
*/
private int runGetFrom(@NonNull final Object[] directives, final int index) {
final Supplier supplier = (Supplier) directives[index + 1];
intermediateValue = checkNotNull(supplier.get());
return index + 2;
}
/**
* 添加 mergeIn 指令
* 到 指令集合 里
*
* mergeIn 所在集合的位置,后面紧跟着
* 1. mergeIn 需要的 Supplier
* 2. mergeIn 需要的 Merger
*
* @param supplier mergeIn 需要的 Supplier
* @param merger mergeIn 需要的 Merger
* @param directives 指令集合
*/
static void addMergeIn(@NonNull final Supplier supplier, @NonNull final Merger merger,
@NonNull final List<Object> directives) {
directives.add(MERGE_IN);
directives.add(supplier);
directives.add(merger);
}
/**
* 开始 运行 mergeIn(...) 操作符
*
* @param directives 指令集合
* @param index 索引
* @return 下个指令,由于一个指令,后紧跟着,指令需要的角色( Supplier,Function,Merger... )
* 需要两个角色
* 所以要 +3
*/
private int runMergeIn(@NonNull final Object[] directives, final int index) {
final Supplier supplier = (Supplier) directives[index + 1];
final Merger merger = (Merger) directives[index + 2];
intermediateValue = checkNotNull(merger.merge(intermediateValue, supplier.get()));
return index + 3;
}
/**
* 添加 transform 指令
* 到 指令集合 里
*
* transform 所在集合的位置,后面紧跟着
* transform 需要的 Function
*
* @param function transform 需要的 Function
* @param directives 指令集合
*/
static void addTransform(@NonNull final Function function,
@NonNull final List<Object> directives) {
directives.add(TRANSFORM);
directives.add(function);
}
/**
* 开始 运行 transform(...) 操作符
*
* @param directives 指令集合
* @param index 索引
* @return 下个指令,由于一个指令,后紧跟着,指令需要的角色( Supplier,Function,Merger... )
* 所以要 +2
*/
private int runTransform(@NonNull final Object[] directives, final int index) {
final Function function = (Function) directives[index + 1];
intermediateValue = checkNotNull(function.apply(intermediateValue));
return index + 2;
}
/**
* 添加 check 指令
* 到 指令集合 里
*
* check 所在集合的位置,后面紧跟着
* 1. check 需要的 caseFunction
* 2. check 需要的 casePredicate
* 3. check 需要的 terminatingValueFunction
*
* @param caseFunction check 需要的 caseFunction
* @param casePredicate check 需要的 casePredicate
* @param terminatingValueFunction check 需要的 terminatingValueFunction
* @param directives 指令集合
*/
static void addCheck(@NonNull final Function caseFunction,
@NonNull final Predicate casePredicate,
@Nullable final Function terminatingValueFunction,
@NonNull final List<Object> directives) {
directives.add(CHECK);
directives.add(caseFunction);
directives.add(casePredicate);
directives.add(terminatingValueFunction);
}
/**
* 开始 运行 check(...) 操作符
*
* @param directives 指令集合
* @param index 索引
* @return 下个指令,由于一个指令,后紧跟着,指令需要的角色( Supplier,Function,Merger... )
* 需要三个角色
* 如果断定
* 成功了 +4,因为有三个角色
* 成功了返回 -1,表示终止,并且运行 runTerminate(...)
*/
private int runCheck(@NonNull final Object[] directives, final int index) {
final Function caseFunction = (Function) directives[index + 1];
final Predicate casePredicate = (Predicate) directives[index + 2];
final Function terminatingValueFunction = (Function) directives[index + 3];
final Object caseValue = caseFunction.apply(intermediateValue);
if (casePredicate.apply(caseValue)) {
return index + 4;
} else {
runTerminate(caseValue, terminatingValueFunction);
return -1;
}
}
/**
* 添加 goTo 指令
* 到 指令集合 里
*
* goTo 所在集合的位置,后面紧跟着
* goTo 需要的 Executor
*
* @param executor goTo 需要的 Executor
* @param directives 指令集合
*/
static void addGoTo(@NonNull final Executor executor, @NonNull final List<Object> directives) {
directives.add(GO_TO);
directives.add(executor);
}
/**
* 开始 运行 goTo(...) 操作符
*
* @param directives 指令集合
* @param index 索引
* @return 返回 -1 终止
*/
private int runGoTo(@NonNull final Object[] directives, final int index) {
Executor executor = (Executor) directives[index + 1];
executor.execute(this);
return -1;
}
/**
* 继续执行 goTo 后面的 指令
* 目前只在本类使用
*
* @param directives 指令集合
* @param index goTo 的 指令 index
* @return goTo 的下一个指令 的 index
*/
private static int continueFromGoTo(@NonNull final Object[] directives, final int index) {
checkState(directives[index].equals(GO_TO), "Inconsistent directive state for goTo");
return index + 2;
}
/**
* 添加 goLazy 指令
* 到 指令集合 里
*
* @param directives 指令集合
*/
static void addGoLazy(@NonNull final List<Object> directives) {
directives.add(GO_LAZY);
}
/**
* 继续执行 goLazy 后面的 指令
* 目前只在本类使用
*
* @param directives 指令集合
* @param index goLazy 的 指令 index
* @return goLazy 的下一个指令 的 index
*/
private static int continueFromGoLazy(@NonNull final Object[] directives, final int index) {
checkState(directives[index].equals(GO_LAZY), "Inconsistent directive state for goLazy");
return index + 1;
}
/**
* 添加 sendTo 指令
* 到 指令集合 里
*
* sendTo 所在集合的位置,后面紧跟着
* sendTo 需要的 Receiver
*
* @param receiver goTo 需要的 Receiver
* @param directives 指令集合
*/
static void addSendTo(
@NonNull final Receiver receiver, @NonNull final List<Object> directives) {
directives.add(SEND_TO);
directives.add(receiver);
}
/**
* 开始 运行 sendTo(...) 操作符
*
* @param directives 指令集合
* @param index 索引
* @return 下个指令,由于一个指令,后紧跟着,指令需要的角色( Supplier,Function,Merger... )
* 所以要 +2
*/
private int runSendTo(@NonNull final Object[] directives, final int index) {
Receiver receiver = (Receiver) directives[index + 1];
receiver.accept(intermediateValue);
return index + 2;
}
/**
* 添加 bindWith 指令
* 到 指令集合 里
*
* bindWith 所在集合的位置,后面紧跟着
* 1. bindWith 需要的 Supplier
* 2. bindWith 需要的 Receiver
*
* @param supplier bindWith 需要的 Supplier
* @param binder bindWith 需要的 Binder
* @param directives 指令集合
*/
static void addBindWith(@NonNull final Supplier supplier, @NonNull final Binder binder,
@NonNull final List<Object> directives) {
directives.add(BIND);
directives.add(supplier);
directives.add(binder);
}
/**
* 开始 运行 bindWith(...) 操作符
*
* @param directives 指令集合
* @param index 索引
* @return 下个指令,由于一个指令,后紧跟着,指令需要的角色( Supplier,Function,Merger... )
* 需要两个角色
* 所以要 +3
*/
private int runBindWith(@NonNull final Object[] directives, final int index) {
final Supplier supplier = (Supplier) directives[index + 1];
final Binder binder = (Binder) directives[index + 2];
binder.bind(intermediateValue, supplier.get());
return index + 3;
}
/**
* 添加 filterSuccess 指令
* 到 指令集合 里
*
* filterSuccess 所在集合的位置,后面紧跟着
* filterSuccess 需要的 terminatingValueFunction
*
* @param terminatingValueFunction filterSuccess 需要的 terminatingValueFunction
* @param directives 指令集合
*/
static void addFilterSuccess(
@Nullable final Function terminatingValueFunction, @NonNull final List<Object> directives) {
directives.add(FILTER_SUCCESS);
directives.add(terminatingValueFunction);
}
/**
* 开始 运行 filterSuccess(...) 操作符
*
* @param directives 指令集合
* @param index 索引
* @return 下个指令,由于一个指令,后紧跟着,指令需要的角色( Supplier,Function,Merger... )
* 需要一个角色
* 判断结果是否
* 成功,+2,因为有一个角色
* 失败,返回 -1,终止
*/
private int runFilterSuccess(@NonNull final Object[] directives, final int index) {
final Function terminatingValueFunction = (Function) directives[index + 1];
final Result tryValue = (Result) intermediateValue;
if (tryValue.succeeded()) {
intermediateValue = tryValue.get();
return index + 2;
} else {
runTerminate(tryValue.getFailure(), terminatingValueFunction);
return -1;
}
}
static void addFilterFailure(@NonNull final List<Object> directives) {
directives.add(FILTER_FAILURE);
}
private int runFilterFailure(@NonNull final Object[] directives, final int index) {
final Result tryValue = (Result) intermediateValue;
if (tryValue.succeeded()) {
runTerminate(tryValue.get(), identityFunction());
return -1;
} else {
intermediateValue = tryValue.getFailure();
return index + 1;
}
}
/**
* 终止状态
*
* @param terminatingValueFunction 结束时的转换方法
*/
private void runTerminate(@NonNull final Object caseValue,
@Nullable final Function terminatingValueFunction) {
if (terminatingValueFunction == null) {
skipAndEndFlow();
} else {
setNewValueAndEndFlow(checkNotNull(terminatingValueFunction.apply(caseValue)));
}
}
/**
* 添加 end 指令
* 到 指令集合 里
*
* end 所在集合的位置,后面紧跟着
* end 需要的 ship 标识
*
* @param skip end 需要的 ship 标识
* @param directives 指令集合
*/
static void addEnd(final boolean skip, @NonNull final List<Object> directives) {
directives.add(END);
directives.add(skip);
}
/**
* 开始 运行 end(...) 操作符
*
* @param directives 指令集合
* @param index 索引
* @return 返回 -1,终止
*/
private int runEnd(@NonNull final Object[] directives, final int index) {
final boolean skip = (Boolean) directives[index + 1];
if (skip) {
skipAndEndFlow();
} else {
setNewValueAndEndFlow(intermediateValue);
}
return -1;
}
//endregion Running directives
//region Completing, pausing and resuming flow
/**
* 快进 并 结束 流
*
* 设置 运行状态 为 闲置
* 中间值 设置为 初始值
*
* 调用 checkRestartLocked()
* 如果 已经标记了 需要重启
* 那么调用 CompiledRepository.maybeStartFlow()
*/
private synchronized void skipAndEndFlow() {
runState = IDLE;
intermediateValue
= initialValue; // GC the intermediate value but field must be kept non-null.
checkRestartLocked();
}
/**
* 设置 新值 并 结束 流
*
* 1. 检查 运行状态 是否是 懒加载运行,记录为 wasRunningLazily
* 2. 设置 运行状态 为 闲置
* 3. 中间值 设置为 初始值
* 4. 如果 wasRunningLazily 记录 为 true,当前值 设置为 新值
* 5. 如果 wasRunningLazily 记录 为 false,调用 setNewValueLocked(newValue)
* 6. 调用 checkRestartLocked()
* 如果 已经标记了 需要重启
* 那么调用 CompiledRepository.maybeStartFlow()
*
* @param newValue 新值
*/
private synchronized void setNewValueAndEndFlow(@NonNull final Object newValue) {
final boolean wasRunningLazily = runState == RUNNING_LAZILY;
runState = IDLE;
intermediateValue
= initialValue; // GC the intermediate value but field must be kept non-null.
if (wasRunningLazily) {
currentValue = newValue; // Don't notify if this new value is produced lazily
} else {
setNewValueLocked(newValue); // May notify otherwise
}
checkRestartLocked();
}
/**
* notifyChecker 实际上是一个 ObjectsUnequalMerger 对象
* 对象不相等 合并者,用于比较
*
* 1. 判断 新值 与 当前值 是否 相等,记录为 shouldNotify
* 2. 设置 当前值 等于 新值
* 3. 如果 shouldNotify 记录 为 true,dispatchUpdate() 通知所有观察者
*
* @param newValue 新值
*/
private void setNewValueLocked(@NonNull final Object newValue) {
final boolean shouldNotify = notifyChecker.merge(currentValue, newValue);
currentValue = newValue;
if (shouldNotify) {
dispatchUpdate();
}
}
/**
* goTo 指令,设置 暂停
*
* 1. lastDirectiveIndex 设置为 goTo 指令的 index
* 2. 设置 运行状态 为 子线程暂停
*
* @param resumeIndex goTo 指令的 index
*/
private void setPausedAtGoToLocked(final int resumeIndex) {
lastDirectiveIndex = resumeIndex;
runState = PAUSED_AT_GO_TO;
}
/** Called from the executor of a goTo instruction to continue processing. */
/**
* CompiledRepository 也作为 Runnable 这个角色
*
* 1. 保存 最后指令 lastDirectiveIndex 到 index
* 2. 检查 当前 运行状态:必须是 子线程暂停 或者 取消请求,不然报错
* 3. 设置 lastDirectiveIndex = -1
* 4. checkCancellationLocked(),
* 如果是 取消请求 状态
* 则调用 CompiledRepository.acknowledgeCancel()
*
* 然后返回
*
* 5. 设置 运行状态 为 运行
* 6. 记录 当前线程
* 7. runFlowFrom(continueFromGoTo(directives, index), true); 从 暂停 -> 恢复 流
* 8. Thread.interrupted(); 线程中断
* 9. 如果 执行 6 了,那么最后要,清空 当前线程的引用
*/
@Override
public void run() {
final Thread myThread = currentThread();
final int index;
synchronized (this) {
index = lastDirectiveIndex;
checkState(runState == PAUSED_AT_GO_TO || runState == CANCEL_REQUESTED,
"Illegal call of Runnable.run()");
lastDirectiveIndex = -1;
if (checkCancellationLocked()) {
return;
}
runState = RUNNING;
// allow thread interruption (set this when still holding the lock)
currentThread = myThread;
}
// leave the synchronization lock to run the rest of the flow
runFlowFrom(continueFromGoTo(directives, index), true);
// consume any unconsumed interrupted flag
Thread.interrupted();
// disallow interrupting the current thread, but chances are the next directive has started
// asynchronously, so check currentThread is still this thread. This also works if a goTo
// directive is given a synchronous executor, in which case the next part of the flow will
// have been completed by now and currentThread will have been reset by that invocation of
// runFlowFrom().
synchronized (this) {
if (currentThread == myThread) {
currentThread = null;
}
}
}
/**
* 设置 lazy 状态 并 结束 流
*
* 1. lastDirectiveIndex 设置为 goLazy 指令的 index
* 2. 设置 运行状态 为 懒加载暂停
* 3. 通知所有观察者 dispatchUpdate()
* 4. checkRestartLocked()
* 如果 已经标记了 需要重启
* 那么调用 CompiledRepository.maybeStartFlow()
*
* @param resumeIndex goLazy 指令的 index
*/
private void setLazyAndEndFlowLocked(final int resumeIndex) {
lastDirectiveIndex = resumeIndex;
runState = PAUSED_AT_GO_LAZY;
dispatchUpdate();
checkRestartLocked();
}
/**
* 获取 CompiledRepository 作为 仓库 角色 时
* 保存的 仓库数据
*
* 1. 如果 当前 运行状态 是 懒加载暂停
* 2. index = lastDirectiveIndex,拿到最后执行指令的 index
* 3. 运行状态 设置为 懒加载运行
* 4. runFlowFrom(...) 恢复流,继续执行,内部会对 currentValue 进行赋值
*
* 5. 返回 当前值/数据 ( currentValue )
*
* @return 仓库数据
*/
@NonNull
@Override
public synchronized Object get() {
if (runState == PAUSED_AT_GO_LAZY) {
final int index = lastDirectiveIndex;
runState = RUNNING_LAZILY;
runFlowFrom(continueFromGoLazy(directives, index), false);
}
return currentValue;
}
//endregion Completing, pausing and resuming flow
}