[SDL] What are threads allowed to do?

Albert Cahalan albert at users.sf.net
Mon Jan 24 13:46:57 PST 2005


On Mon, 2005-01-24 at 12:40 -0500, Albert Cahalan wrote:
> On Mon, 2005-01-24 at 09:03 -0600, Bob Pendleton wrote:

> > What does that mean to an SDL programmer? It means that you can have 10
> > threads reading 10 files, but only one thread can be decoding a ttf font
> > at a time.
> 
> This is awful. I looked over libSDL_ttf and didn't find anything
> significant. What did I miss? I saw:
> 
> a. error text might get corrupted (but no crash)
> b. can't do simultaneous TTF_Init() calls (no problem)
> 
> Regarding #a, note that libSDL_ttf does not pass '%'
> in error strings. So the unsafe vararg stuff in SDL's
> error handling would not be involved.

Found it!

FreeType keeps a buffer around to fast scan line conversion.
This buffer is not static within FreeType, so FreeType itself
is thread-safe. The buffer must be in the FT_Library struct or
hanging off it. The libSDL_ttf code shares this struct with
all fonts that it opens.

I'm including a patch (not tested) that should improve the
situation greatly. Please apply it. Please also be sure to
fully document the remaining problems. I think they are:

a. SDL error messages might get messed up
b. the byteswap setting is obviously global
c. each thread will need a private TTF_Font

(in the man pages, the wiki pages, the info pages...)

BTW, the wide character handling is kind of broken anyway.
Full Unicode version 2.x requires 32-bit characters.
The early-adopter systems using 16-bit have had to switch
to the nasty UTF-16 encoding. Perhaps all the 16-bit stuff
should just be removed. The gcc compiler provides some help;
you can put __attribute__((deprecated)) in a header file to
warn users about the obsolete interface.

Anyway, here's the patch:

////////////////////////////////////////////////////////////////////////
diff -Naurd old/SDL_ttf.c new/SDL_ttf.c
--- old/SDL_ttf.c	2005-01-24 16:11:26.000000000 -0500
+++ new/SDL_ttf.c	2005-01-24 16:28:21.000000000 -0500
@@ -90,6 +90,7 @@
 struct _TTF_Font {
 	/* Freetype2 maintains all sorts of useful info itself */
 	FT_Face face;
+	FT_Library library;
 
 	/* We'll cache these ourselves */
 	int height;
@@ -122,10 +123,7 @@
 	int font_size_family;
 };
 
-/* The FreeType font engine/library */
-static FT_Library library;
-static int TTF_initialized = 0;
-static int TTF_byteswapped = 0;
+static int TTF_byteswapped;
 
 /* UNICODE string utilities */
 static __inline__ int UNICODE_strlen(const Uint16 *text)
@@ -205,21 +203,10 @@
 #endif /* USE_FREETYPE_ERRORS */
 }
 
+/* this exists only to maintain the ABI */
 int TTF_Init( void )
 {
-	int status = 0;
-
-	if ( ! TTF_initialized ) {
-		FT_Error error = FT_Init_FreeType( &library );
-		if ( error ) {
-			TTF_SetFTError("Couldn't init FreeType engine", error);
-			status = -1;
-		}
-	}
-	if ( status == 0 ) {
-		++TTF_initialized;
-	}
-	return status;
+	return 0;
 }
 
 static unsigned long RWread(
@@ -245,11 +232,6 @@
 	FT_Stream stream;
 	int position;
 
-	if ( ! TTF_initialized ) {
-		TTF_SetError( "Library not initialized" );
-		return NULL;
-	}
-
 	/* Check to make sure we can seek in this stream */
 	position = SDL_RWtell(src);
 	if ( position < 0 ) {
@@ -267,6 +249,13 @@
 	font->src = src;
 	font->freesrc = freesrc;
 
+	FT_Error error = FT_Init_FreeType( &font->library );
+	if ( error ) {
+		TTF_SetFTError("Couldn't init FreeType engine", error);
+		free( font );
+		return NULL;
+	}
+
 	stream = (FT_Stream)malloc(sizeof(*stream));
 	if ( stream == NULL ) {
 		TTF_SetError( "Out of memory" );
@@ -275,7 +264,7 @@
 	}
 	memset(stream, 0, sizeof(*stream));
 
-	stream->memory = library->memory;
+	stream->memory = font->library->memory;
 	stream->read = RWread;
 	stream->descriptor.pointer = src;
 	stream->pos = (unsigned long)position;
@@ -286,7 +275,7 @@
 	font->args.flags = FT_OPEN_STREAM;
 	font->args.stream = stream;
 
-	error = FT_Open_Face( library, &font->args, index, &font->face );
+	error = FT_Open_Face( font->library, &font->args, index, &font->face );
 	if( error ) {
 		TTF_SetFTError( "Couldn't load font file", error );
 		TTF_CloseFont( font );
@@ -668,6 +657,7 @@
 	if ( font->freesrc ) {
 		SDL_RWclose( font->src );
 	}
+	FT_Done_FreeType( font->library );
 	free( font );
 }
 
@@ -849,10 +839,6 @@
 	FT_UInt prev_index = 0;
 
 	/* Initialize everything to 0 */
-	if ( ! TTF_initialized ) {
-		TTF_SetError( "Library not initialized" );
-		return -1;
-	}
 	status = 0;
 	minx = maxx = 0;
 	miny = maxy = 0;
@@ -1735,14 +1721,10 @@
 
 void TTF_Quit( void )
 {
-	if ( TTF_initialized ) {
-		if ( --TTF_initialized == 0 ) {
-			FT_Done_FreeType( library );
-		}
-	}
+	return;
 }
 
 int TTF_WasInit( void )
 {
-	return TTF_initialized;
+	return 1;  // this is a don't-care value to satisfy the ABI
 }

////////////////////////////////////////////////////////////////////////






More information about the SDL mailing list