freetype
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [ft] Clarification about FT_Init_FreeType in a multithreaded environ


From: Werner LEMBERG
Subject: Re: [ft] Clarification about FT_Init_FreeType in a multithreaded environment
Date: Tue, 11 Jun 2013 16:33:19 +0200 (CEST)

Hello Ulrich!


> The documentation for FT_Init_FreeType says "For multi-threading
> applications each thread should have its own FT_Library object." and
> I'm wondering how to understand this sentence.  Is this meant as
> "don't access FT_Library objects concurrently from different
> threads" or does every thread have to create its own library
> instance and I can't move objects between threads?  I assume the
> former, but I'd like to clarify that first.

Actually, it's the latter.  Calls to FreeType are only thread-safe if
you have one FT_Library object per thread.

> When rendering text, I would
> 1. Lock the library mutex.
> 2. If the faces is not cached, load it now and store it in the cache.
> 3. Then, lock the face mutex and release the library mutex.
> 4. Load the glyphs and render their outlines.
> 5. Release the face mutex.

I must admit that I'm bad at multi-threading, but I think this doesn't
work in general.  For example, here's a comment from one of the
auto-hinter's (internal) header files, `afloader.h', describing the
AF_ModuleRec structure:

  The autofitter module's (global) data structure to communicate with
  actual fonts.  If necessary, `local' data like the current face, the
  current face's auto-hint data, or the current glyph's parameters
  relevant to auto-hinting are `swapped in'.  Cf. functions like
  `af_loader_reset' and `af_loader_load_g'.

In other words, functions related to FT_Face (temporarily) manipulate
data in the various FreeType font driver, hinting, and renderer
modules, and those modules are contained in FT_Library.

However, I *think* that the auto-hinter is the only module which does
this.  If you don't need it, your approach might work.

> My question in that context is whether the two-level approach to
> locking works, i.e. if I can call FT_Load_Char() and
> FT_Outline_Decompose() on the face while some other thread calls
> FT_New_Face() on the library.

Only with the abovementioned restrictions, I believe.

> If not, could I get the above level of separation if I had one
> library instance per face?  What is the overhead of creating a
> library instance?

This is a nice idea.  By default, the FT_LibraryRec object has a size
of 212 bytes (on my i386 machine), containing an array for 32
FT_Module pointers (which is 128 bytes).  If you know in advance which
font types you have, this can be greatly reduced, cf. FT_MAX_MODULES.
It also contains a dynamically allocated array called `raster_pool',
used by the rasterizers, with a size of FT_RENDER_POOL_SIZE.  This
array gets created by a call to `FT_New_Library'.  Since you don't
want rasterization, you can set this to a very small value, or even
zero.  In summary, I think you can reduce the overhead to less than
200 bytes per FT_Library object.

> BTW: It would have helped me understand the FreeType API if every
> resource-acquiring function had their release counterpart
> documented.  This is already done for
> FT_New_Memory_Face()/FT_Open_Face() and FT_Done_Face(), but what
> about FT_New_Face()?

It is documented as a wrapper for `FT_Open_Face', so it pairs with
`FT_Done_Face' too.  I've always thought that this is obvious, but
apparently it isn't, so I've added a line to the documentation to
explain this.

> Also, what is still not completely clear to me is when I can use
> FT_Done_FreeType().  For the faces, it seems that they are
> reference-counted, but what about the library itself?  Will an early
> call pull the library from under my feet?

Ah, this is indeed missing in the docs.  While `FT_Done_FreeType'
simply calls `FT_Done_Library', which *is* reference-counted, it also
calls `FT_Done_Memory', which is not.

So a program with multiple threads should use `FT_New_Library' and
`FT_Done_Library' (instead of `FT_Init_FreeType' and
`FT_Done_FreeType'), providing its own FT_Memory object.


    Werner



reply via email to

[Prev in Thread] Current Thread [Next in Thread]