CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-tencent--mmkv-static

High-performance, cross-platform key-value storage framework with static C++ linking for Android applications

Pending
Overview
Eval results
Files

process-management.mddocs/

Process Management and Synchronization

MMKV provides robust multi-process synchronization capabilities, allowing safe concurrent access across Android processes with file locking, content change notifications, and automatic synchronization.

Capabilities

Process Locking

MMKV provides inter-process exclusive locking for safe concurrent access across multiple processes.

/**
 * Exclusively inter-process lock the MMKV instance.
 * It will block and wait until it successfully locks the file.
 * It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
 */
void lock();

/**
 * Exclusively inter-process unlock the MMKV instance.
 * It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
 */
void unlock();

/**
 * Try exclusively inter-process lock the MMKV instance.
 * It will not block if the file has already been locked by another process.
 * It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
 * @return True if successfully locked, otherwise return immediately with False
 */
boolean tryLock();

Usage Examples:

// Create multi-process MMKV instance
MMKV sharedKv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE);

// Blocking lock - waits until lock is acquired
sharedKv.lock();
try {
    // Critical section - only one process can access at a time
    sharedKv.encode("shared_counter", sharedKv.decodeInt("shared_counter", 0) + 1);
    sharedKv.encode("last_modified", System.currentTimeMillis());
} finally {
    // Always unlock in finally block
    sharedKv.unlock();
}

// Non-blocking lock attempt
if (sharedKv.tryLock()) {
    try {
        // Got the lock, perform operations
        sharedKv.encode("optional_update", "updated");
    } finally {
        sharedKv.unlock();
    }
} else {
    Log.d("MMKV", "Could not acquire lock, skipping update");
}

Data Synchronization

MMKV provides explicit synchronization methods for ensuring data persistence, though data is normally persisted immediately.

/**
 * Save all mmap memory to file synchronously.
 * You don't need to call this, really, I mean it.
 * Unless you worry about the device running out of battery.
 */
void sync();

/**
 * Save all mmap memory to file asynchronously.
 * No need to call this unless you worry about the device running out of battery.
 */
void async();

Usage Examples:

MMKV kv = MMKV.mmkvWithID("important_data");

// Store critical data
kv.encode("critical_setting", importantValue);

// Force synchronous write to disk (usually not needed)
kv.sync();

// Or force asynchronous write
kv.async();

// Note: MMKV automatically persists data immediately, these calls are optional

Content Change Notifications

MMKV provides inter-process content change notifications to detect when data is modified by other processes.

/**
 * Register for MMKV inter-process content change notification.
 * The notification will trigger only when any method is manually called on the MMKV instance.
 * For example checkContentChangedByOuterProcess().
 * @param notify The notification handler
 */
static void registerContentChangeNotify(MMKVContentChangeNotification notify);

/**
 * Unregister for MMKV inter-process content change notification.
 */
static void unregisterContentChangeNotify();

/**
 * Check inter-process content change manually.
 */
void checkContentChangedByOuterProcess();

Usage Examples:

// Set up content change notification
MMKV.registerContentChangeNotify(new MMKVContentChangeNotification() {
    @Override
    public void onContentChangedByOuterProcess(String mmapID) {
        Log.d("MMKV", "Content changed in instance: " + mmapID);
        
        // Refresh UI or reload data as needed
        if ("shared_config".equals(mmapID)) {
            reloadConfiguration();
        }
    }
});

// In your activity or service
MMKV sharedConfig = MMKV.mmkvWithID("shared_config", MMKV.MULTI_PROCESS_MODE);

// Periodically check for changes from other processes
private void checkForUpdates() {
    sharedConfig.checkContentChangedByOuterProcess();
    // If content changed, onContentChangedByOuterProcess() will be called
}

// Clean up when done
@Override
protected void onDestroy() {
    super.onDestroy();
    MMKV.unregisterContentChangeNotify();
}

Process Mode Management

MMKV provides utilities for managing and validating process modes to prevent conflicts.

