androidx.datastore の DataStore はデータを非同期にストレージへ読み書きするためのフレームワークです。
DataStore は 1 つのファイルに対しデータの読み書きを実行するので、同一のプロセス内では必ず DataStore のインスタンスは 1 つ(シングルトン)に限らなければなりません。同一プロセス内で複数のおなじ DataStore インスタンスを使おうとすると例外が発生します。この制限は複数のプロセスで同じ DataStore を使う場合にも適用されますが、Java/Kotlin が提供している Mutex や Semaphore などではプロセスを超える排他制御ができないため、DataStore の作り方がすこし異なります。
複数のプロセスで同一の DataStore を使う場合、DataStore は MultiProcessDataStoreFactory
をつかって初期化します。このとき、どのプロセスでも必ず MultiProcessDataStoreFactory
を使って初期化しなければなりません。
MultiProcessDataStoreFactory
を使うと、内部で FileLock
を使ったファイルロックの仕組みで排他制御されます。
ファイルロックによる排他制御は MultiProcessCoordinator
が実装していて、実はこの MultiProcessCoordinator
は createMultiProcessCoordinator
を呼び出すことで DataStore 以外の場所でも使えます。
次のコード例では DataStore は使わず Mutex を使うのと同じ感覚でクリティカルセクションを定義できます。
Kotlin では Mutex#withLock
でブロックを抜けたときにロックを解除しますが、MultiProcessCoordinator
は lock
のブロックを抜けたときにファイルロックを解除します。
class Sample( coroutineScope: CoroutineScope, ) { private val lockFile = File(context.filesDir, "my_critical_section_lock") private val coordinator = createMultiProcessCoordinator( coroutineScope.coroutineContext, lockFile ) suspend fun somethingImportant() { coordinator.lock { // critical section // do some work! } } }