package com.mogujie.tt.packet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.mogujie.tt.log.Logger;
import com.mogujie.tt.packet.action.Action;
import com.mogujie.tt.packet.base.Packet;
/**
* 消息队列,要通过socket发送的请求都必须提交到这个队列里面来
*
* @author dolphinWang
* @time 2014/4/30
*/
public class SocketMessageQueue {
@SuppressWarnings("unused")
private volatile static boolean mIsOffline;
private Logger logger = Logger.getLogger(SocketMessageQueue.class);
/*
* 等待队列,一个Action在被发送出去之后,会进入这个队列,等待对方返回
*/
private static final ConcurrentHashMap<Integer, Action> mWaitingList = new ConcurrentHashMap<Integer, Action>();
/*
* 任务队列,所有需要socket发送的任务都应该被提交到这个队列来
*/
private static final Queue<Action> mActionQueue = new LinkedList<Action>();
private static final int[] mMessages = new int[] {
MessageDispatchCenter.MESSAGE_OFFLINE,
MessageDispatchCenter.MESSAGE_ONLINE
};
private static Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MessageDispatchCenter.MESSAGE_OFFLINE:
mIsOffline = true;
break;
case MessageDispatchCenter.MESSAGE_ONLINE:
mIsOffline = false;
break;
}
super.handleMessage(msg);
}
};
private SocketMessageQueue() {
MessageDispatchCenter.getInstance().register(mHandler, mMessages);
}
private static class SingletonHolder {
static SocketMessageQueue queue = new SocketMessageQueue();
}
public static SocketMessageQueue getInstance() {
return SingletonHolder.queue;
}
public void clear() {
synchronized (mActionQueue) {
mActionQueue.clear();
}
synchronized (mWaitingList) {
mWaitingList.clear();
}
}
public void clearActionQueue() {
synchronized (mActionQueue) {
try {
while (mActionQueue.size() > 0) {
Action action = mActionQueue.poll();
if (null == action) {
continue;
}
Packet packet = action.getPacket();
if (null == packet) {
continue;
}
if (packet.getNeedMonitor()) {
add2WaitingList(action);
}
}
} catch (Exception e) {
logger.e(e.getMessage());
} finally {
mActionQueue.clear();
}
}
}
/**
* 把任务提交给任务队列
*
* @param action
*/
public void submitAndEnqueue(Action action) {
if (null == action)
return;
synchronized (mActionQueue) {
// 如果提交任务的时候正好的网络断开的时候,直接将任务抛弃
// FIXME: 可不可以不直接抛弃,也许入队之后socket连上了,就可以被发出去了
// FIXED: 任务队列会有缓冲
/*
* if (mIsOffline) { ActionCallback callback = action.getCallback();
* if (callback != null) { callback.onFaild(); } else {
* Log.w(getClass().getName(), "Wow this action have no callback!");
* } return; }
*/
// 检查一下是否存在
if (mActionQueue.contains(action)) {
// 把原来的任务移除掉
mActionQueue.remove(action);
}
// 分配一个sequence number
short seqNo = action.getPacket().getRequest().getHeader()
.getReserved();
action.setSquenceNo(seqNo);
mActionQueue.offer(action);
}
}
/**
* 从队列中获得一个任务,并不移除
*/
public Action getFront() {
synchronized (mActionQueue) {
if (mActionQueue.size() > 0) {
return mActionQueue.peek();
} else {
return null;
}
}
}
/**
* 从任务队列取出一个任务
*
* @return
*/
public Action pull() {
synchronized (mActionQueue) {
if (mActionQueue.size() > 0) {
return mActionQueue.poll();
} else {
return null;
}
}
}
/**
* 添加一个等待回复的任务到等待队列。
*
* @param action
*/
public void add2WaitingList(Action action) {
if (null == action)
return;
if (checkIsInMainThread()) {
throw new RuntimeException(
"Call from wrong thread! The main thread should not operate waiting list!");
}
synchronized (mWaitingList) {
// 国际惯例,检测是否任务存在
final int squenceNo = action.getSequenceNo();
if (mWaitingList.containsKey(squenceNo)) {
// 存在的remove掉,再重新入列
mWaitingList.remove(squenceNo);
}
mWaitingList.put(action.getSequenceNo(), action);
}
}
/**
* Get and remove an action from waiting list by sequence number.
*
* @param sequenceNo
* @return
*/
public Action getFromWaitingList(int sequenceNo) {
if (sequenceNo < 0) {
return null;
}
if (checkIsInMainThread()) {
throw new RuntimeException(
"Call from wrong thread! The main thread should not operate waiting list!");
}
Action actionRemoved = null;
synchronized (mWaitingList) {
boolean bContains = mWaitingList.containsKey(sequenceNo);
if (bContains) {
actionRemoved = mWaitingList.get(sequenceNo);
mWaitingList.remove(sequenceNo);
}
}
return actionRemoved;
}
public Map<Integer, Action> getWaitingList() {
if (checkIsInMainThread()) {
throw new RuntimeException(
"Call from wrong thread! The main thread should not operate waiting list!");
}
synchronized (mWaitingList) {
return mWaitingList;
}
}
/**
* 检测是否在主线程上面
*
* @return
*/
private boolean checkIsInMainThread() {
return Looper.getMainLooper().getThread() == Thread.currentThread();
}
public synchronized void stop() {
mHandler.removeCallbacksAndMessages(null);
MessageDispatchCenter.getInstance().unRegister(mHandler, mMessages);
}
}