
com.path.android.jobqueue.nonPersistentQueue.MergedQueue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of android-priority-jobqueue Show documentation
Show all versions of android-priority-jobqueue Show documentation
a Job Queue specifically written for Android to easily schedule jobs (tasks) that run in the background, improving UX and application stability.
package com.path.android.jobqueue.nonPersistentQueue;
import com.path.android.jobqueue.JobHolder;
import java.util.*;
/**
* A queue implementation that utilize two queues depending on one or multiple properties of the {@link JobHolder}
* While retrieving items, it uses a different comparison method to handle dynamic comparisons (e.g. time)
* between two queues
*/
abstract public class MergedQueue implements JobSet {
JobSet queue0;
JobSet queue1;
final Comparator comparator;
final Comparator retrieveComparator;
/**
*
* @param initialCapacity passed to {@link MergedQueue#createQueue(com.path.android.jobqueue.nonPersistentQueue.MergedQueue.SetId, int, java.util.Comparator)}
* @param comparator passed to {@link MergedQueue#createQueue(com.path.android.jobqueue.nonPersistentQueue.MergedQueue.SetId, int, java.util.Comparator)}
* @param retrieveComparator upon retrieval, if both queues return items, this comparator is used to decide which
* one should be returned
*/
public MergedQueue(int initialCapacity, Comparator comparator, Comparator retrieveComparator) {
this.comparator = comparator;
this.retrieveComparator = retrieveComparator;
queue0 = createQueue(SetId.S0, initialCapacity, comparator);
queue1 = createQueue(SetId.S1, initialCapacity, comparator);
}
/**
* used to poll from one of the queues
* @param queueId
* @return
*/
protected JobHolder pollFromQueue(SetId queueId, Collection excludeGroupIds) {
if(queueId == SetId.S0) {
return queue0.poll(excludeGroupIds);
}
return queue1.poll(excludeGroupIds);
}
/**
* used to peek from one of the queues
* @param queueId
* @return
*/
protected JobHolder peekFromQueue(SetId queueId, Collection excludeGroupIds) {
if(queueId == SetId.S0) {
return queue0.peek(excludeGroupIds);
}
return queue1.peek(excludeGroupIds);
}
/**
* {@inheritDoc}
*/
@Override
public boolean offer(JobHolder jobHolder) {
SetId queueId = decideQueue(jobHolder);
if(queueId == SetId.S0) {
return queue0.offer(jobHolder);
}
return queue1.offer(jobHolder);
}
/**
* {@inheritDoc}
*/
@Override
public JobHolder poll(Collection excludeGroupIds) {
JobHolder delayed = queue0.peek(excludeGroupIds);
if(delayed == null) {
return queue1.poll(excludeGroupIds);
}
//if queue for this job has changed, re-add it and try poll from scratch
if(decideQueue(delayed) != SetId.S0) {
//should be moved to the other queue
queue0.remove(delayed);
queue1.offer(delayed);
return poll(excludeGroupIds);
}
JobHolder nonDelayed = queue1.peek(excludeGroupIds);
if(nonDelayed == null) {
queue0.remove(delayed);
return delayed;
}
//if queue for this job has changed, re-add it and try poll from scratch
if(decideQueue(nonDelayed) != SetId.S1) {
queue0.offer(nonDelayed);
queue1.remove(nonDelayed);
return poll(excludeGroupIds);
}
//both are not null, need to compare and return the better
int cmp = retrieveComparator.compare(delayed, nonDelayed);
if(cmp == -1) {
queue0.remove(delayed);
return delayed;
} else {
queue1.remove(nonDelayed);
return nonDelayed;
}
}
/**
* {@inheritDoc}
*/
@Override
public JobHolder peek(Collection excludeGroupIds) {
JobHolder delayed = queue0.peek(excludeGroupIds);
//if queue for this job has changed, re-add it and try peek from scratch
if(delayed != null && decideQueue(delayed) != SetId.S0) {
queue1.offer(delayed);
queue0.remove(delayed);
return peek(excludeGroupIds);
}
JobHolder nonDelayed = queue1.peek(excludeGroupIds);
//if queue for this job has changed, re-add it and try peek from scratch
if(nonDelayed != null && decideQueue(nonDelayed) != SetId.S1) {
queue0.offer(nonDelayed);
queue1.remove(nonDelayed);
return peek(excludeGroupIds);
}
if(delayed == null) {
return nonDelayed;
}
if(nonDelayed == null) {
return delayed;
}
int cmp = retrieveComparator.compare(delayed, nonDelayed);
if(cmp == -1) {
return delayed;
}
return nonDelayed;
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
queue1.clear();
queue0.clear();
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(JobHolder holder) {
//we cannot check queue here, might be dynamic
return queue1.remove(holder) || queue0.remove(holder);
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return queue0.size() + queue1.size();
}
/**
* decides which queue should the job holder go
* if first queue, should return 0
* if second queue, should return 1
* is only called when an item is inserted. methods like remove always call both queues.
* @param jobHolder
* @return
*/
abstract protected SetId decideQueue(JobHolder jobHolder);
/**
* called when we want to create the subsequent queues
* @param initialCapacity
* @param comparator
* @return
*/
abstract protected JobSet createQueue(SetId setId, int initialCapacity, Comparator comparator);
public CountWithGroupIdsResult countReadyJobs(SetId setId, long now, Collection excludeGroups) {
if(setId == SetId.S0) {
return queue0.countReadyJobs(now, excludeGroups);
} else {
return queue1.countReadyJobs(now, excludeGroups);
}
}
public CountWithGroupIdsResult countReadyJobs(SetId setId, Collection excludeGroups) {
if(setId == SetId.S0) {
return queue0.countReadyJobs(excludeGroups);
} else {
return queue1.countReadyJobs(excludeGroups);
}
}
/**
* simple enum to identify queues
*/
protected static enum SetId {
S0,
S1
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy