/* * Copyright 2016 jeasonlzy(廖子尧) * * 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.lzy.okrx.subscribe; import com.lzy.okgo.adapter.Call; import com.lzy.okgo.model.Response; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import rx.Producer; import rx.Subscriber; import rx.Subscription; import rx.exceptions.CompositeException; import rx.exceptions.Exceptions; import rx.exceptions.OnCompletedFailedException; import rx.exceptions.OnErrorFailedException; import rx.exceptions.OnErrorNotImplementedException; import rx.plugins.RxJavaHooks; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ final class CallArbiter<T> extends AtomicInteger implements Subscription, Producer { private static final long serialVersionUID = 613435323949233509L; private static final int STATE_WAITING = 0; private static final int STATE_REQUESTED = 1; private static final int STATE_HAS_RESPONSE = 2; private static final int STATE_TERMINATED = 3; private final Call<T> call; private final Subscriber<? super Response<T>> subscriber; private volatile LinkedList<Response<T>> responseList; CallArbiter(Call<T> call, Subscriber<? super Response<T>> subscriber) { super(STATE_WAITING); responseList = new LinkedList<>(); this.call = call; this.subscriber = subscriber; } @Override public void unsubscribe() { call.cancel(); } @Override public boolean isUnsubscribed() { return call.isCanceled(); } @Override public void request(long amount) { if (amount == 0) { return; } while (true) { int state = get(); switch (state) { case STATE_WAITING: if (compareAndSet(STATE_WAITING, STATE_REQUESTED)) { return; } break; // State transition failed. Try again. case STATE_HAS_RESPONSE: if (STATE_HAS_RESPONSE == get()) { emitResponse(responseList); return; } break; // State transition failed. Try again. case STATE_REQUESTED: case STATE_TERMINATED: return; // Nothing to do. default: throw new IllegalStateException("Unknown state: " + state); } } } void emitNext(Response<T> response) { while (true) { int state = get(); switch (state) { case STATE_WAITING: synchronized (this) { responseList.add(response); } if (compareAndSet(STATE_WAITING, STATE_HAS_RESPONSE)) { return; } break; // State transition failed. Try again. case STATE_REQUESTED: synchronized (this) { responseList.add(response); } if (STATE_REQUESTED == get()) { emitResponse(responseList); return; } break; // State transition failed. Try again. case STATE_HAS_RESPONSE: case STATE_TERMINATED: throw new AssertionError(); default: throw new IllegalStateException("Unknown state: " + state); } } } private void emitResponse(List<Response<T>> responseList) { try { synchronized (this) { Iterator<Response<T>> iterator = responseList.iterator(); while (iterator.hasNext()) { Response<T> next = iterator.next(); iterator.remove(); if (!isUnsubscribed()) { subscriber.onNext(next); } else { return; } } } } catch (OnCompletedFailedException | OnErrorFailedException | OnErrorNotImplementedException e) { RxJavaHooks.getOnError().call(e); } catch (Throwable t) { Exceptions.throwIfFatal(t); try { subscriber.onError(t); } catch (OnCompletedFailedException | OnErrorFailedException | OnErrorNotImplementedException e) { RxJavaHooks.getOnError().call(e); } catch (Throwable inner) { Exceptions.throwIfFatal(inner); RxJavaHooks.getOnError().call(new CompositeException(t, inner)); } } } void emitComplete() { set(STATE_TERMINATED); try { if (!isUnsubscribed()) { subscriber.onCompleted(); } } catch (OnCompletedFailedException | OnErrorFailedException | OnErrorNotImplementedException e) { RxJavaHooks.getOnError().call(e); } catch (Throwable t) { Exceptions.throwIfFatal(t); RxJavaHooks.getOnError().call(t); } } void emitError(Throwable t) { set(STATE_TERMINATED); if (!isUnsubscribed()) { try { subscriber.onError(t); } catch (OnCompletedFailedException | OnErrorFailedException | OnErrorNotImplementedException e) { RxJavaHooks.getOnError().call(e); } catch (Throwable inner) { Exceptions.throwIfFatal(inner); RxJavaHooks.getOnError().call(new CompositeException(t, inner)); } } } }