/**
 * Manually enable the process mode checker.
 * By default, it's automatically enabled in DEBUG build, and disabled in RELEASE build.
 * If it's enabled, MMKV will throw exceptions when an MMKV instance is created with mismatch process mode.
 */
static void enableProcessModeChecker();

/**
 * Manually disable the process mode checker.
 * By default, it's automatically enabled in DEBUG build, and disabled in RELEASE build.
 * If it's enabled, MMKV will throw exceptions when an MMKV instance is created with mismatch process mode.
 */
static void disableProcessModeChecker();

/**
 * Check if this instance is in multi-process mode.
 * @return True if in multi-process mode, False otherwise
 */
boolean isMultiProcess();

/**
 * Check if this instance is in read-only mode.
 * @return True if in read-only mode, False otherwise
 */
boolean isReadOnly();

Usage Examples:

// Enable strict process mode checking for debugging
MMKV.enableProcessModeChecker();

// Create instances
MMKV singleKv = MMKV.mmkvWithID("single_data", MMKV.SINGLE_PROCESS_MODE);
MMKV multiKv = MMKV.mmkvWithID("multi_data", MMKV.MULTI_PROCESS_MODE);

// Verify process modes
Log.d("MMKV", "Single KV multi-process: " + singleKv.isMultiProcess()); // false
Log.d("MMKV", "Multi KV multi-process: " + multiKv.isMultiProcess());   // true

// This would throw an exception if process mode checker is enabled
// and "multi_data" was previously opened with SINGLE_PROCESS_MODE
try {
    MMKV conflictKv = MMKV.mmkvWithID("multi_data", MMKV.SINGLE_PROCESS_MODE);
} catch (IllegalArgumentException e) {
    Log.e("MMKV", "Process mode conflict: " + e.getMessage());
}

// Disable checking for production
MMKV.disableProcessModeChecker();

Anonymous Shared Memory for Inter-Process Communication

MMKV supports Anonymous Shared Memory (ashmem) for high-performance inter-process data sharing without disk persistence.

/**
 * Create an MMKV instance base on Anonymous Shared Memory, aka not synced to any disk files.
 * @param context The context of Android App, usually from Application
 * @param mmapID The unique ID of the MMKV instance
 * @param size The maximum size of the underlying Anonymous Shared Memory.
 *             Anonymous Shared Memory on Android can't grow dynamically, must set an appropriate size on creation
 * @param mode The process mode of the MMKV instance, defaults to SINGLE_PROCESS_MODE
 * @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes)
 * @throws RuntimeException if there's a runtime error
 */
static MMKV mmkvWithAshmemID(Context context, String mmapID, int size, int mode, String cryptKey);

/**
 * @return The file descriptor of the ashmem of the MMKV file
 */
int ashmemFD();

/**
 * @return The file descriptor of the ashmem of the MMKV crc file
 */
int ashmemMetaFD();

Usage Examples:

// Create ashmem instance for inter-process communication
MMKV ashmemKv = MMKV.mmkvWithAshmemID(
    this,
    "ipc_data",
    1024 * 1024,              // 1MB max size
    MMKV.MULTI_PROCESS_MODE,
    null                      // No encryption
);

// Use like regular MMKV instance
ashmemKv.encode("shared_message", "Hello from process A");
ashmemKv.encode("shared_timestamp", System.currentTimeMillis());

// Get file descriptors for passing to other processes
int dataFD = ashmemKv.ashmemFD();
int metaFD = ashmemKv.ashmemMetaFD();

// Pass these FDs to other processes via Binder/AIDL
// The receiving process can create MMKV instance from FDs

Multi-Process Best Practices

Guidelines and patterns for effective multi-process MMKV usage.

// Example multi-process architecture
public class SharedDataManager {
    private static final String SHARED_INSTANCE_ID = "app_shared_data";
    private final MMKV sharedKv;
    
    public SharedDataManager(Context context) {
        // Always use MULTI_PROCESS_MODE for shared data
        sharedKv = MMKV.mmkvWithID(SHARED_INSTANCE_ID, MMKV.MULTI_PROCESS_MODE);
        
        // Set up change notifications
        MMKV.registerContentChangeNotify(this::onContentChanged);
    }
    
