Xbase++ V3 supports multithreading in two distinct runtime modes: single-processor mode and multi-processor mode. The mode is selected at link time depending on the application type. This article describes the technical characteristics of each mode, when each applies, and what developers need to account for.


Single-Processor Mode (Multithreaded/Single-Processor)​

In single-processor mode, the application runs multiple threads, but only one thread executes at any given moment. The operating system schedules threads, but they never run in parallel across CPU cores.

Characteristics:
  • Multiple threads exist concurrently but execute serially
  • Execution is deterministic and predictable
  • Traditional synchronization primitives are sufficient for thread coordination
  • Simpler to reason about and easier to debug
Typical use cases: Desktop applications, interactive GUI applications, scenarios where background threads handle processing while the main thread manages UI events.


Multi-Processor Mode (Multithreaded/Multi-Processor)​

In multi-processor mode, multiple threads execute simultaneously on separate CPU cores. This enables true parallel execution and higher CPU utilization.

Characteristics:
  • Threads run concurrently on different cores
  • Execution order is non-deterministic
  • Requires careful synchronization for any shared state
  • Suitable for high-throughput workloads
Typical use cases: Server applications, microservices, parallel data processing pipelines, TCP connection handlers.

Example — parallel data processing across all logical CPU cores:
Xbase++:
aWorkers := {}
FOR i := 1 TO GetLogicalProcessorCount()
    oWorker := Thread():New()
    oWorker:Start({ |nId| ProcessDataChunk(nId, aDataSet) }, i)
    aadd(aWorkers, oWorker)
NEXT
ThreadWaitAll(aWorkers)

Each worker thread processes a separate chunk of aDataSet simultaneously. The total execution time approaches 1 / N of single-threaded time where N is the number of cores, provided there is no contention on shared resources.

Example — microservice handling concurrent HTTP requests:
Xbase++:
CLASS TodoEditHandler FROM RestHandler
  EXPORTED:
  CLASS METHOD onRegister()

  METHOD getTodoItemById()
ENDCLASS


CLASS METHOD TodoEditHandler:onRegister(oEP)
  ::addType( "id", "N" )
  oEP:map( "GET",    "/todoitems/::id", "/TodoEditHandler/getTodoItemById" )
RETURN SELF


METHOD TodoEditHandler:getTodoItemById(nId)
   LOCAL oTodoItem
   LOCAL oResult
   LOCAL oTDM

   IF nId == 0
     oTDM  := TodoDataManager():open()
     oTodoItem := oTDM:getDefault()
     oTDM:close()
   ELSE
     oTodoItem := ::fetchTodoItemById(nId)
     IF IsNull(oTodoItem)
       ::setError(404, "Requested todo item not found")
       RETURN
     ENDIF
   ENDIF
RETURN oTodoItem

The MSA framework dispatches each incoming request to a separate thread. Multiple instances of TodoEditHandler() can execute simultaneously on different cores.

Mode Comparison​

AspectSingle-ProcessorMulti-Processor
ExecutionOne thread at a timeMultiple threads simultaneously
CPU utilizationOne coreAll available cores
Execution orderDeterministicNon-deterministic
Synchronization complexityLowHigher
Typical application typeDesktop / interactiveServer / parallel processing
ScalabilityLimited by single coreScales with core count

Debugging Considerations​

Single-processor mode is considerably easier to debug because execution is serialized. A breakpoint in one thread pauses all observable execution, and thread interleaving is not a factor.

In multi-processor mode, bugs may be timing-dependent and not reproducible on every run. Race conditions, deadlocks, and stale reads of shared state become possible. Adequate synchronization must be in place before enabling or targeting multi-processor mode.

Historical Context​

Multi-core CPUs have been available since 2005, but for many years the overhead of synchronizing shared state outweighed the parallelism benefit for line-of-business applications. Hardware and operating system improvements in the 2020s — particularly advances in cache coherency and OS scheduler efficiency — reduced this overhead to a level where multi-processor mode delivers measurable gains for typical LOB workloads.