From ada448040f04bb4c8fae82fe839807ba45a85d61 Mon Sep 17 00:00:00 2001 From: "chudy@google.com" Date: Mon, 30 Jul 2012 12:59:12 +0000 Subject: [PATCH] Deserialization locks up multithreading fix. Review URL: https://codereview.appspot.com/6448077 git-svn-id: http://skia.googlecode.com/svn/trunk@4824 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/ports/SkFontHost_linux.cpp | 89 ++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/src/ports/SkFontHost_linux.cpp b/src/ports/SkFontHost_linux.cpp index 4ae15c7..120d30e 100644 --- a/src/ports/SkFontHost_linux.cpp +++ b/src/ports/SkFontHost_linux.cpp @@ -43,7 +43,7 @@ struct FamilyRec; struct NameFamilyPair { const char* fName; // we own this FamilyRec* fFamily; // we don't own this, we just reference it - + void construct(const char name[], FamilyRec* family) { fName = strdup(name); @@ -67,7 +67,7 @@ static SkTDArray gNameList; struct FamilyRec { FamilyRec* fNext; SkTypeface* fFaces[4]; - + FamilyRec() { fNext = gFamilyHead; @@ -79,7 +79,7 @@ struct FamilyRec { static SkTypeface* find_best_face(const FamilyRec* family, SkTypeface::Style style) { SkTypeface* const* faces = family->fFaces; - + if (faces[style] != NULL) { // exact match return faces[style]; } @@ -137,7 +137,7 @@ static FamilyRec* remove_from_family(const SkTypeface* face) { FamilyRec* family = find_family(face); SkASSERT(family->fFaces[face->style()] == face); family->fFaces[face->style()] = NULL; - + for (int i = 0; i < 4; i++) { if (family->fFaces[i] != NULL) { // family is non-empty return NULL; @@ -150,7 +150,7 @@ static FamilyRec* remove_from_family(const SkTypeface* face) { static void detach_and_delete_family(FamilyRec* family) { FamilyRec* curr = gFamilyHead; FamilyRec* prev = NULL; - + while (curr != NULL) { FamilyRec* next = curr->fNext; if (curr == family) { @@ -179,7 +179,7 @@ static const char* find_family_name(const SkTypeface* familyMember) { } static FamilyRec* find_familyrec(const char name[]) { - const NameFamilyPair* list = gNameList.begin(); + const NameFamilyPair* list = gNameList.begin(); int index = SkStrLCSearch(&list[0].fName, gNameList.count(), name, sizeof(list[0])); return index >= 0 ? list[index].fFamily : NULL; @@ -199,12 +199,12 @@ static SkTypeface* find_typeface(const SkTypeface* familyMember, static void add_name(const char name[], FamilyRec* family) { SkAutoAsciiToLC tolc(name); name = tolc.lc(); - + NameFamilyPair* list = gNameList.begin(); int count = gNameList.count(); - + int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); - + if (index < 0) { list = gNameList.insert(~index); list->construct(name, family); @@ -217,9 +217,9 @@ static void remove_from_names(FamilyRec* emptyFamily) { SkASSERT(emptyFamily->fFaces[i] == NULL); } #endif - + SkTDArray& list = gNameList; - + // must go backwards when removing for (int i = list.count() - 1; i >= 0; --i) { NameFamilyPair* pair = &list[i]; @@ -237,19 +237,19 @@ public: FamilyTypeface(Style style, bool sysFont, FamilyRec* family, bool isFixedWidth) : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) { fIsSysFont = sysFont; - + SkAutoMutexAcquire ac(gFamilyMutex); - + if (NULL == family) { family = SkNEW(FamilyRec); } family->fFaces[style] = this; fFamilyRec = family; // just record it so we can return it if asked } - + virtual ~FamilyTypeface() { SkAutoMutexAcquire ac(gFamilyMutex); - + // remove us from our family. If the family is now empty, we return // that and then remove that family from the name list FamilyRec* family = remove_from_family(this); @@ -258,17 +258,17 @@ public: detach_and_delete_family(family); } } - + bool isSysFont() const { return fIsSysFont; } FamilyRec* getFamily() const { return fFamilyRec; } // openStream returns a SkStream that has been ref-ed virtual SkStream* openStream() = 0; virtual const char* getUniqueString() const = 0; - + private: FamilyRec* fFamilyRec; // we don't own this, just point to it bool fIsSysFont; - + typedef SkTypeface INHERITED; }; @@ -281,11 +281,11 @@ private: class EmptyTypeface : public FamilyTypeface { public: EmptyTypeface() : INHERITED(SkTypeface::kNormal, true, NULL, false) {} - + // overrides virtual SkStream* openStream() { return NULL; } virtual const char* getUniqueString() const { return NULL; } - + private: typedef FamilyTypeface INHERITED; }; @@ -301,19 +301,19 @@ public: virtual ~StreamTypeface() { fStream->unref(); } - + // overrides - virtual SkStream* openStream() - { + virtual SkStream* openStream() + { // openStream returns a refed stream. fStream->ref(); return fStream; } virtual const char* getUniqueString() const { return NULL; } - + private: SkStream* fStream; - + typedef FamilyTypeface INHERITED; }; @@ -324,12 +324,12 @@ public: : INHERITED(style, sysFont, family, isFixedWidth) { fPath.set(path); } - + // overrides virtual SkStream* openStream() { SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str())); - + // check for failure if (stream->getLength() <= 0) { SkDELETE(stream); @@ -350,10 +350,10 @@ public: } return str; } - + private: SkString fPath; - + typedef FamilyTypeface INHERITED; }; @@ -361,7 +361,7 @@ private: /////////////////////////////////////////////////////////////////////////////// static bool get_name_and_style(const char path[], SkString* name, - SkTypeface::Style* style, bool* isFixedWidth) { + SkTypeface::Style* style, bool* isFixedWidth) { SkMMAPStream stream(path); if (stream.getLength() > 0) { return find_name_and_attributes(&stream, name, style, isFixedWidth); @@ -372,7 +372,7 @@ static bool get_name_and_style(const char path[], SkString* name, return find_name_and_attributes(&stream, name, style, isFixedWidth); } } - + SkDebugf("---- failed to open <%s> as a font\n", path); return false; } @@ -400,14 +400,14 @@ static void load_system_fonts() { bool isFixedWidth; SkString realname; SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized warning - + if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedWidth)) { SkDebugf("------ can't load <%s> as a font\n", filename.c_str()); continue; } // SkDebugf("font: <%s> %d <%s>\n", realname.c_str(), style, filename.c_str()); - + FamilyRec* family = find_familyrec(realname.c_str()); if (family && family->fFaces[style]) { // SkDebugf("---- skipping duplicate typeface %s style %d\n", @@ -461,7 +461,7 @@ static void load_system_fonts() { if (NULL == gDefaultNormal) { sk_throw(); } - gFallBackTypeface = gDefaultNormal; + gFallBackTypeface = gDefaultNormal; gDefaultFamily = find_family(gDefaultNormal); // SkDebugf("---- default %p head %p family %p\n", gDefaultNormal, gFamilyHead, gDefaultFamily); @@ -494,10 +494,7 @@ void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { } SkTypeface* SkFontHost::Deserialize(SkStream* stream) { - { - SkAutoMutexAcquire ac(gFamilyMutex); - load_system_fonts(); - } + load_system_fonts(); SkFontDescriptor descriptor(stream); const char* familyName = descriptor.getFamilyName(); @@ -526,33 +523,33 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, const char familyName[], SkTypeface::Style style) { load_system_fonts(); - + SkAutoMutexAcquire ac(gFamilyMutex); - + // clip to legal style bits style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); - + SkTypeface* tf = NULL; - + if (NULL != familyFace) { tf = find_typeface(familyFace, style); } else if (NULL != familyName) { // SkDebugf("======= familyName <%s>\n", familyName); tf = find_typeface(familyName, style); } - + if (NULL == tf) { tf = find_best_face(gDefaultFamily, style); } - - SkSafeRef(tf); + + SkSafeRef(tf); return tf; } SkStream* SkFontHost::OpenStream(uint32_t fontID) { FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID); SkStream* stream = tf ? tf->openStream() : NULL; - + if (stream && stream->getLength() == 0) { stream->unref(); stream = NULL; -- 2.7.4