-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathCriticalSectionsHandlerImpl.java
More file actions
121 lines (100 loc) · 3.06 KB
/
Copy pathCriticalSectionsHandlerImpl.java
File metadata and controls
121 lines (100 loc) · 3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package ru.yandex.yamblz.handler;
import android.os.Handler;
import android.os.Looper;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* Non thread-safe implementation of {@link CriticalSectionsHandler}.
*/
@SuppressWarnings("WeakerAccess")
public class CriticalSectionsHandlerImpl implements CriticalSectionsHandler {
private final Handler handler;
private final Set<Integer> sections;
private final Runnable executeTask;
private final Set<Task> taskQueue;
private final Map<Task, Runnable> delayedTasks;
public CriticalSectionsHandlerImpl() {
handler = new Handler(Looper.getMainLooper());
sections = new HashSet<>();
executeTask = buildExecuteTask();
taskQueue = new LinkedHashSet<>();
delayedTasks = new HashMap<>();
}
private Runnable buildExecuteTask() {
return () -> {
Task currentTask = null;
currentTask = taskQueue.iterator().next();
taskQueue.remove(currentTask);
// This runnable is in execution queue iff taskQueue is not empty.
assert currentTask != null;
currentTask.run();
if (!taskQueue.isEmpty() && sections.isEmpty()) {
handler.post(executeTask);
}
};
}
@Override
public void startSection(int id) {
sections.add(id);
if (!taskQueue.isEmpty()) {
handler.removeCallbacks(executeTask);
}
}
@Override
public void stopSection(int id) {
sections.remove(id);
if (sections.isEmpty()) {
if (!taskQueue.isEmpty()) {
handler.post(executeTask);
}
}
}
@Override
public void stopSections() {
sections.clear();
if (!taskQueue.isEmpty()) {
handler.post(executeTask);
}
}
@Override
public void postLowPriorityTask(Task task) {
if (taskQueue.add(task) && sections.isEmpty() && taskQueue.size() == 1) {
handler.post(executeTask);
}
delayedTasks.remove(task);
}
@Override
public void postLowPriorityTaskDelayed(Task task, int delayMillis) {
if (taskQueue.contains(task)) {
return;
}
Runnable runnable = () -> {
if (delayedTasks.containsKey(task)) {
postLowPriorityTask(task);
}
};
delayedTasks.put(task, runnable);
handler.postDelayed(runnable, delayMillis);
}
@Override
public void removeLowPriorityTask(Task task) {
if (taskQueue.contains(task)) {
taskQueue.remove(task);
if (taskQueue.isEmpty()) {
handler.removeCallbacks(executeTask);
}
}
if (delayedTasks.containsKey(task)) {
delayedTasks.remove(task);
}
}
@Override
public void removeLowPriorityTasks() {
taskQueue.clear();
delayedTasks.clear();
handler.removeCallbacks(executeTask);
}
}