1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package androidx.room
17 
18 import java.util.ArrayDeque
19 import java.util.concurrent.Executor
20 
21 /**
22  * Executor wrapper for performing database transactions serially.
23  *
24  * Since database transactions are exclusive, this executor ensures that transactions are performed
25  * in-order and one at a time, preventing threads from blocking each other when multiple concurrent
26  * transactions are attempted.
27  */
28 internal class TransactionExecutor(private val executor: Executor) : Executor {
29     private val tasks = ArrayDeque<Runnable>()
30     private var active: Runnable? = null
31     private val syncLock = Any()
32 
executenull33     override fun execute(command: Runnable) {
34         synchronized(syncLock) {
35             tasks.offer(
36                 Runnable {
37                     try {
38                         command.run()
39                     } finally {
40                         scheduleNext()
41                     }
42                 }
43             )
44             if (active == null) {
45                 scheduleNext()
46             }
47         }
48     }
49 
scheduleNextnull50     fun scheduleNext() {
51         synchronized(syncLock) {
52             if (tasks.poll().also { active = it } != null) {
53                 executor.execute(active)
54             }
55         }
56     }
57 }
58