Author: zooey Date: 2011-02-16 16:27:33 +0100 (Wed, 16 Feb 2011) New Revision: 40529 Changeset: http://dev.haiku-os.org/changeset/40529 Ticket: http://dev.haiku-os.org/ticket/7227 Modified: haiku/trunk/headers/private/locale/MutableLocaleRoster.h haiku/trunk/src/kits/locale/MutableLocaleRoster.cpp Log: * improve locale roster to no longer rely on static object initialization order This was meant to fix #7227, but just seems to have bypassed it - the crash is now somewhere else ... needs more investigation Modified: haiku/trunk/headers/private/locale/MutableLocaleRoster.h =================================================================== --- haiku/trunk/headers/private/locale/MutableLocaleRoster.h 2011-02-16 15:24:22 UTC (rev 40528) +++ haiku/trunk/headers/private/locale/MutableLocaleRoster.h 2011-02-16 15:27:33 UTC (rev 40529) @@ -114,15 +114,16 @@ bool fAreResourcesLoaded; BResources fResources; - RosterData(); + status_t fInitStatus; + RosterData(const BLanguage& language, const BFormattingConventions& conventions); ~RosterData(); static RosterData* Default(); - void InitializeCatalogAddOns(); - void CleanupCatalogAddOns(); + status_t InitCheck() const; + status_t Refresh(); static int CompareInfos(const void* left, @@ -133,6 +134,11 @@ status_t SetDefaultTimeZone(const BTimeZone& zone); status_t SetPreferredLanguages(const BMessage* msg); private: + status_t _Initialize(); + + status_t _InitializeCatalogAddOns(); + void _CleanupCatalogAddOns(); + status_t _LoadLocaleSettings(); status_t _SaveLocaleSettings(); Modified: haiku/trunk/src/kits/locale/MutableLocaleRoster.cpp =================================================================== --- haiku/trunk/src/kits/locale/MutableLocaleRoster.cpp 2011-02-16 15:24:22 UTC (rev 40528) +++ haiku/trunk/src/kits/locale/MutableLocaleRoster.cpp 2011-02-16 15:27:33 UTC (rev 40529) @@ -12,6 +12,7 @@ #include <set> +#include <pthread.h> #include <syslog.h> #include <AppFileInfo.h> @@ -126,6 +127,9 @@ // #pragma mark - RosterData +namespace { + + static const char* kPriorityAttr = "ADDON:priority"; static const char* kLanguageField = "language"; @@ -133,23 +137,28 @@ static const char* kTimezoneField = "timezone"; static const char* kOffsetField = "offset"; -static RosterData sRosterData(BLanguage("en_US"), - BFormattingConventions("en_US")); +static RosterData* sRosterData = NULL; +static pthread_once_t sRosterDataInitOnce = PTHREAD_ONCE_INIT; -RosterData::RosterData() - : - fLock("LocaleRosterData"), - fAreResourcesLoaded(false) -{ - openlog_team("liblocale.so", LOG_PID, LOG_USER); -#ifndef DEBUG - setlogmask_team(LOG_UPTO(LOG_WARNING)); -#endif +static struct RosterDataReaper { + ~RosterDataReaper() + { + delete sRosterData; + sRosterData = NULL; + } +} sRosterDataReaper; - InitializeCatalogAddOns(); - Refresh(); +} // anonymous namespace + + + +static void +InitializeRosterData() +{ + sRosterData = new (std::nothrow) RosterData(BLanguage("en_US"), + BFormattingConventions("en_US")); } @@ -160,14 +169,7 @@ fDefaultLocale(&language, &conventions), fAreResourcesLoaded(false) { - openlog_team("liblocale.so", LOG_PID, LOG_USER); -#ifndef DEBUG - setlogmask_team(LOG_UPTO(LOG_WARNING)); -#endif - - InitializeCatalogAddOns(); - - Refresh(); + fInitStatus = _Initialize(); } @@ -175,7 +177,7 @@ { BAutolock lock(fLock); - CleanupCatalogAddOns(); + _CleanupCatalogAddOns(); closelog(); } @@ -183,10 +185,34 @@ /*static*/ RosterData* RosterData::Default() { - return &sRosterData; + if (sRosterData == NULL) + pthread_once(&sRosterDataInitOnce, &BPrivate::InitializeRosterData); + + return sRosterData; } +status_t +RosterData::InitCheck() const +{ + return fAreResourcesLoaded ? B_OK : B_NO_INIT; +} + + +status_t +RosterData::Refresh() +{ + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + + _LoadLocaleSettings(); + _LoadTimeSettings(); + + return B_OK; +} + + int RosterData::CompareInfos(const void* left, const void* right) { @@ -196,35 +222,118 @@ status_t -RosterData::Refresh() +RosterData::SetDefaultFormattingConventions( + const BFormattingConventions& newFormattingConventions) { + status_t status = B_OK; + BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - _LoadLocaleSettings(); - _LoadTimeSettings(); + status = _SetDefaultFormattingConventions(newFormattingConventions); + if (status == B_OK) + status = _SaveLocaleSettings(); + + if (status == B_OK) { + BMessage updateMessage(B_LOCALE_CHANGED); + status = _AddDefaultFormattingConventionsToMessage(&updateMessage); + if (status == B_OK) + status = be_roster->Broadcast(&updateMessage); + } + + return status; +} + + +status_t +RosterData::SetDefaultTimeZone(const BTimeZone& newZone) +{ + status_t status = B_OK; + + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + + status = _SetDefaultTimeZone(newZone); + + if (status == B_OK) + status = _SaveTimeSettings(); + + if (status == B_OK) { + BMessage updateMessage(B_LOCALE_CHANGED); + status = _AddDefaultTimeZoneToMessage(&updateMessage); + if (status == B_OK) + status = be_roster->Broadcast(&updateMessage); + } + + return status; +} + + +status_t +RosterData::SetPreferredLanguages(const BMessage* languages) +{ + status_t status = B_OK; + + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + + status = _SetPreferredLanguages(languages); + + if (status == B_OK) + status = _SaveLocaleSettings(); + + if (status == B_OK) { + BMessage updateMessage(B_LOCALE_CHANGED); + status = _AddPreferredLanguagesToMessage(&updateMessage); + if (status == B_OK) + status = be_roster->Broadcast(&updateMessage); + } + + return status; +} + + +status_t +RosterData::_Initialize() +{ + openlog_team("liblocale.so", LOG_PID, LOG_USER); +#ifndef DEBUG + setlogmask_team(LOG_UPTO(LOG_WARNING)); +#endif + + status_t result = _InitializeCatalogAddOns(); + if (result != B_OK) + return result; + + if ((result = Refresh()) != B_OK) + return result; + + fInitStatus = B_OK; return B_OK; } + /* iterate over add-on-folders and collect information about each catalog-add-ons (types of catalogs) into fCatalogAddOnInfos. */ -void -RosterData::InitializeCatalogAddOns() +status_t +RosterData::_InitializeCatalogAddOns() { BAutolock lock(fLock); if (!lock.IsLocked()) - return; + return B_ERROR; // add info about embedded default catalog: CatalogAddOnInfo* defaultCatalogAddOnInfo = new(std::nothrow) CatalogAddOnInfo("Default", "", DefaultCatalog::kDefaultCatalogAddOnPriority); if (!defaultCatalogAddOnInfo) - return; + return B_NO_MEMORY; defaultCatalogAddOnInfo->fInstantiateFunc = DefaultCatalog::Instantiate; defaultCatalogAddOnInfo->fInstantiateEmbeddedFunc @@ -330,6 +439,8 @@ } } fCatalogAddOnInfos.SortItems(CompareInfos); + + return B_OK; } @@ -337,7 +448,7 @@ * unloads all catalog-add-ons (which will throw away all loaded catalogs, too) */ void -RosterData::CleanupCatalogAddOns() +RosterData::_CleanupCatalogAddOns() { BAutolock lock(fLock); if (!lock.IsLocked()) @@ -354,82 +465,6 @@ status_t -RosterData::SetDefaultFormattingConventions( - const BFormattingConventions& newFormattingConventions) -{ - status_t status = B_OK; - - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; - - status = _SetDefaultFormattingConventions(newFormattingConventions); - - if (status == B_OK) - status = _SaveLocaleSettings(); - - if (status == B_OK) { - BMessage updateMessage(B_LOCALE_CHANGED); - status = _AddDefaultFormattingConventionsToMessage(&updateMessage); - if (status == B_OK) - status = be_roster->Broadcast(&updateMessage); - } - - return status; -} - - -status_t -RosterData::SetDefaultTimeZone(const BTimeZone& newZone) -{ - status_t status = B_OK; - - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; - - status = _SetDefaultTimeZone(newZone); - - if (status == B_OK) - status = _SaveTimeSettings(); - - if (status == B_OK) { - BMessage updateMessage(B_LOCALE_CHANGED); - status = _AddDefaultTimeZoneToMessage(&updateMessage); - if (status == B_OK) - status = be_roster->Broadcast(&updateMessage); - } - - return status; -} - - -status_t -RosterData::SetPreferredLanguages(const BMessage* languages) -{ - status_t status = B_OK; - - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; - - status = _SetPreferredLanguages(languages); - - if (status == B_OK) - status = _SaveLocaleSettings(); - - if (status == B_OK) { - BMessage updateMessage(B_LOCALE_CHANGED); - status = _AddPreferredLanguagesToMessage(&updateMessage); - if (status == B_OK) - status = be_roster->Broadcast(&updateMessage); - } - - return status; -} - - -status_t RosterData::_LoadLocaleSettings() { BPath path; @@ -653,9 +688,15 @@ // #pragma mark - MutableLocaleRoster +namespace { + + static MutableLocaleRoster sLocaleRoster; +} // anonymous namespace + + MutableLocaleRoster::MutableLocaleRoster() { }