With the release of version 25.2 of the MBS Xojo Plugins, we’re excited to introduce the new AtomicQueueMBS class—a powerful tool for managing thread-safe job queues in your Xojo applications.
Whether you’re building a multithreaded server, a background processing system, or any app where tasks need to be scheduled and executed safely across threads, AtomicQueueMBS gives you a robust, atomic queue implementation that works across macOS, Windows, Linux, and iOS.
What is an atomic queue?
AtomicQueueMBS is a generic queue class designed for atomic operations, ensuring thread safety when adding or removing items. It acts as a flexible container for your jobs or data, supporting both FIFO (First-In-First-Out) and LIFO (Last-In-First-Out) behavior.
Example:
Var queue As New AtomicQueueMBS // Add jobs to the queue queue.Push(New MyJob) queue.Push(New MyJob) // Process jobs in another thread Do Var job As MyJob = queue.PopLast // or queue.PopFirst job.Process Loop Until queue.Count = 0
Core Features
- Fully thread-safe
- Compatible with all platforms supported by Xojo
- Works with any type stored as a
Variant
- Simple and intuitive API
Key Properties
- Count (Read-only) Returns the number of items in the queue.
- TopValue (Read/Write) Retrieves or sets the value at the top of the queue without removing it.
Powerful Methods
- Push(value as Variant) Adds a value to the end of the queue.
- PopFirst / PopLast Removes and returns the first or last item, supporting FIFO or LIFO patterns.
- Add(values as AtomicQueueMBS) Merges another queue into the current one.
- Add(values() as Variant) Pushes multiple values at once.
- Insert(value as Variant) Inserts a value at the front of the queue.
- Clear() Empties the entire queue.
- Values() as Variant() Returns all values in the queue as an array.
- Operator_Convert Allows seamless conversion to a
Variant()
array:
Var values() As Variant = queue
- Operator_Add Enables this elegant syntax:
queue = queue + 123
- Operator_Compare Compares two queues for equality.
Use Case: A Multi-Threaded Job Queue
A common use case for AtomicQueueMBSis distributing jobs between multiple threads. For example, one thread can enqueue tasks while several worker threads pop them off concurrently, all without needing to manually handle synchronization.
// Declare the job class
Class MyJob
Public JobID As Integer
Sub Constructor(id As Integer)
JobID = id
End Sub
Public Sub Process()
// Simulate processing time with a simple delay
System.Sleep(1000)
System.DebugLog("Processing Job ID: " + JobID.ToString)
End Sub
End Class
// Declare the main procedure
Sub Main()
Var queue As New AtomicQueueMBS
// Main thread pushing jobs into the queue
For i As Integer = 1 To 5
queue.Push New MyJob(i)
System.DebugLog("Pushed Job ID: " + i.ToString)
Next
// store the queue globally
app.queue = queue
// Now, simulate worker threads processing jobs
For i As Integer = 1 To 3
// Create and start a worker thread to process jobs
Var worker As New Thread
worker.RunAddress = AddressOf WorkerThread
worker.Identifier = i // Assign worker ID
worker.Start
Next
End Sub
// Worker thread procedure
Sub WorkerThread(t As Thread)
Var queue As AtomicQueueMBS = app.queue ' Receive the queue
// Simulate worker processing jobs from the queue
Do
If queue.Count > 0 Then
Var job As MyJob = queue.PopFirst // Pop first job in FIFO order
if job = nil then
// someone else was quicker
Else
job.Process()
End If
Else
System.DebugLog("No jobs to process. Worker " + t.Identifier.ToString + " is idle.")
Exit Do
End If
Loop
End Sub
How This Works:
- Main Thread: The main thread creates an AtomicQueueMBS object and pushes five
MyJob
objects onto the queue. These jobs could represent anything you want to process, like tasks, files, or data. - Worker Threads: Three worker threads are created. Each worker will pull jobs off the queue and process them one by one. The
PopFirst
method ensures that the jobs are processed in FIFO order (First-In-First-Out). - Processing: The
MyJob
class simulates a job with anID
and aProcess
method that usesSystem.Sleep
to mimic a time-consuming task. Once a job is processed, the worker outputs the job ID in the debug log. - Atomic Operations: The AtomicQueueMBSensures thread safety, meaning multiple threads can safely access and modify the queue without conflicts.
Notes:
- Each worker thread pulls from the same queue, so the tasks are shared across threads.
- The queue operates atomically, meaning it handles the synchronization internally, so you don’t have to worry about race conditions.
You can modify the WorkerThread
to do more complex work depending on your needs, but this demo should provide a basic framework to get started with job queues in a multithreaded environment.
Would you like me to explain any part of the code or further enhance the demo?
Conclusion
The AtomicQueueMBS class simplifies concurrent programming in Xojo by providing a reliable, atomic queue structure. It’s a great addition for developers looking to build high-performance, thread-safe applications across platforms.
This feature is now available in MBS Xojo Plugin 25.2. Try it out today and make your threading logic cleaner, faster, and safer.
Have questions or need examples? Let us know in the comments or reach out directly!