Shared Preferences Async Mutex

Daniel Carneiro
3 min readJul 2, 2021

A data structure used to synchronize concurrent processes running on different threads. For example, before accessing a non-threadsafe resource, a thread will lock the mutex. This is guaranteed to block the thread until no other thread holds a lock on the mutex and thus enforces exclusive access to the resource. Once the operation is complete, the thread releases the lock, allowing other threads to acquire a lock and access the resource.

So after understanding that, I have created a class that controls the Flutter secure storage.

import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
/// A data structure used to synchronize concurrent processes running on different threads.
/// For example, before accessing a non-threadsafe resource, a thread will lock the mutex.
/// This is guaranteed to block the thread until no other thread holds a lock on the mutex and thus enforces exclusive access to the resource.
/// Once the operation is complete, the thread releases the lock, allowing other threads to acquire a lock and access the resource.
class AsyncMutex {
Completer<void>? _completer;
/// locks the mutex
Future<void> lock() async {
while (_completer != null) {
await _completer!.future;
}
_completer = Completer<void>();
}
/// unlocks the mutex
void unlock() {
assert(_completer != null);
final completer = _completer!;
_completer = null;
completer.complete();
}
}
class SecureStorage {
static const _secureStorage = FlutterSecureStorage();
static final _mutex = AsyncMutex();
/// [iOptions] requests will be sent when the user unlocks his device or else it won't be able to access the local storage in ios
final IOSOptions iosOptions = IOSOptions(accessibility: IOSAccessibility.first_unlock_this_device);
/// AES encryption is used for Android. AES secret key is encrypted with RSA and RSA key is stored in KeyStore
/// we can use EncryptedSharedPreferences on Android by enabling it in the Android Options like so:final AndroidOptions androidOptions = AndroidOptions(encryptedSharedPreferences: true);/// reads the data that contains the given [key] from flutter secure storage safely
/// will lock when is triggered and unlock when it has finished
Future<String?> read({required String key}) async {
try {
await _mutex.lock();
return await _secureStorage.read(
key: key,
iOptions: iosOptions,
aOptions: androidOptions,
);
} catch (e) {
debugPrint('ERROR: SecureStorage - read: ${e.toString()} ');
return null;
} finally {
_mutex.unlock();
}
}
/// writes the [key] and [value] to flutter secure storage safely
/// will lock when is triggered and unlock when it has finished
Future<void> write({required String key, String? value}) async {
try {
await _mutex.lock();
await _secureStorage.write(
key: key,
value: value,
iOptions: iosOptions,
aOptions: androidOptions,
);
} catch (e) {
debugPrint('ERROR: SecureStorage - write: ${e.toString()} ');
} finally {
_mutex.unlock();
}
}
/// deletes the [key] from flutter secure storage safely
/// will lock when is triggered and unlock when it has finished
Future<void> delete({required String key}) async {
try {
await _mutex.lock();
await _secureStorage.delete(
key: key,
iOptions: iosOptions,
aOptions: androidOptions,
);
} catch (e) {
debugPrint('ERROR: SecureStorage - delete: ${e.toString()} ');
} finally {
_mutex.unlock();
}
}
/// deletes all the keys from flutter secure storage safely
/// will lock when is triggered and unlock when it has finished
Future<void> deleteAll() async {
try {
await _mutex.lock();
await _secureStorage.deleteAll(
iOptions: iosOptions,,
aOptions: androidOptions,
);
} catch (e) {
debugPrint('ERROR: SecureStorage - deleteAll: ${e.toString()} ');
} finally {
_mutex.unlock();
}
}
}

Example:

final SecureStorage _secureStorage = SecureStorage();await _secureStorage.write(key: 'test', value: 'this is a test');var test = await _secureStorage.read(key: 'test');await _secureStorage.delete(key: 'test');await _secureStorage.deleteAll()

That’s all folks!

Did you know you can clap up to 50x times? Go ahead and clap is you like!

--

--