Re: thread-safe access to font metrics

Jonathan Kew <[email protected]> Wed, 14 Dec 2016 14:01:47 +0000
Newsgroups gmane.comp.mozilla.devel.layout
Message-ID <[email protected]>
Hi Bobby,

On 13/12/2016 17:34, Bobby Holley wrote:
> Hi Jonathan,
>
> For Stylo to compute values for 'ex' and 'ch' units, it needs access to
> font metrics from the parallel worker threads. I've heard that font
> metrics are generally not thread-safe in Gecko, so I'm trying to figure
> out next steps, and have a few questions:
>
> (1) How not-thread-safe is the font metric stuff? If we just need
> trivial stuff like the things mentioned above, will we still run into
> problems?

In principle, the answer may differ between font back-ends, as we 
ultimately rely on platform APIs to access fonts. But I think the answer 
is that font metric stuff -can- be made thread-safe without too much 
difficulty.

My understanding is that both Core Text & Core Graphics on macOS and 
DirectWrite & GDI on Windows can safely be used to read font metrics 
from multiple threads.

Note, however, that the FreeType docs say that "[a]n ‘FT_Face’ object 
can only be safely used from one thread at a time", so multiple 
concurrent workers all asking for metrics may be problematic on Linux 
and Android.

The current Gecko code in gfx/thebes that deals with metrics is -not- 
thread-safe, however, as it includes a bunch of caching that looks like 
it'd be unsafe (e.g. gfxGlyphExtents includes an nsTHashtable where it 
stores extents, and this would get very confused if two threads 
simultaneously tried to update it). We could presumably go through that 
code and make it thread-safe (for some cost), if that would be an 
overall win.

(Actually, you're probably less interested in gfxGlyphExtents at this 
stage; that would be relevant to textRun construction rather than style 
processing. But initializing the metrics of an individual gfxFont object 
is also not thread-safe, AFAICS.)

>
> (2) Assuming that the information we need does indeed require
> non-threadsafe calls, can you tell us whether those calls are strictly
> main-thread-only, or whether it's enough to simply avoid concurrency? We
> block the main thread during style traversal, so we could stick a mutex
> around the font metrics stuff and only acquire that mutex during
> parallel traversal (leaving main-thread callpaths untouched). We could
> then also cache the metrics we need in TLS to further-reduce the
> synchronization cost.

I'm not aware of any main-thread-only calls involved here; I believe 
you'll be fine getting metrics on a worker thread. The two issues we'll 
need to be careful of are the currently non-thread-safe caching in 
gfxFont etc., and the FreeType restriction on concurrent use of an 
FT_Face. If we make the gfxFont caching thread-safe, then AFAIK you 
could have multiple concurrent threads getting font metrics on both 
macOS and Windows.


Besides getting metrics, I suspect you're also going to be interested in 
querying the list of available fonts (so that you can find the best 
matching face for a given family/weight/stretch/style/etc combination). 
That will also need to be looked at, because the current Gecko font-list 
code loads the faces within each family lazily (and modification of the 
gfxFontFamily to add faces isn't thread-safe).

So really, this comes before the question about font metrics: you can't 
get font metrics until you know which font you're dealing with, so you 
need to resolve the font-* properties to a specific face, and currently 
you can't safely do that concurrently from multiple threads. (AFAIK it 
should be OK to do it from a single worker thread if the main thread is 
blocked.)

HTH,

JK

_______________________________________________
dev-tech-layout mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-layout