Page:
Threads
No results
1
Threads
dxtr edited this page 2026-10-14 04:36:31 +02:00
Table of Contents
Threads
An atlas, its pages and its regions may be used from any number of threads at once.
- One lock guards an atlas's pages and its cache. Adding an image, looking a key up, taking a page's changes and copying a page's texels each hold it for as long as they take.
- Regions never change, so they may be kept and shared freely.
- Images are made outside the lock. The function
atlas-find-or-addcalls to make a missing image runs without the lock, so threads can make images at the same time, such as the workers of a job pool rasterizing glyphs. Only packing the finished image takes the lock. - A key may be made twice. If two threads ask for the same new key at once, both run their function; the first image packed is kept, and the second thread gets the same region, its own image dropped. Make the function free of other side effects.
- Uploading while others pack.
copy-page-regionreads under the lock, so it never sees half an image. Take a page's changes before copying, as Uploading Pages does, and an image packed in between is in the copy or in the next changes.
Making images on a job pool
With cl-threads, the workers of a pool pack images into one atlas:
(asdf:load-system :cl-threads)
(defpackage #:example
(:use #:cl)
(:local-nicknames (#:atlas #:cl-atlas)
(#:th #:cl-threads)))
(in-package #:example)
(defun square (size &optional (value 255))
"Return an image of SIZE by SIZE texels of one byte, each VALUE."
(make-array (list size size) :element-type '(unsigned-byte 8) :initial-element value))
(th:with-job-pool (pool)
(let ((atlas (atlas:make-atlas :page-size 256)))
;; A thousand requests for squares of 1 to 32 texels: each size is
;; packed once, however many workers ask for it.
(th:parallel-for pool 0 1000
(lambda (start end)
(loop for request from start below end
do (let ((size (1+ (mod request 32))))
(atlas:atlas-find-or-add atlas size
(lambda () (square size)))))))
(list (atlas:atlas-page-count atlas)
(loop for size from 1 to 32 count (atlas:atlas-find atlas size)))))
;; => (1 32)
Where the squares go on the page depends on which worker packs first, so it differs from run to run; which squares are there does not.