run roster sync in replacing task manager
This commit is contained in:
		
							parent
							
								
									9908af6286
								
							
						
					
					
						commit
						ba91fe2698
					
				| 
						 | 
				
			
			@ -105,6 +105,7 @@ import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
 | 
			
		|||
import eu.siacs.conversations.utils.PRNGFixes;
 | 
			
		||||
import eu.siacs.conversations.utils.PhoneHelper;
 | 
			
		||||
import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
 | 
			
		||||
import eu.siacs.conversations.utils.ReplacingTaskManager;
 | 
			
		||||
import eu.siacs.conversations.utils.Resolver;
 | 
			
		||||
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
 | 
			
		||||
import eu.siacs.conversations.xml.Namespace;
 | 
			
		||||
| 
						 | 
				
			
			@ -157,6 +158,7 @@ public class XmppConnectionService extends Service {
 | 
			
		|||
	private final SerialSingleThreadExecutor mDatabaseWriterExecutor = new SerialSingleThreadExecutor("DatabaseWriter");
 | 
			
		||||
	private final SerialSingleThreadExecutor mDatabaseReaderExecutor = new SerialSingleThreadExecutor("DatabaseReader");
 | 
			
		||||
	private final SerialSingleThreadExecutor mNotificationExecutor = new SerialSingleThreadExecutor("NotificationExecutor");
 | 
			
		||||
	private final ReplacingTaskManager mRosterSyncTaskManager = new ReplacingTaskManager();
 | 
			
		||||
	private final IBinder mBinder = new XmppConnectionBinder();
 | 
			
		||||
	private final List<Conversation> conversations = new CopyOnWriteArrayList<>();
 | 
			
		||||
	private final IqGenerator mIqGenerator = new IqGenerator(this);
 | 
			
		||||
| 
						 | 
				
			
			@ -1459,7 +1461,7 @@ public class XmppConnectionService extends Service {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
	public void syncRoster(final Account account) {
 | 
			
		||||
		mDatabaseWriterExecutor.execute(() -> databaseBackend.writeRoster(account.getRoster()));
 | 
			
		||||
		mRosterSyncTaskManager.execute(account, () -> databaseBackend.writeRoster(account.getRoster()));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public List<Conversation> getConversations() {
 | 
			
		||||
| 
						 | 
				
			
			@ -1855,6 +1857,7 @@ public class XmppConnectionService extends Service {
 | 
			
		|||
			};
 | 
			
		||||
			mDatabaseWriterExecutor.execute(runnable);
 | 
			
		||||
			this.accounts.remove(account);
 | 
			
		||||
			this.mRosterSyncTaskManager.clear(account);
 | 
			
		||||
			updateAccountUi();
 | 
			
		||||
			getNotificationService().updateErrorNotification();
 | 
			
		||||
			syncEnabledAccountSetting();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,13 +2,13 @@ package eu.siacs.conversations.utils;
 | 
			
		|||
 | 
			
		||||
public class ReplacingSerialSingleThreadExecutor extends SerialSingleThreadExecutor {
 | 
			
		||||
 | 
			
		||||
    public ReplacingSerialSingleThreadExecutor(boolean prepareLooper) {
 | 
			
		||||
        super(ReplacingSerialSingleThreadExecutor.class.getName(), prepareLooper);
 | 
			
		||||
    }
 | 
			
		||||
	public ReplacingSerialSingleThreadExecutor(boolean prepareLooper) {
 | 
			
		||||
		super(ReplacingSerialSingleThreadExecutor.class.getName(), prepareLooper);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public synchronized void execute(final Runnable r) {
 | 
			
		||||
        tasks.clear();
 | 
			
		||||
        super.execute(r);
 | 
			
		||||
    }
 | 
			
		||||
	@Override
 | 
			
		||||
	public synchronized void execute(final Runnable r) {
 | 
			
		||||
		tasks.clear();
 | 
			
		||||
		super.execute(r);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Daniel Gultsch All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without modification,
 | 
			
		||||
 * are permitted provided that the following conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright notice, this
 | 
			
		||||
 * list of conditions and the following disclaimer.
 | 
			
		||||
 *
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
			
		||||
 * this list of conditions and the following disclaimer in the documentation and/or
 | 
			
		||||
 * other materials provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * 3. Neither the name of the copyright holder nor the names of its contributors
 | 
			
		||||
 * may be used to endorse or promote products derived from this software without
 | 
			
		||||
 * specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 | 
			
		||||
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 | 
			
		||||
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 | 
			
		||||
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package eu.siacs.conversations.utils;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
 | 
			
		||||
import eu.siacs.conversations.entities.Account;
 | 
			
		||||
 | 
			
		||||
public class ReplacingTaskManager {
 | 
			
		||||
 | 
			
		||||
	private final HashMap<Account, ReplacingSerialSingleThreadExecutor> executors = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
	public void execute(final Account account, Runnable runnable) {
 | 
			
		||||
		ReplacingSerialSingleThreadExecutor executor;
 | 
			
		||||
		synchronized (this.executors) {
 | 
			
		||||
			executor = this.executors.get(account);
 | 
			
		||||
			if (executor == null) {
 | 
			
		||||
				executor = new ReplacingSerialSingleThreadExecutor(false);
 | 
			
		||||
				this.executors.put(account, executor);
 | 
			
		||||
			}
 | 
			
		||||
			executor.execute(runnable);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void clear(Account account) {
 | 
			
		||||
		synchronized (this.executors) {
 | 
			
		||||
			this.executors.remove(account);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -13,8 +13,8 @@ import eu.siacs.conversations.services.AttachFileToConversationRunnable;
 | 
			
		|||
 | 
			
		||||
public class SerialSingleThreadExecutor implements Executor {
 | 
			
		||||
 | 
			
		||||
	final Executor executor = Executors.newSingleThreadExecutor();
 | 
			
		||||
	protected final ArrayDeque<Runnable> tasks = new ArrayDeque<>();
 | 
			
		||||
	private final Executor executor = Executors.newSingleThreadExecutor();
 | 
			
		||||
	final ArrayDeque<Runnable> tasks = new ArrayDeque<>();
 | 
			
		||||
	private Runnable active;
 | 
			
		||||
	private final String name;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,26 +22,19 @@ public class SerialSingleThreadExecutor implements Executor {
 | 
			
		|||
		this(name, false);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public SerialSingleThreadExecutor(String name, boolean prepareLooper) {
 | 
			
		||||
	SerialSingleThreadExecutor(String name, boolean prepareLooper) {
 | 
			
		||||
		if (prepareLooper) {
 | 
			
		||||
			execute(new Runnable() {
 | 
			
		||||
				@Override
 | 
			
		||||
				public void run() {
 | 
			
		||||
					Looper.prepare();
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
			execute(Looper::prepare);
 | 
			
		||||
		}
 | 
			
		||||
		this.name = name;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public synchronized void execute(final Runnable r) {
 | 
			
		||||
		tasks.offer(new Runnable() {
 | 
			
		||||
			public void run() {
 | 
			
		||||
				try {
 | 
			
		||||
					r.run();
 | 
			
		||||
				} finally {
 | 
			
		||||
					scheduleNext();
 | 
			
		||||
				}
 | 
			
		||||
		tasks.offer(() -> {
 | 
			
		||||
			try {
 | 
			
		||||
				r.run();
 | 
			
		||||
			} finally {
 | 
			
		||||
				scheduleNext();
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
		if (active == null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -49,7 +42,7 @@ public class SerialSingleThreadExecutor implements Executor {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected synchronized void scheduleNext() {
 | 
			
		||||
	private synchronized void scheduleNext() {
 | 
			
		||||
		if ((active =  tasks.poll()) != null) {
 | 
			
		||||
			executor.execute(active);
 | 
			
		||||
			int remaining = tasks.size();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue