AtomicDictionaryMBS – Thread-Safe Dictionaries for Xojo

Modern applications increasingly rely on multi-threading: background tasks, network processing, rendering pipelines, and data caching often run in parallel. In such environments, shared mutable data structures become a critical source of bugs if not properly synchronized.

With AtomicDictionaryMBS introduced in MBS Xojo Plugins 26.3, we provide a dedicated thread-safe dictionary designed specifically for safe concurrent access in Xojo applications.

Why not just use a Xojo Dictionary?

The standard Dictionary in Xojo is not thread-safe. This means:

  • Concurrent reads and writes can lead to crashes

  • Race conditions can overwrite data unexpectedly

  • Iteration while another thread modifies data can cause exceptions

  • Complex locking must be implemented manually using Mutexes

In practice, this often leads to subtle bugs that are difficult to reproduce, especially in production environments where thread timing differs from debugging scenarios.

Developers typically solve this by wrapping a Dictionary in a Mutex, but this approach is error-prone:

  • Locks may be forgotten for certain access paths

  • Deadlocks can occur if multiple locks are used

  • Fine-grained atomic operations are hard to implement correctly

What AtomicDictionaryMBS improves

AtomicDictionaryMBS encapsulates synchronization internally and provides atomic operations that eliminate common race conditions entirely.

Instead of manually locking around read-modify-write sequences, you use purpose-built methods that guarantee correctness.

Core advantages

1. Built-in thread safety

All operations on AtomicDictionaryMBS are internally synchronized, meaning multiple threads can safely access the same instance without external locks.

2. Atomic operations instead of manual locking

Rather than doing this (unsafe in threaded code):

Var v As Variant = dict.Value("counter")
dict.Value("counter") = v + 1

You do:

a.Increment("counter")

This removes the race condition between read and write.

Key methods and why they matter

CompareAndSet – lock-free style synchronization

Var ok As Boolean = a.CompareAndSet("state", "idle", "running")

This ensures the value is only updated if it still matches the expected state. It prevents:

  • lost updates

  • double processing

  • stale state overwrites

This pattern is widely used in concurrent programming and replaces fragile manual locking logic.

GetAndSet – atomic read-modify-write

Var newValue As Variant = 100
Var oldValue As Variant = a.GetAndSet("queueSize", newValue)

This ensures no other thread can modify the value between reading and updating it.

GetOrSet – safe lazy initialization

Var v As Variant = a.GetOrSet("config", defaultConfig)

This avoids duplicate initialization when multiple threads attempt to create the same entry.

Increment – safe counters without locks

a.Increment("hits")

A common problem in multithreaded apps is updating counters safely. This method guarantees correctness without requiring a mutex.

ExecuteLocked – grouped atomic operations

a.ExecuteLocked(AddressOf UpdateDic)

Sub UpdateDic(dic As AtomicDictionaryMBS)
  dic.Value("Hello") = dic.Value("Hello") + 1
End Sub

When multiple operations must be performed as a single atomic unit, this method ensures exclusive access for the duration of the delegate.

SetIfAbsent – safe initialization pattern

a.SetIfAbsent("session", sessionObject)

This ensures a value is only written if it does not already exist, preventing race conditions during initialization.

Iteration safety

The class provides an iterator for For Each loops:

For Each v As Variant In a.Iterator
  // safe iteration snapshot behavior
Next

This avoids common crashes that occur when a Dictionary is modified during enumeration.

How AtomicDictionaryMBS differs from manual Mutex usage

Aspect Mutex + Dictionary AtomicDictionaryMBS
Thread safety Manual, error-prone Built-in
Atomic operations Must be implemented manually Built-in (CompareAndSet, Increment, etc.)
Race conditions Easy to introduce Eliminated for API operations
Code complexity High Low
Deadlock risk Possible Greatly reduced

Typical use cases

We can use the dictionary for various use cases in our Xojo projects:

  • Shared caches across worker threads

  • Game state synchronization (physics, AI, rendering)

  • Network session and token management

  • Producer/consumer pipelines

  • Event subscription systems

When NOT to use it

A standard Dictionary is still appropriate when:

  • Only one thread accesses the data

  • All access is already protected externally

  • Data is immutable after creation

Using AtomicDictionaryMBS in single-threaded scenarios is safe, but may introduce unnecessary overhead.

Availability

AtomicDictionaryMBS is available in MBS Xojo Plugins 26.3 and newer.

Summary

AtomicDictionaryMBS provides a modern, safe abstraction over shared key-value storage in multi-threaded Xojo applications. It removes the need for manual locking in most cases and replaces fragile concurrency patterns with clear, atomic operations.

The result is simpler code, fewer race conditions, and more reliable applications under real-world concurrent load.

3 Likes