An utility that was added to the DWScript sample WebServer during the 4 TeraPixel Mandelbrot [1] experiment is the BackgroundWorkers API.
This is a rather low-level threading facility that can work well with Global Queues [2] to handle background tasks or serializing tasks.
BackgroundWorkers static class
It’s found in the dwsBackgroundWorkersLibModule module, which exposes a System.Workers unit to the script. It has only 4 methods:
- CreateWorkQueue( name ) : create a work queue of the given name
- DestroyWorkQueue( name ) : destroys the work queue of given name, aborting all queued work
- QueueWork( name, task, data ) : queues a work unit
- QueueSize( name ) : queries the number of work units for a given queue (size of the queue)
Each queue will process its work units sequentially, you can have as many queues as you want (or rather as memory and OS allows, but that’s a lot). The queues exist outside of the script contexts, and are shared by all scripts running in the same executable.
Under the hood queue rely on IOCP [3] and are thus quite cheap both in terms of memory and overhead.
Usage
The dwsBackgroundWorkersLibModule offers an OnBackgroundWork event which you’re supposed to tie to whatever code you’ll use to process the queued work units.
In the context of the DWS sample WebServer, tasks are programs (scripts) that will be executed as if they had been invoked by an http request (ie. their WebRequest.ContentData will hold the data you passed)
Typically, you’ll start by creating your work queues in the startup script (the “.startup.pas” file default), then proceed to give them work. From that point on:
- asynchronous workers: other requests will either immediately queue work, or accumulate in a global queue, and then create a work unit
- background (polling) task: these will usually queue themselves, perform some work, sleep & terminate (note that the sleep() function in DWS is interruptible), rinse and repeat
You’re thus free to use the BackgroundWorkers as a basic MultiThreading API, to spread work over multiple threads, or as a serialization API, to ensure a strictly sequential execution.