made i/o and memory intensive operations execute in serial order

This commit is contained in:
Daniel Gultsch 2015-06-05 08:46:06 +02:00
parent 31deb44780
commit 9d1e8205a2
2 changed files with 52 additions and 11 deletions

View file

@ -77,6 +77,7 @@ import eu.siacs.conversations.utils.ExceptionHelper;
import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
import eu.siacs.conversations.utils.PRNGFixes;
import eu.siacs.conversations.utils.PhoneHelper;
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
import eu.siacs.conversations.utils.Xmlns;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnBindListener;
@ -119,6 +120,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
startService(intent);
}
};
private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor();
private final SerialSingleThreadExecutor mDatabaseExecutor = new SerialSingleThreadExecutor();
private final IBinder mBinder = new XmppConnectionBinder();
private final List<Conversation> conversations = new CopyOnWriteArrayList<>();
private final FileObserver fileObserver = new FileObserver(
@ -373,7 +378,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
callback.success(message);
}
} else {
new Thread(new Runnable() {
mFileAddingExecutor.execute(new Runnable() {
@Override
public void run() {
try {
@ -388,8 +393,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
callback.error(e.getResId(),message);
}
}
}).start();
});
}
}
@ -405,7 +409,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
message.setCounterpart(conversation.getNextCounterpart());
message.setType(Message.TYPE_IMAGE);
new Thread(new Runnable() {
mFileAddingExecutor.execute(new Runnable() {
@Override
public void run() {
@ -420,7 +424,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
callback.error(e.getResId(), message);
}
}
}).start();
});
}
public Conversation find(Bookmark bookmark) {
@ -976,7 +980,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
Account account = accountLookupTable.get(conversation.getAccountUuid());
conversation.setAccount(account);
}
new Thread(new Runnable() {
Runnable runnable =new Runnable() {
@Override
public void run() {
Log.d(Config.LOGTAG,"restoring roster");
@ -997,7 +1001,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
Log.d(Config.LOGTAG,"restored all messages");
updateConversationUi();
}
}).start();
};
mDatabaseExecutor.execute(runnable);
}
}
@ -1066,7 +1071,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (XmppConnectionService.this.getMessageArchiveService().queryInProgress(conversation,callback)) {
return;
}
new Thread(new Runnable() {
Runnable runnable = new Runnable() {
@Override
public void run() {
final Account account = conversation.getAccount();
@ -1085,7 +1090,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
callback.informUser(R.string.fetching_history_from_server);
}
}
}).start();
};
mDatabaseExecutor.execute(runnable);
}
public List<Account> getAccounts() {
@ -2344,13 +2350,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
public void syncRosterToDisk(final Account account) {
new Thread(new Runnable() {
Runnable runnable = new Runnable() {
@Override
public void run() {
databaseBackend.writeRoster(account.getRoster());
}
}).start();
};
mDatabaseExecutor.execute(runnable);
}

View file

@ -0,0 +1,34 @@
package eu.siacs.conversations.utils;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class SerialSingleThreadExecutor implements Executor {
final Executor executor = Executors.newSingleThreadExecutor();
final Queue<Runnable> tasks = new ArrayDeque();
Runnable active;
public synchronized void execute(final Runnable r) {
tasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (active == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((active = tasks.poll()) != null) {
executor.execute(active);
}
}
}