Bug 584319 - 'IndexedDB: Out of Memory error and crash when calling moz_indexedDB.open a lot'. r=sicking

This commit is contained in:
Ben Turner 2010-10-19 10:58:42 -07:00
Родитель e8315ce8b9
Коммит 88b443f419
13 изменённых файлов: 156 добавлений и 152 удалений

Просмотреть файл

@ -172,12 +172,6 @@ AsyncConnectionHelper::Run()
NS_ASSERTION(connection, "This should never be null!");
}
}
else if (mDatabase) {
rv = mDatabase->GetOrCreateConnection(getter_AddRefs(connection));
if (NS_SUCCEEDED(rv)) {
NS_ASSERTION(connection, "This should never be null!");
}
}
if (connection) {
rv = connection->SetProgressHandler(kProgressHandlerGranularity, this,

Просмотреть файл

@ -147,14 +147,14 @@ CheckPermissionsHelper::Run()
nsRefPtr<AsyncConnectionHelper> helper;
helper.swap(mHelper);
nsCOMPtr<nsIThread> thread;
thread.swap(mThread);
nsCOMPtr<nsIDOMWindow> window;
window.swap(mWindow);
if (permission == nsIPermissionManager::ALLOW_ACTION) {
return helper->Dispatch(thread);
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
NS_ASSERTION(mgr, "This should never be null!");
return helper->Dispatch(mgr->IOThread());
}
NS_ASSERTION(permission == nsIPermissionManager::UNKNOWN_ACTION ||

Просмотреть файл

@ -63,25 +63,21 @@ public:
NS_DECL_NSIOBSERVER
CheckPermissionsHelper(AsyncConnectionHelper* aHelper,
nsIThread* aThread,
nsIDOMWindow* aWindow,
const nsACString& aASCIIOrigin)
: mHelper(aHelper),
mThread(aThread),
mWindow(aWindow),
mASCIIOrigin(aASCIIOrigin),
mHasPrompted(PR_FALSE),
mPromptResult(0)
{
NS_ASSERTION(aHelper, "Null pointer!");
NS_ASSERTION(aThread, "Null pointer!");
NS_ASSERTION(aWindow, "Null pointer!");
NS_ASSERTION(!aASCIIOrigin.IsEmpty(), "Empty host!");
}
private:
nsRefPtr<AsyncConnectionHelper> mHelper;
nsCOMPtr<nsIThread> mThread;
nsCOMPtr<nsIDOMWindow> mWindow;
nsCString mASCIIOrigin;
PRBool mHasPrompted;

Просмотреть файл

@ -81,6 +81,54 @@ EnumerateObjectStoreNames(const nsAString& aKey,
}
#ifdef NS_BUILD_REFCNT_LOGGING
DatabaseInfo::DatabaseInfo()
: id(0)
{
MOZ_COUNT_CTOR(DatabaseInfo);
}
DatabaseInfo::~DatabaseInfo()
{
MOZ_COUNT_DTOR(DatabaseInfo);
}
IndexInfo::IndexInfo()
: id(LL_MININT),
unique(false),
autoIncrement(false)
{
MOZ_COUNT_CTOR(IndexInfo);
}
IndexInfo::~IndexInfo()
{
MOZ_COUNT_DTOR(IndexInfo);
}
ObjectStoreInfo::ObjectStoreInfo()
: id(0),
autoIncrement(false),
databaseId(0)
{
MOZ_COUNT_CTOR(ObjectStoreInfo);
}
ObjectStoreInfo::~ObjectStoreInfo()
{
MOZ_COUNT_DTOR(ObjectStoreInfo);
}
IndexUpdateInfo::IndexUpdateInfo()
{
MOZ_COUNT_CTOR(IndexUpdateInfo);
}
IndexUpdateInfo::~IndexUpdateInfo()
{
MOZ_COUNT_DTOR(IndexUpdateInfo);
}
#endif /* NS_BUILD_REFCNT_LOGGING */
// static
bool
DatabaseInfo::Get(PRUint32 aId,

Просмотреть файл

@ -57,8 +57,13 @@ struct DatabaseInfo
nsAutoRefCnt referenceCount;
#ifdef NS_BUILD_REFCNT_LOGGING
DatabaseInfo();
~DatabaseInfo();
#else
DatabaseInfo()
: id(0) { }
#endif
static bool Get(PRUint32 aId,
DatabaseInfo** aInfo);
@ -73,8 +78,13 @@ struct DatabaseInfo
struct IndexInfo
{
#ifdef NS_BUILD_REFCNT_LOGGING
IndexInfo();
~IndexInfo();
#else
IndexInfo()
: id(LL_MININT), unique(false), autoIncrement(false) { }
#endif
PRInt64 id;
nsString name;
@ -92,8 +102,13 @@ struct ObjectStoreInfo
PRUint32 databaseId;
nsTArray<IndexInfo> indexes;
#ifdef NS_BUILD_REFCNT_LOGGING
ObjectStoreInfo();
~ObjectStoreInfo();
#else
ObjectStoreInfo()
: id(0), autoIncrement(false), databaseId(0) { }
#endif
static bool Get(PRUint32 aDatabaseId,
const nsAString& aName,
@ -107,6 +122,11 @@ struct ObjectStoreInfo
struct IndexUpdateInfo
{
#ifdef NS_BUILD_REFCNT_LOGGING
IndexUpdateInfo();
~IndexUpdateInfo();
#endif
IndexInfo info;
Key value;
};

Просмотреть файл

@ -224,14 +224,10 @@ already_AddRefed<IDBDatabase>
IDBDatabase::Create(nsIScriptContext* aScriptContext,
nsPIDOMWindow* aOwner,
DatabaseInfo* aDatabaseInfo,
LazyIdleThread* aThread,
nsCOMPtr<mozIStorageConnection>& aConnection,
const nsACString& aASCIIOrigin)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aDatabaseInfo, "Null pointer!");
NS_ASSERTION(aThread, "Null pointer!");
NS_ASSERTION(aConnection, "Null pointer!");
NS_ASSERTION(!aASCIIOrigin.IsEmpty(), "Empty origin!");
nsRefPtr<IDBDatabase> db(new IDBDatabase());
@ -245,16 +241,11 @@ IDBDatabase::Create(nsIScriptContext* aScriptContext,
db->mFilePath = aDatabaseInfo->filePath;
db->mASCIIOrigin = aASCIIOrigin;
aThread->SetWeakIdleObserver(db);
db->mConnectionThread = aThread;
db->mConnection.swap(aConnection);
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
NS_ASSERTION(mgr, "This should never be null!");
if (!mgr->RegisterDatabase(db)) {
NS_WARNING("Out of memory?");
// Either out of memory or shutting down.
return nsnull;
}
@ -263,7 +254,8 @@ IDBDatabase::Create(nsIScriptContext* aScriptContext,
IDBDatabase::IDBDatabase()
: mDatabaseId(0),
mInvalidated(0)
mInvalidated(0),
mRegistered(false)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -276,17 +268,14 @@ IDBDatabase::IDBDatabase()
IDBDatabase::~IDBDatabase()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
if (mgr) {
mgr->UnregisterDatabase(this);
}
if (mConnectionThread) {
mConnectionThread->SetWeakIdleObserver(nsnull);
if (mRegistered) {
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
if (mgr) {
mgr->UnregisterDatabase(this);
}
}
CloseConnection();
if (mDatabaseId && !mInvalidated) {
DatabaseInfo* info;
if (!DatabaseInfo::Get(mDatabaseId, &info)) {
@ -314,40 +303,6 @@ IDBDatabase::~IDBDatabase()
}
}
nsresult
IDBDatabase::GetOrCreateConnection(mozIStorageConnection** aResult)
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
if (mInvalidated) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!mConnection) {
mConnection = IDBFactory::GetConnection(mFilePath);
NS_ENSURE_TRUE(mConnection, NS_ERROR_FAILURE);
}
nsCOMPtr<mozIStorageConnection> result(mConnection);
result.forget(aResult);
return NS_OK;
}
void
IDBDatabase::CloseConnection()
{
if (mConnection) {
if (mConnectionThread) {
NS_ProxyRelease(mConnectionThread, mConnection, PR_TRUE);
}
else {
NS_ERROR("Leaking connection!");
mozIStorageConnection* leak;
mConnection.forget(&leak);
}
}
}
bool
IDBDatabase::IsQuotaDisabled()
{
@ -415,7 +370,6 @@ IDBDatabase::Invalidate()
}
PR_AtomicSet(&mInvalidated, 1);
CloseConnection();
DatabaseInfo* info;
if (!DatabaseInfo::Get(mDatabaseId, &info)) {
@ -448,7 +402,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBDatabase)
NS_INTERFACE_MAP_ENTRY(nsIIDBDatabase)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBDatabase)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
@ -653,6 +606,10 @@ IDBDatabase::Transaction(nsIVariant* aStoreNames,
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (IndexedDatabaseManager::IsShuttingDown()) {
return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
}
if (aOptionalArgCount) {
if (aMode != nsIIDBTransaction::READ_WRITE &&
aMode != nsIIDBTransaction::READ_ONLY &&
@ -831,19 +788,6 @@ IDBDatabase::ObjectStore(const nsAString& aName,
return NS_OK;
}
NS_IMETHODIMP
IDBDatabase::Observe(nsISupports* aSubject,
const char* aTopic,
const PRUnichar* aData)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ENSURE_FALSE(strcmp(aTopic, IDLE_THREAD_TOPIC), NS_ERROR_UNEXPECTED);
CloseConnection();
return NS_OK;
}
PRUint16
SetVersionHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{

Просмотреть файл

@ -41,16 +41,13 @@
#define mozilla_dom_indexeddb_idbdatabase_h__
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "mozilla/dom/indexedDB/LazyIdleThread.h"
#include "nsIIDBDatabase.h"
#include "nsIObserver.h"
#include "nsCycleCollectionParticipant.h"
#include "nsDOMEventTargetHelper.h"
#include "nsDOMLists.h"
class mozIStorageConnection;
class nsIScriptContext;
class nsPIDOMWindow;
@ -59,17 +56,17 @@ BEGIN_INDEXEDDB_NAMESPACE
class AsyncConnectionHelper;
struct DatabaseInfo;
class IDBTransaction;
class IndexedDatabaseManager;
class IDBDatabase : public nsDOMEventTargetHelper,
public nsIIDBDatabase,
public nsIObserver
public nsIIDBDatabase
{
friend class AsyncConnectionHelper;
friend class IndexedDatabaseManager;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIIDBDATABASE
NS_DECL_NSIOBSERVER
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBDatabase,
nsDOMEventTargetHelper)
@ -78,17 +75,8 @@ public:
Create(nsIScriptContext* aScriptContext,
nsPIDOMWindow* aOwner,
DatabaseInfo* aDatabaseInfo,
LazyIdleThread* aThread,
nsCOMPtr<mozIStorageConnection>& aConnection,
const nsACString& aASCIIOrigin);
nsIThread* ConnectionThread()
{
return mConnectionThread;
}
void CloseConnection();
PRUint32 Id()
{
return mDatabaseId;
@ -111,8 +99,7 @@ public:
return mOwner;
}
bool
IsQuotaDisabled();
bool IsQuotaDisabled();
nsCString& Origin()
{
@ -126,21 +113,13 @@ private:
IDBDatabase();
~IDBDatabase();
// Only meant to be called on mStorageThread!
nsresult GetOrCreateConnection(mozIStorageConnection** aConnection);
PRUint32 mDatabaseId;
nsString mName;
nsString mDescription;
nsString mFilePath;
nsCString mASCIIOrigin;
PRInt32 mInvalidated;
nsRefPtr<LazyIdleThread> mConnectionThread;
// Only touched on mStorageThread! These must be destroyed in the
// FireCloseConnectionRunnable method.
nsCOMPtr<mozIStorageConnection> mConnection;
bool mRegistered;
// Only touched on the main thread.
nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener;

Просмотреть файл

@ -128,30 +128,24 @@ public:
OpenDatabaseHelper(IDBRequest* aRequest,
const nsAString& aName,
const nsAString& aDescription,
const nsACString& aASCIIOrigin,
LazyIdleThread* aThread)
const nsACString& aASCIIOrigin)
: AsyncConnectionHelper(static_cast<IDBDatabase*>(nsnull), aRequest),
mName(aName), mDescription(aDescription), mASCIIOrigin(aASCIIOrigin),
mThread(aThread), mDatabaseId(0)
mDatabaseId(0)
{ }
PRUint16 DoDatabaseWork(mozIStorageConnection* aConnection);
PRUint16 GetSuccessResult(nsIWritableVariant* aResult);
private:
PRUint16 DoDatabaseWorkInternal(mozIStorageConnection* aConnection);
// In-params.
nsString mName;
nsString mDescription;
nsCString mASCIIOrigin;
nsRefPtr<LazyIdleThread> mThread;
// Out-params.
nsTArray<nsAutoPtr<ObjectStoreInfo> > mObjectStores;
nsString mVersion;
nsCOMPtr<mozIStorageConnection> mConnection;
nsString mDatabaseFilePath;
PRUint32 mDatabaseId;
};
@ -718,14 +712,11 @@ IDBFactory::Open(const nsAString& aName,
nsRefPtr<IDBRequest> request = IDBRequest::Create(this, context, innerWindow);
NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
nsRefPtr<LazyIdleThread> thread(new LazyIdleThread(kDefaultThreadTimeoutMS,
nsnull));
nsRefPtr<OpenDatabaseHelper> openHelper =
new OpenDatabaseHelper(request, aName, aDescription, origin, thread);
new OpenDatabaseHelper(request, aName, aDescription, origin);
nsRefPtr<CheckPermissionsHelper> permissionHelper =
new CheckPermissionsHelper(openHelper, thread, innerWindow, origin);
new CheckPermissionsHelper(openHelper, innerWindow, origin);
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::GetOrCreate();
NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE);
@ -839,30 +830,26 @@ IDBFactory::MakeBoundKeyRange(nsIVariant* aLeft,
PRUint16
OpenDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{
PRUint16 result = DoDatabaseWorkInternal(aConnection);
if (result != OK) {
mConnection = nsnull;
}
return result;
}
PRUint16
OpenDatabaseHelper::DoDatabaseWorkInternal(mozIStorageConnection* aConnection)
{
#ifdef DEBUG
{
PRBool correctThread;
NS_ASSERTION(NS_SUCCEEDED(mThread->IsOnCurrentThread(&correctThread)) &&
NS_ASSERTION(NS_SUCCEEDED(IndexedDatabaseManager::Get()->IOThread()->
IsOnCurrentThread(&correctThread)) &&
correctThread,
"Running on the wrong thread!");
}
#endif
NS_ASSERTION(!aConnection, "Huh?!");
if (IndexedDatabaseManager::IsShuttingDown()) {
return nsIIDBDatabaseException::UNKNOWN_ERR;
}
nsCOMPtr<mozIStorageConnection> connection;
nsresult rv = CreateDatabaseConnection(mASCIIOrigin, mName, mDescription,
mDatabaseFilePath,
getter_AddRefs(mConnection));
getter_AddRefs(connection));
NS_ENSURE_SUCCESS(rv, nsIIDBDatabaseException::UNKNOWN_ERR);
mDatabaseId = HashString(mDatabaseFilePath);
@ -872,7 +859,7 @@ OpenDatabaseHelper::DoDatabaseWorkInternal(mozIStorageConnection* aConnection)
{ // Load object store names and ids.
nsCOMPtr<mozIStorageStatement> stmt;
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
rv = connection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT name, id, key_path, auto_increment "
"FROM object_store"
), getter_AddRefs(stmt));
@ -910,7 +897,7 @@ OpenDatabaseHelper::DoDatabaseWorkInternal(mozIStorageConnection* aConnection)
{ // Load index information
nsCOMPtr<mozIStorageStatement> stmt;
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
rv = connection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT object_store_id, id, name, key_path, unique_index, "
"object_store_autoincrement "
"FROM object_store_index"
@ -951,7 +938,7 @@ OpenDatabaseHelper::DoDatabaseWorkInternal(mozIStorageConnection* aConnection)
{ // Load version information.
nsCOMPtr<mozIStorageStatement> stmt;
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
rv = connection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT version "
"FROM database"
), getter_AddRefs(stmt));
@ -975,8 +962,6 @@ OpenDatabaseHelper::DoDatabaseWorkInternal(mozIStorageConnection* aConnection)
PRUint16
OpenDatabaseHelper::GetSuccessResult(nsIWritableVariant* aResult)
{
NS_ASSERTION(mConnection, "Should have a connection!");
DatabaseInfo* dbInfo;
if (DatabaseInfo::Get(mDatabaseId, &dbInfo)) {
NS_ASSERTION(dbInfo->referenceCount, "Bad reference count!");
@ -1064,10 +1049,10 @@ OpenDatabaseHelper::GetSuccessResult(nsIWritableVariant* aResult)
nsRefPtr<IDBDatabase> db =
IDBDatabase::Create(mRequest->ScriptContext(), mRequest->Owner(), dbInfo,
mThread, mConnection, mASCIIOrigin);
NS_ASSERTION(db, "This can't fail!");
NS_ASSERTION(!mConnection, "Should have swapped out!");
mASCIIOrigin);
if (!db) {
return nsIIDBDatabaseException::UNKNOWN_ERR;
}
aResult->SetAsISupports(static_cast<nsPIDOMEventTarget*>(db));
return OK;

Просмотреть файл

@ -53,6 +53,7 @@
#include "nsHashKeys.h"
#include "nsInterfaceHashtable.h"
class mozIStorageConnection;
class mozIStorageStatement;
class nsIThread;

Просмотреть файл

@ -68,7 +68,7 @@ using namespace mozilla::services;
namespace {
bool gShutdown = false;
PRInt32 gShutdown = 0;
// Does not hold a reference.
IndexedDatabaseManager* gInstance = nsnull;
@ -116,7 +116,7 @@ IndexedDatabaseManager::GetOrCreate()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (gShutdown) {
if (IsShuttingDown()) {
NS_ERROR("Calling GetOrCreateInstance() after shutdown!");
return nsnull;
}
@ -153,7 +153,8 @@ IndexedDatabaseManager::GetOrCreate()
// Make a lazy thread for any IO we need (like clearing or enumerating the
// contents of indexedDB database directories).
instance->mIOThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS);
instance->mIOThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS,
LazyIdleThread::ManualShutdown);
// The observer service will hold our last reference, don't AddRef here.
gInstance = instance;
@ -187,7 +188,7 @@ IndexedDatabaseManager::RegisterDatabase(IDBDatabase* aDatabase)
NS_ASSERTION(aDatabase, "Null pointer!");
// Don't allow any new databases to be created after shutdown.
if (gShutdown) {
if (IsShuttingDown()) {
return false;
}
@ -205,6 +206,8 @@ IndexedDatabaseManager::RegisterDatabase(IDBDatabase* aDatabase)
NS_WARNING("Out of memory?");
return false;
}
aDatabase->mRegistered = true;
return true;
}
@ -287,6 +290,13 @@ IndexedDatabaseManager::WaitForClearAndDispatch(const nsACString& aOrigin,
return NS_DispatchToCurrentThread(aRunnable);
}
// static
bool
IndexedDatabaseManager::IsShuttingDown()
{
return !!gShutdown;
}
NS_IMPL_ISUPPORTS2(IndexedDatabaseManager, nsIIndexedDatabaseManager,
nsIObserver)
@ -445,9 +455,11 @@ IndexedDatabaseManager::Observe(nsISupports* aSubject,
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID)) {
// Setting this flag prevents the servic from being recreated and prevents
// Setting this flag prevents the service from being recreated and prevents
// further databases from being created.
gShutdown = true;
if (PR_AtomicSet(&gShutdown, 1)) {
NS_ERROR("Shutdown more than once?!");
}
// Make sure to join with our IO thread.
if (NS_FAILED(mIOThread->Shutdown())) {

Просмотреть файл

@ -80,6 +80,14 @@ public:
nsresult WaitForClearAndDispatch(const nsACString& aOrigin,
nsIRunnable* aRunnable);
nsIThread* IOThread()
{
NS_ASSERTION(mIOThread, "This should never be null!");
return mIOThread;
}
static bool IsShuttingDown();
private:
IndexedDatabaseManager();
~IndexedDatabaseManager();

Просмотреть файл

@ -64,6 +64,7 @@ USING_INDEXEDDB_NAMESPACE
using mozilla::MutexAutoLock;
LazyIdleThread::LazyIdleThread(PRUint32 aIdleTimeoutMS,
ShutdownMethod aShutdownMethod,
nsIObserver* aIdleObserver)
: mMutex("LazyIdleThread::mMutex"),
mOwningThread(NS_GetCurrentThread()),
@ -71,6 +72,7 @@ LazyIdleThread::LazyIdleThread(PRUint32 aIdleTimeoutMS,
mIdleTimeoutMS(aIdleTimeoutMS),
mPendingEventCount(0),
mIdleNotificationCount(0),
mShutdownMethod(aShutdownMethod),
mShutdown(PR_FALSE),
mThreadIsShuttingDown(PR_FALSE),
mIdleTimeoutEnabled(PR_TRUE)
@ -172,7 +174,7 @@ LazyIdleThread::EnsureThread()
nsresult rv;
if (NS_IsMainThread()) {
if (mShutdownMethod == AutomaticShutdown && NS_IsMainThread()) {
nsCOMPtr<nsIObserverService> obs =
do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
@ -257,7 +259,7 @@ LazyIdleThread::ShutdownThread()
nsresult rv;
if (mThread) {
if (NS_IsMainThread()) {
if (mShutdownMethod == AutomaticShutdown && NS_IsMainThread()) {
nsCOMPtr<nsIObserverService> obs =
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
NS_WARN_IF_FALSE(obs, "Failed to get observer service!");
@ -504,8 +506,10 @@ LazyIdleThread::Observe(nsISupports* /* aSubject */,
const PRUnichar* /* aData */)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ENSURE_FALSE(strcmp("xpcom-shutdown-threads", aTopic),
NS_ERROR_UNEXPECTED);
NS_ASSERTION(mShutdownMethod == AutomaticShutdown,
"Should not receive notifications if not AutomaticShutdown!");
NS_ASSERTION(!strcmp("xpcom-shutdown-threads", aTopic), "Bad topic!");
Shutdown();
return NS_OK;
}

Просмотреть файл

@ -72,11 +72,17 @@ public:
NS_DECL_NSITHREADOBSERVER
NS_DECL_NSIOBSERVER
enum ShutdownMethod {
AutomaticShutdown = 0,
ManualShutdown
};
/**
* Create a new LazyIdleThread that will destroy its thread after the given
* number of milliseconds.
*/
LazyIdleThread(PRUint32 aIdleTimeoutMS,
ShutdownMethod aShutdownMethod = AutomaticShutdown,
nsIObserver* aIdleObserver = nsnull);
/**
@ -191,6 +197,13 @@ private:
*/
PRUint32 mIdleNotificationCount;
/**
* Whether or not the thread should automatically shutdown. If the owner
* specified ManualShutdown at construction time then the owner should take
* care to call Shutdown() manually when appropriate.
*/
ShutdownMethod mShutdownMethod;
/**
* Only accessed on the owning thread. Set to true when Shutdown() has been
* called and prevents EnsureThread() from recreating mThread.