    public void updateSharedConfig(String key, Object value) {
        sharedKv.lock();
        try {
            // Update with timestamp for conflict resolution
            sharedKv.encode(key + "_timestamp", System.currentTimeMillis());
            
            if (value instanceof String) {
                sharedKv.encode(key, (String) value);
            } else if (value instanceof Integer) {
                sharedKv.encode(key, (Integer) value);
            }
            // Handle other types...
            
        } finally {
            sharedKv.unlock();
        }
    }
    
    public <T> T getSharedConfig(String key, Class<T> type, T defaultValue) {
        // Check for updates from other processes
        sharedKv.checkContentChangedByOuterProcess();
        
        if (type == String.class) {
            return (T) sharedKv.decodeString(key, (String) defaultValue);
        } else if (type == Integer.class) {
            return (T) Integer.valueOf(sharedKv.decodeInt(key, (Integer) defaultValue));
        }
        // Handle other types...
        
        return defaultValue;
    }
    
    private void onContentChanged(String mmapID) {
        if (SHARED_INSTANCE_ID.equals(mmapID)) {
            // Notify UI components about data changes
            LocalBroadcastManager.getInstance(context)
                .sendBroadcast(new Intent("SHARED_DATA_CHANGED"));
        }
    }
}

Types

/**
 * Inter-process content change notification.
 * Triggered by any method call, such as getXXX() or setXXX() or checkContentChangedByOuterProcess().
 */
interface MMKVContentChangeNotification {
    /**
     * Inter-process content change notification.
     * Triggered by any method call, such as getXXX() or setXXX() or checkContentChangedByOuterProcess().
     * @param mmapID The unique ID of the changed MMKV instance
     */
    void onContentChangedByOuterProcess(String mmapID);
}

/**
 * A helper class for MMKV based on Anonymous Shared Memory.
 */
class ParcelableMMKV implements Parcelable {
    /**
     * Create from existing MMKV instance
     * @param mmkv The MMKV instance to wrap
     */
    ParcelableMMKV(MMKV mmkv);
    
    /**
     * Convert back to MMKV instance
     * @return MMKV instance, or null if invalid
     */
    MMKV toMMKV();
    
    // Parcelable implementation for passing between processes
    int describeContents();
    void writeToParcel(Parcel dest, int flags);
    static final Parcelable.Creator<ParcelableMMKV> CREATOR;
}

/**
 * A helper class for getting process information
 */
class MMKVContentProvider extends ContentProvider {
    /**
     * Get process name by process ID
     * @param context Application context
     * @param pid Process ID
     * @return Process name or empty string if not found
     */
    static String getProcessNameByPID(Context context, int pid);
    
    /**
     * Get content provider URI for ashmem operations
     * @param context Application context
     * @return Content provider URI, or null if not configured
     */
    static Uri contentUri(Context context);
}

Process Mode Constants

/**
 * Single-process mode. The default mode on an MMKV instance.
 */
static final int SINGLE_PROCESS_MODE = 1;

/**
 * Multi-process mode.
 * To enable multi-process accessing of an MMKV instance, you must set this mode whenever you getting that instance.
 */
static final int MULTI_PROCESS_MODE = 2;

/**
 * Read-only mode.
 */
static final int READ_ONLY_MODE = 32;

Performance Considerations

  • Single-process mode: Fastest performance, no locking overhead
  • Multi-process mode: Slight performance overhead due to file locking
  • Ashmem mode: Best for temporary data sharing between processes
  • Content change notifications: Minimal overhead, triggered only on manual checks
  • Process mode checker: Should be disabled in production builds for optimal performance

Install with Tessl CLI

npx tessl i tessl/maven-com-tencent--mmkv-static

docs

advanced-features.md

data-operations.md

index.md

initialization.md

instance-management.md

namespace.md

process-management.md

shared-preferences.md

utility-types.md

tile.json