Merge branch 'improve-thread-encapsulation' into upstream

This commit is contained in:
Abraham Kiggundu
2015-01-05 11:07:55 +03:00
21 changed files with 1034 additions and 522 deletions

View File

@@ -11,6 +11,8 @@ import static java.util.logging.Level.WARNING;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;
import javax.inject.Inject;
@@ -56,14 +58,16 @@ Service, EventListener {
private final EventBus eventBus;
private final Context appContext;
private final Map<ContactId, Integer> contactCounts =
new HashMap<ContactId, Integer>(); // Locking: this
new HashMap<ContactId, Integer>();
private final Map<GroupId, Integer> groupCounts =
new HashMap<GroupId, Integer>(); // Locking: this
new HashMap<GroupId, Integer>();
private int privateTotal = 0, groupTotal = 0; // Locking: this
private int nextRequestId = 0; // Locking: this
private int privateTotal = 0, groupTotal = 0;
private int nextRequestId = 0;
private volatile Settings settings = new Settings();
private final Lock synchLock = new ReentrantLock();
@Inject
public AndroidNotificationManagerImpl(DatabaseComponent db,
@@ -103,22 +107,33 @@ Service, EventListener {
if(e instanceof SettingsUpdatedEvent) loadSettings();
}
public synchronized void showPrivateMessageNotification(ContactId c) {
Integer count = contactCounts.get(c);
if(count == null) contactCounts.put(c, 1);
else contactCounts.put(c, count + 1);
privateTotal++;
updatePrivateMessageNotification();
public void showPrivateMessageNotification(ContactId c) {
synchLock.lock();
try{
Integer count = contactCounts.get(c);
if(count == null) contactCounts.put(c, 1);
else contactCounts.put(c, count + 1);
privateTotal++;
updatePrivateMessageNotification();
}
finally{
synchLock.unlock();
}
}
public synchronized void clearPrivateMessageNotification(ContactId c) {
Integer count = contactCounts.remove(c);
if(count == null) return; // Already cleared
privateTotal -= count;
updatePrivateMessageNotification();
public void clearPrivateMessageNotification(ContactId c) {
synchLock.lock();
try{
Integer count = contactCounts.remove(c);
if(count == null) return; // Already cleared
privateTotal -= count;
updatePrivateMessageNotification();
}
finally{
synchLock.unlock();
}
}
// Locking: this
private void updatePrivateMessageNotification() {
if(privateTotal == 0) {
clearPrivateMessageNotification();
@@ -162,7 +177,6 @@ Service, EventListener {
}
}
// Locking: this
private void clearPrivateMessageNotification() {
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
NotificationManager nm = (NotificationManager) o;
@@ -180,22 +194,33 @@ Service, EventListener {
return defaults;
}
public synchronized void showGroupPostNotification(GroupId g) {
Integer count = groupCounts.get(g);
if(count == null) groupCounts.put(g, 1);
else groupCounts.put(g, count + 1);
groupTotal++;
updateGroupPostNotification();
public void showGroupPostNotification(GroupId g) {
synchLock.lock();
try{
Integer count = groupCounts.get(g);
if(count == null) groupCounts.put(g, 1);
else groupCounts.put(g, count + 1);
groupTotal++;
updateGroupPostNotification();
}
finally{
synchLock.unlock();
}
}
public synchronized void clearGroupPostNotification(GroupId g) {
public void clearGroupPostNotification(GroupId g) {
synchLock.lock();
try{
Integer count = groupCounts.remove(g);
if(count == null) return; // Already cleared
groupTotal -= count;
updateGroupPostNotification();
}
finally{
synchLock.unlock();
}
}
// Locking: this
private void updateGroupPostNotification() {
if(groupTotal == 0) {
clearGroupPostNotification();
@@ -238,18 +263,23 @@ Service, EventListener {
}
}
// Locking: this
private void clearGroupPostNotification() {
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
NotificationManager nm = (NotificationManager) o;
nm.cancel(GROUP_POST_NOTIFICATION_ID);
}
public synchronized void clearNotifications() {
contactCounts.clear();
groupCounts.clear();
privateTotal = groupTotal = 0;
clearPrivateMessageNotification();
clearGroupPostNotification();
public void clearNotifications() {
synchLock.lock();
try{
contactCounts.clear();
groupCounts.clear();
privateTotal = groupTotal = 0;
clearPrivateMessageNotification();
clearGroupPostNotification();
}
finally{
synchLock.unlock();
}
}
}

View File

@@ -4,6 +4,8 @@ import static java.util.logging.Level.INFO;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;
import org.briarproject.api.android.ReferenceManager;
@@ -13,49 +15,70 @@ class ReferenceManagerImpl implements ReferenceManager {
private static final Logger LOG =
Logger.getLogger(ReferenceManagerImpl.class.getName());
// Locking: this
private final Map<Class<?>, Map<Long, Object>> outerMap =
new HashMap<Class<?>, Map<Long, Object>>();
private long nextHandle = 0; // Locking: this
private long nextHandle = 0;
public synchronized <T> T getReference(long handle, Class<T> c) {
Map<Long, Object> innerMap = outerMap.get(c);
if(innerMap == null) {
private final Lock synchLock = new ReentrantLock();
public <T> T getReference(long handle, Class<T> c) {
synchLock.lock();
try{
Map<Long, Object> innerMap = outerMap.get(c);
if(innerMap == null) {
if(LOG.isLoggable(INFO))
LOG.info("0 handles for " + c.getName());
return null;
}
if(LOG.isLoggable(INFO))
LOG.info("0 handles for " + c.getName());
return null;
LOG.info(innerMap.size() + " handles for " + c.getName());
Object o = innerMap.get(handle);
return c.cast(o);
}
if(LOG.isLoggable(INFO))
LOG.info(innerMap.size() + " handles for " + c.getName());
Object o = innerMap.get(handle);
return c.cast(o);
finally{
synchLock.unlock();
}
}
public synchronized <T> long putReference(T reference, Class<T> c) {
Map<Long, Object> innerMap = outerMap.get(c);
if(innerMap == null) {
innerMap = new HashMap<Long, Object>();
outerMap.put(c, innerMap);
public <T> long putReference(T reference, Class<T> c) {
synchLock.lock();
try{
Map<Long, Object> innerMap = outerMap.get(c);
if(innerMap == null) {
innerMap = new HashMap<Long, Object>();
outerMap.put(c, innerMap);
}
long handle = nextHandle++;
innerMap.put(handle, reference);
if(LOG.isLoggable(INFO)) {
LOG.info(innerMap.size() + " handles for " + c.getName() +
" after put");
}
return handle;
}
long handle = nextHandle++;
innerMap.put(handle, reference);
if(LOG.isLoggable(INFO)) {
LOG.info(innerMap.size() + " handles for " + c.getName() +
" after put");
finally{
synchLock.unlock();
}
return handle;
}
public synchronized <T> T removeReference(long handle, Class<T> c) {
Map<Long, Object> innerMap = outerMap.get(c);
if(innerMap == null) return null;
Object o = innerMap.remove(handle);
if(innerMap.isEmpty()) outerMap.remove(c);
if(LOG.isLoggable(INFO)) {
LOG.info(innerMap.size() + " handles for " + c.getName() +
" after remove");
public <T> T removeReference(long handle, Class<T> c) {
synchLock.lock();
try{
Map<Long, Object> innerMap = outerMap.get(c);
if(innerMap == null) return null;
Object o = innerMap.remove(handle);
if(innerMap.isEmpty()) outerMap.remove(c);
if(LOG.isLoggable(INFO)) {
LOG.info(innerMap.size() + " handles for " + c.getName() +
" after remove");
}
return c.cast(o);
}
return c.cast(o);
finally{
synchLock.unlock();
}
}
}