package com.raizlabs.android.dbflow.structure.database.transaction;
import android.os.Looper;
import com.raizlabs.android.dbflow.config.FlowLog;
import java.util.Iterator;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Description: Handles concurrent requests to the database and puts them in FIFO order based on a
* {@link LinkedBlockingQueue}. As requests come in, they're placed in order and ran one at a time
* until the queue becomes empty.
*/
public class DefaultTransactionQueue extends Thread implements ITransactionQueue {
private final LinkedBlockingQueue<Transaction> queue;
private boolean isQuitting = false;
/**
* Creates a queue with the specified name to ID it.
*
* @param name
*/
public DefaultTransactionQueue(String name) {
super(name);
queue = new LinkedBlockingQueue<>();
}
@SuppressWarnings("unchecked")
@Override
public void run() {
Looper.prepare();
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
Transaction transaction;
while (true) {
try {
transaction = queue.take();
} catch (InterruptedException e) {
synchronized (this) {
if (isQuitting) {
synchronized (queue) {
queue.clear();
}
return;
}
}
continue;
}
if (!isQuitting) {
transaction.executeSync();
}
}
}
@Override
public void add(Transaction runnable) {
synchronized (queue) {
if (!queue.contains(runnable)) {
queue.add(runnable);
}
}
}
/**
* Cancels the specified request.
*
* @param runnable
*/
@Override
public void cancel(Transaction runnable) {
synchronized (queue) {
if (queue.contains(runnable)) {
queue.remove(runnable);
}
}
}
/**
* Cancels all requests by a specific tag
*
* @param tag
*/
@Override
public void cancel(String tag) {
synchronized (queue) {
Iterator<Transaction> it = queue.iterator();
while (it.hasNext()) {
Transaction next = it.next();
if (next.name() != null && next.name().equals(tag)) {
it.remove();
}
}
}
}
@Override
public void startIfNotAlive() {
synchronized (this) {
if (!isAlive()) {
try {
start();
} catch (IllegalThreadStateException i) {
// log if failure from thread is still alive.
FlowLog.log(FlowLog.Level.E, i);
}
}
}
}
/**
* Quits this process
*/
@Override
public void quit() {
synchronized (this) {
isQuitting = true;
}
interrupt();
}
}