Last updated:
0 purchases
shared map
shared_map #
The package shared_map provides a versatile and synchronized Map data structure for Dart applications. This package is
designed to facilitate efficient sharing and communication of synchronized key-value pairs between different parts of your Dart
application, including Isolates or external applications.
Motivation #
Modern Dart applications often involve complex architectures with multiple Isolates or concurrent execution
environments. In such scenarios, efficient communication and synchronization of shared data become fundamental.
The shared_map package was created with the following motivations:
Simplified Sharing:
Sharing data across different parts of an application, especially Isolates, is often complex. The shared_map
package simplifies this process by offering a shared and synchronized map structure.
Concurrency-Friendly:
Managing concurrent execution requires careful consideration of data access and modification. The shared_map
package is crafted to be concurrency-friendly, ensuring safe access and updates to shared data across multiple
execution contexts.
Scalability:
As applications grow and incorporate more concurrent patterns, having a dependable and scalable mechanism for sharing
state becomes essential, especially across Isolates. The shared_map package plays a role in enhancing the scalability of Dart applications by
providing an efficient tool for data sharing.
Usage #
To use a SharedMap, first, create a SharedStore, then call getSharedMap.
To pass it to another Isolate, use its SharedReference returned by SharedMap.shareReference(),
then instantiate it with SharedMap.fromSharedReference(sharedMapReference).
Example:
import 'dart:io' show exit;
import 'dart:isolate';
import 'package:shared_map/shared_map.dart';
void main() async {
var store1 = SharedStore('t1');
var m1 = await store1.getSharedMap<String, int>('m1');
var va1 = await m1!.get('a'); // return `null`
print('get> va1: $va1');
var va2 = m1.put('a', 11); // put and return `11`
print('put> va2: $va2');
final sharedMapReference = m1.sharedReference();
print('sharedMapReference: $sharedMapReference');
// Use the `SharedMap` inside an `Isolate`:
var va3 = await Isolate.run<int?>(() async {
// Instantiate from `sharedMapReference`:
var m2 = SharedMap<String, int>.fromSharedReference(sharedMapReference);
var va3 = await m2.get('a'); // return `11`
return va3;
}); // Isolate returns 11
print('Isolate return> va3: $va3');
// Use the `SharedMap` inside another `Isolate`:
var va4 = await Isolate.run<int?>(() async {
// Instantiate from `sharedMapReference`:
var m3 = SharedMap<String, int>.fromSharedReference(sharedMapReference);
var va4 = await m3.put('a', 111); // put and return 111
return va4;
}); // Isolate returns 111
print('Isolate return> va4: $va4');
final sharedMapID = sharedMapReference.id;
print('sharedMapID: $sharedMapID');
final sharedStoreReference = store1.sharedReference();
print('shareStoreReference: $sharedStoreReference');
// Use the `SharedStore` inside another `Isolate`:
var va5 = await Isolate.run<int?>(() async {
// Instantiate from `shareStoreReference`:
var store2 = SharedStore.fromSharedReference(sharedStoreReference);
// Get the `SharedMap` through the `SharedStore`:
var m4 = await store2.getSharedMap(sharedMapID);
var va5 = await m4?.put('a', 222); // put and return `222`
return va5;
});
print('Isolate return> va5: $va5'); // print `222`
var va6 = await m1.get('a');
print('get> va6: $va6'); // print `222`
var va7 = await m1.get('a');
print('get> va7: $va7'); // print `222`
var va8 = await m1.putIfAbsent('a', 1001);
print('putIfAbsent> va8: $va8'); // print `1001`
var va9 = await Isolate.run<int?>(() async {
var store4 = SharedStore.fromSharedReference(sharedStoreReference);
var m6 = await store4.getSharedMap(sharedMapID);
var va9 = await m6?.putIfAbsent('a', 1001);
return va9;
});
print('Isolate return> va9: $va9'); // print `222`
var vb1 = await m1.putIfAbsent('b', 2001);
print('putIfAbsent> vb1: $vb1'); // print `2001`
print('get> vb1: ${await m1.get('b')}'); // print `2001`
var vc1 = await Isolate.run<int?>(() async {
var store5 = SharedStore.fromSharedReference(sharedStoreReference);
var m7 = await store5.getSharedMap(sharedMapID);
var vc1 = await m7?.putIfAbsent('c', 3001);
return vc1;
});
print('Isolate return> vc1: $vc1'); // print `3001`
print('get> vc1: ${await m1.get('c')}'); // print `3001`
exit(0);
}
copied to clipboard
Output:
get> va1: null
put> va2: 11
sharedMapReference: SharedMapReference{id: m1, sharedStore: {id: t1}}
Isolate return> va3: 11
Isolate return> va4: 111
sharedMapID: m1
shareStoreReference: SharedStoreReference{id: t1}
Isolate return> va5: 222
get> va6: 222
get> va7: 222
putIfAbsent> va8: 222
Isolate return> va9: 222
putIfAbsent> vb1: 2001
get> vb1: 2001
Isolate return> vc1: 3001
get> vc1: 3001
copied to clipboard
How it Works #
When operating on a Dart platform with Isolates, the mechanism involves a "server" version of a SharedStore
or SharedMap residing in the main Isolate responsible for storing data. Simultaneously, auxiliary Isolates host a
"client" version of these shared instances.
In the auxiliary Isolates, every get or put action on the SharedMap triggers an
Isolate message to the "server" version, fetching the current value in the Isolate.
To optimize performance and
circumvent unnecessary Isolate requests, consider utilizing the cached version of the SharedMap (SharedMapCache).
Note that the main Isolate is the one that created the SharedStore or SharedMap instance,
and the auxiliary Isolates are the one that "gets" an instance from a sharedReference.
Features and bugs #
Please file feature requests and bugs at the issue tracker.
Author #
Graciliano M. Passos: gmpassos@GitHub.
Sponsor #
Don't be shy, show some love, and become our GitHub Sponsor.
Your support means the world to us, and it keeps the code caffeinated! ☕✨
Thanks a million! 🚀😄
License #
Apache License - Version 2.0
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.