Make BCatalog threadsafe.

* use a locker to protect the CatalogAddOn-chain against parallel
  access
* rename BCatalog::SetCatalog() to SetTo() and make it a proper
  initializing function
* adjust implementation of BLocaleRoster accordingly
This commit is contained in:
Oliver Tappe 2012-04-14 17:38:58 +02:00
parent 250eca3254
commit cc52f0df3a
3 changed files with 60 additions and 15 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2010, Haiku, Inc.
* Copyright 2003-2012, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#ifndef _CATALOG_H_
@ -7,6 +7,7 @@
#include <LocaleRoster.h>
#include <Locker.h>
#include <SupportDefs.h>
#include <String.h>
@ -42,8 +43,9 @@ public:
status_t GetLanguage(BString* language);
status_t GetFingerprint(uint32* fingerprint);
status_t SetCatalog(const entry_ref& catalogOwner,
uint32 fingerprint);
status_t SetTo(const entry_ref& catalogOwner,
const char* language = NULL,
uint32 fingerprint = 0);
status_t InitCheck() const;
int32 CountItems() const;
@ -58,6 +60,7 @@ protected:
// hide assignment and copy-constructor
BCatalogAddOn* fCatalog;
mutable BLocker fLock;
private:
friend class BLocale;

View File

@ -1,6 +1,6 @@
/*
* Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de
* Copyright 2003-2004, Oliver Tappe, zooey@hirschkaefer.de
* Copyright 2003-2004,2012, Oliver Tappe, zooey@hirschkaefer.de
* Distributed under the terms of the MIT License.
*/
@ -9,6 +9,7 @@
#include <syslog.h>
#include <Application.h>
#include <Autolock.h>
#include <Locale.h>
#include <MutableLocaleRoster.h>
#include <Node.h>
@ -21,16 +22,19 @@ using BPrivate::MutableLocaleRoster;
//#pragma mark - BCatalog
BCatalog::BCatalog()
:
fCatalog(NULL)
fCatalog(NULL),
fLock("Catalog")
{
}
BCatalog::BCatalog(const entry_ref& catalogOwner, const char* language,
uint32 fingerprint)
:
fCatalog(NULL),
fLock("Catalog")
{
fCatalog = MutableLocaleRoster::Default()->LoadCatalog(catalogOwner,
language, fingerprint);
SetTo(catalogOwner, language, fingerprint);
}
@ -44,6 +48,10 @@ const char*
BCatalog::GetString(const char* string, const char* context,
const char* comment)
{
BAutolock lock(&fLock);
if (!lock.IsLocked())
return string;
const char* translated;
for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
translated = cat->GetString(string, context, comment);
@ -58,6 +66,10 @@ BCatalog::GetString(const char* string, const char* context,
const char*
BCatalog::GetString(uint32 id)
{
BAutolock lock(&fLock);
if (!lock.IsLocked())
return "";
const char* translated;
for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
translated = cat->GetString(id);
@ -72,6 +84,10 @@ BCatalog::GetString(uint32 id)
status_t
BCatalog::GetData(const char* name, BMessage* msg)
{
BAutolock lock(&fLock);
if (!lock.IsLocked())
return B_ERROR;
if (fCatalog == NULL)
return B_NO_INIT;
@ -89,6 +105,10 @@ BCatalog::GetData(const char* name, BMessage* msg)
status_t
BCatalog::GetData(uint32 id, BMessage* msg)
{
BAutolock lock(&fLock);
if (!lock.IsLocked())
return B_ERROR;
if (fCatalog == NULL)
return B_NO_INIT;
@ -106,6 +126,10 @@ BCatalog::GetData(uint32 id, BMessage* msg)
status_t
BCatalog::GetSignature(BString* sig)
{
BAutolock lock(&fLock);
if (!lock.IsLocked())
return B_ERROR;
if (sig == NULL)
return B_BAD_VALUE;
@ -121,6 +145,10 @@ BCatalog::GetSignature(BString* sig)
status_t
BCatalog::GetLanguage(BString* lang)
{
BAutolock lock(&fLock);
if (!lock.IsLocked())
return B_ERROR;
if (lang == NULL)
return B_BAD_VALUE;
@ -136,6 +164,10 @@ BCatalog::GetLanguage(BString* lang)
status_t
BCatalog::GetFingerprint(uint32* fp)
{
BAutolock lock(&fLock);
if (!lock.IsLocked())
return B_ERROR;
if (fp == NULL)
return B_BAD_VALUE;
@ -149,13 +181,16 @@ BCatalog::GetFingerprint(uint32* fp)
status_t
BCatalog::SetCatalog(const entry_ref& catalogOwner, uint32 fingerprint)
BCatalog::SetTo(const entry_ref& catalogOwner, const char* language,
uint32 fingerprint)
{
// This is not thread safe. It is used only in ReadOnlyBootPrompt and should
// not do harm there, but not sure what to do about it…
BAutolock lock(&fLock);
if (!lock.IsLocked())
return B_ERROR;
MutableLocaleRoster::Default()->UnloadCatalog(fCatalog);
fCatalog = MutableLocaleRoster::Default()->LoadCatalog(catalogOwner, NULL,
fingerprint);
fCatalog = MutableLocaleRoster::Default()->LoadCatalog(catalogOwner,
language, fingerprint);
return B_OK;
}
@ -164,6 +199,10 @@ BCatalog::SetCatalog(const entry_ref& catalogOwner, uint32 fingerprint)
status_t
BCatalog::InitCheck() const
{
BAutolock lock(&fLock);
if (!lock.IsLocked())
return B_ERROR;
return fCatalog != NULL ? fCatalog->InitCheck() : B_NO_INIT;
}
@ -171,6 +210,10 @@ BCatalog::InitCheck() const
int32
BCatalog::CountItems() const
{
BAutolock lock(&fLock);
if (!lock.IsLocked())
return 0;
return fCatalog != NULL ? fCatalog->CountItems() : 0;
}

View File

@ -548,9 +548,8 @@ BLocaleRoster::_GetCatalog(BCatalog* catalog, vint32* catalogInitStatus)
// load the catalog for this mimetype and return it to the app
entry_ref ref;
BEntry(info.name).GetRef(&ref);
catalog->SetCatalog(ref, 0);
*catalogInitStatus = true;
if (BEntry(info.name).GetRef(&ref) == B_OK && catalog->SetTo(ref) == B_OK)
*catalogInitStatus = true;
return catalog;
}