--- a/dom/media/MediaPrefs.cpp
+++ b/dom/media/MediaPrefs.cpp
@@ -64,16 +64,30 @@ void MediaPrefs::PrefAddVarCache(uint32_
void MediaPrefs::PrefAddVarCache(float* aVariable,
const char* aPref,
float aDefault)
{
Preferences::AddFloatVarCache(aVariable, aPref, aDefault);
}
+void MediaPrefs::PrefAddVarCache(AtomicBool* aVariable,
+ const char* aPref,
+ bool aDefault)
+{
+ Preferences::AddAtomicBoolVarCache(aVariable, aPref, aDefault);
+}
+
+void MediaPrefs::PrefAddVarCache(AtomicInt32* aVariable,
+ const char* aPref,
+ int32_t aDefault)
+{
+ Preferences::AddAtomicIntVarCache(aVariable, aPref, aDefault);
+}
+
void MediaPrefs::PrefAddVarCache(AtomicUint32* aVariable,
const char* aPref,
uint32_t aDefault)
{
Preferences::AddAtomicUintVarCache(aVariable, aPref, aDefault);
}
} // namespace mozilla
--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -44,16 +44,18 @@ PrefTemplate<Type, Get##Name##PrefDefaul
#define TEST_PREFERENCE_FAKE_RECOGNITION_SERVICE "media.webspeech.test.fake_recognition_service"
namespace mozilla {
template<class T> class StaticAutoPtr;
class MediaPrefs final
{
+ typedef Atomic<bool, Relaxed> AtomicBool;
+ typedef Atomic<int32_t, Relaxed> AtomicInt32;
typedef Atomic<uint32_t, Relaxed> AtomicUint32;
template <typename T>
struct StripAtomicImpl {
typedef T Type;
};
template <typename T, MemoryOrdering Order>
@@ -210,16 +212,18 @@ private:
template<class T> friend class StaticAutoPtr;
static StaticAutoPtr<MediaPrefs> sInstance;
// Creating these to avoid having to include Preferences.h in the .h
static void PrefAddVarCache(bool*, const char*, bool);
static void PrefAddVarCache(int32_t*, const char*, int32_t);
static void PrefAddVarCache(uint32_t*, const char*, uint32_t);
static void PrefAddVarCache(float*, const char*, float);
+ static void PrefAddVarCache(AtomicBool*, const char*, bool);
+ static void PrefAddVarCache(AtomicInt32*, const char*, int32_t);
static void PrefAddVarCache(AtomicUint32*, const char*, uint32_t);
static void AssertMainThread();
MediaPrefs();
MediaPrefs(const MediaPrefs&) = delete;
MediaPrefs& operator=(const MediaPrefs&) = delete;
};
--- a/gfx/thebes/gfxPrefs.cpp
+++ b/gfx/thebes/gfxPrefs.cpp
@@ -164,16 +164,40 @@ void gfxPrefs::PrefAddVarCache(float* aV
void gfxPrefs::PrefAddVarCache(std::string* aVariable,
const char* aPref,
std::string aDefault)
{
MOZ_ASSERT(IsPrefsServiceAvailable());
Preferences::SetCString(aPref, aVariable->c_str());
}
+void gfxPrefs::PrefAddVarCache(AtomicBool* aVariable,
+ const char* aPref,
+ bool aDefault)
+{
+ MOZ_ASSERT(IsPrefsServiceAvailable());
+ Preferences::AddAtomicBoolVarCache(aVariable, aPref, aDefault);
+}
+
+void gfxPrefs::PrefAddVarCache(AtomicInt32* aVariable,
+ const char* aPref,
+ int32_t aDefault)
+{
+ MOZ_ASSERT(IsPrefsServiceAvailable());
+ Preferences::AddAtomicIntVarCache(aVariable, aPref, aDefault);
+}
+
+void gfxPrefs::PrefAddVarCache(AtomicUint32* aVariable,
+ const char* aPref,
+ uint32_t aDefault)
+{
+ MOZ_ASSERT(IsPrefsServiceAvailable());
+ Preferences::AddAtomicUintVarCache(aVariable, aPref, aDefault);
+}
+
bool gfxPrefs::PrefGet(const char* aPref, bool aDefault)
{
MOZ_ASSERT(IsPrefsServiceAvailable());
return Preferences::GetBool(aPref, aDefault);
}
int32_t gfxPrefs::PrefGet(const char* aPref, int32_t aDefault)
{
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -5,16 +5,17 @@
#ifndef GFX_PREFS_H
#define GFX_PREFS_H
#include <cmath> // for M_PI
#include <stdint.h>
#include <string>
#include "mozilla/Assertions.h"
+#include "mozilla/Atomics.h"
#include "mozilla/gfx/LoggingConstants.h"
#include "nsTArray.h"
// First time gfxPrefs::GetSingleton() needs to be called on the main thread,
// before any of the methods accessing the values are used, but after
// the Preferences system has been initialized.
// The static methods to access the preference value are safe to call
@@ -107,16 +108,20 @@ class GfxPrefValue; // defined in PGPU
} // namespace gfx
} // namespace mozilla
class gfxPrefs;
class gfxPrefs final
{
typedef mozilla::gfx::GfxPrefValue GfxPrefValue;
+ typedef mozilla::Atomic<bool, mozilla::Relaxed> AtomicBool;
+ typedef mozilla::Atomic<int32_t, mozilla::Relaxed> AtomicInt32;
+ typedef mozilla::Atomic<uint32_t, mozilla::Relaxed> AtomicUint32;
+
private:
// Enums for the update policy.
enum class UpdatePolicy {
Skip, // Set the value to default, skip any Preferences calls
Once, // Evaluate the preference once, unchanged during the session
Live // Evaluate the preference and set callback so it stays current/live
};
@@ -785,16 +790,19 @@ private:
static bool IsPrefsServiceAvailable();
static bool IsParentProcess();
// Creating these to avoid having to include Preferences.h in the .h
static void PrefAddVarCache(bool*, const char*, bool);
static void PrefAddVarCache(int32_t*, const char*, int32_t);
static void PrefAddVarCache(uint32_t*, const char*, uint32_t);
static void PrefAddVarCache(float*, const char*, float);
static void PrefAddVarCache(std::string*, const char*, std::string);
+ static void PrefAddVarCache(AtomicBool*, const char*, bool);
+ static void PrefAddVarCache(AtomicInt32*, const char*, int32_t);
+ static void PrefAddVarCache(AtomicUint32*, const char*, uint32_t);
static bool PrefGet(const char*, bool);
static int32_t PrefGet(const char*, int32_t);
static uint32_t PrefGet(const char*, uint32_t);
static float PrefGet(const char*, float);
static std::string PrefGet(const char*, std::string);
static void PrefSet(const char* aPref, bool aValue);
static void PrefSet(const char* aPref, int32_t aValue);
static void PrefSet(const char* aPref, uint32_t aValue);
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -4923,16 +4923,45 @@ Preferences::AddBoolVarCache(bool* aCach
CacheData* data = new CacheData();
data->mCacheLocation = aCache;
data->mDefaultValueBool = aDefault;
CacheDataAppendElement(data);
RegisterVarCacheCallback(BoolVarChanged, aPref, data);
return NS_OK;
}
+template<MemoryOrdering Order>
+static void
+AtomicBoolVarChanged(const char* aPref, void* aClosure)
+{
+ CacheData* cache = static_cast<CacheData*>(aClosure);
+ *static_cast<Atomic<bool, Order>*>(cache->mCacheLocation) =
+ Preferences::GetBool(aPref, cache->mDefaultValueBool);
+}
+
+template<MemoryOrdering Order>
+/* static */ nsresult
+Preferences::AddAtomicBoolVarCache(Atomic<bool, Order>* aCache, const char* aPref, bool aDefault)
+{
+ NS_ASSERTION(aCache, "aCache must not be NULL");
+#ifdef DEBUG
+ AssertNotAlreadyCached("bool", aPref, aCache);
+#endif
+ {
+ AUTO_INSTALLING_CALLBACK();
+ *aCache = Preferences::GetBool(aPref, aDefault);
+ }
+ CacheData* data = new CacheData();
+ data->mCacheLocation = aCache;
+ data->mDefaultValueBool = aDefault;
+ CacheDataAppendElement(data);
+ RegisterVarCacheCallback(AtomicBoolVarChanged<Order>, aPref, data);
+ return NS_OK;
+}
+
static void
IntVarChanged(const char* aPref, void* aClosure)
{
CacheData* cache = static_cast<CacheData*>(aClosure);
*static_cast<int32_t*>(cache->mCacheLocation) =
Preferences::GetInt(aPref, cache->mDefaultValueInt);
}
@@ -4952,16 +4981,47 @@ Preferences::AddIntVarCache(int32_t* aCa
CacheData* data = new CacheData();
data->mCacheLocation = aCache;
data->mDefaultValueInt = aDefault;
CacheDataAppendElement(data);
RegisterVarCacheCallback(IntVarChanged, aPref, data);
return NS_OK;
}
+template<MemoryOrdering Order>
+static void
+AtomicIntVarChanged(const char* aPref, void* aClosure)
+{
+ CacheData* cache = static_cast<CacheData*>(aClosure);
+ *static_cast<Atomic<int32_t, Order>*>(cache->mCacheLocation) =
+ Preferences::GetInt(aPref, cache->mDefaultValueUint);
+}
+
+template<MemoryOrdering Order>
+/* static */ nsresult
+Preferences::AddAtomicIntVarCache(Atomic<int32_t, Order>* aCache,
+ const char* aPref,
+ int32_t aDefault)
+{
+ NS_ASSERTION(aCache, "aCache must not be NULL");
+#ifdef DEBUG
+ AssertNotAlreadyCached("int", aPref, aCache);
+#endif
+ {
+ AUTO_INSTALLING_CALLBACK();
+ *aCache = Preferences::GetInt(aPref, aDefault);
+ }
+ CacheData* data = new CacheData();
+ data->mCacheLocation = aCache;
+ data->mDefaultValueUint = aDefault;
+ CacheDataAppendElement(data);
+ RegisterVarCacheCallback(AtomicIntVarChanged<Order>, aPref, data);
+ return NS_OK;
+}
+
static void
UintVarChanged(const char* aPref, void* aClosure)
{
CacheData* cache = static_cast<CacheData*>(aClosure);
*static_cast<uint32_t*>(cache->mCacheLocation) =
Preferences::GetUint(aPref, cache->mDefaultValueUint);
}
@@ -5012,20 +5072,30 @@ Preferences::AddAtomicUintVarCache(Atomi
CacheData* data = new CacheData();
data->mCacheLocation = aCache;
data->mDefaultValueUint = aDefault;
CacheDataAppendElement(data);
RegisterVarCacheCallback(AtomicUintVarChanged<Order>, aPref, data);
return NS_OK;
}
-// Since the definition of this template function is not in a header file, we
+// Since the definition of template functions is not in a header file, we
// need to explicitly specify the instantiations that are required. Currently
// only the order=Relaxed variant is needed.
template nsresult
+Preferences::AddAtomicBoolVarCache(Atomic<bool, Relaxed>*,
+ const char*,
+ bool);
+
+template nsresult
+Preferences::AddAtomicIntVarCache(Atomic<int32_t, Relaxed>*,
+ const char*,
+ int32_t);
+
+template nsresult
Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Relaxed>*,
const char*,
uint32_t);
static void
FloatVarChanged(const char* aPref, void* aClosure)
{
CacheData* cache = static_cast<CacheData*>(aClosure);
--- a/modules/libpref/Preferences.h
+++ b/modules/libpref/Preferences.h
@@ -309,19 +309,27 @@ public:
// Adds the aVariable to cache table. |aVariable| must be a pointer for a
// static variable. The value will be modified when the pref value is changed
// but note that even if you modified it, the value isn't assigned to the
// pref.
static nsresult AddBoolVarCache(bool* aVariable,
const char* aPref,
bool aDefault = false);
+ template<MemoryOrdering Order>
+ static nsresult AddAtomicBoolVarCache(Atomic<bool, Order>* aVariable,
+ const char* aPref,
+ bool aDefault = false);
static nsresult AddIntVarCache(int32_t* aVariable,
const char* aPref,
int32_t aDefault = 0);
+ template<MemoryOrdering Order>
+ static nsresult AddAtomicIntVarCache(Atomic<int32_t, Order>* aVariable,
+ const char* aPref,
+ int32_t aDefault = 0);
static nsresult AddUintVarCache(uint32_t* aVariable,
const char* aPref,
uint32_t aDefault = 0);
template<MemoryOrdering Order>
static nsresult AddAtomicUintVarCache(Atomic<uint32_t, Order>* aVariable,
const char* aPref,
uint32_t aDefault = 0);
static nsresult AddFloatVarCache(float* aVariable,
--- a/modules/libpref/test/gtest/CallbackAndVarCacheOrder.cpp
+++ b/modules/libpref/test/gtest/CallbackAndVarCacheOrder.cpp
@@ -60,23 +60,37 @@ SetFunc(const char* aPrefName, float aVa
void
AddVarCacheFunc(bool* aVar, const char* aPrefName)
{
nsresult rv = Preferences::AddBoolVarCache(aVar, aPrefName);
ASSERT_TRUE(NS_SUCCEEDED(rv));
}
void
+AddVarCacheFunc(Atomic<bool, Relaxed>* aVar, const char* aPrefName)
+{
+ nsresult rv = Preferences::AddAtomicBoolVarCache(aVar, aPrefName);
+ ASSERT_TRUE(NS_SUCCEEDED(rv));
+}
+
+void
AddVarCacheFunc(int32_t* aVar, const char* aPrefName)
{
nsresult rv = Preferences::AddIntVarCache(aVar, aPrefName);
ASSERT_TRUE(NS_SUCCEEDED(rv));
}
void
+AddVarCacheFunc(Atomic<int32_t, Relaxed>* aVar, const char* aPrefName)
+{
+ nsresult rv = Preferences::AddAtomicIntVarCache(aVar, aPrefName);
+ ASSERT_TRUE(NS_SUCCEEDED(rv));
+}
+
+void
AddVarCacheFunc(uint32_t* aVar, const char* aPrefName)
{
nsresult rv = Preferences::AddUintVarCache(aVar, aPrefName);
ASSERT_TRUE(NS_SUCCEEDED(rv));
}
void
AddVarCacheFunc(Atomic<uint32_t, Relaxed>* aVar, const char* aPrefName)
@@ -136,21 +150,31 @@ RunTest(const char* aPrefName1, const ch
ASSERT_TRUE(closure2.mCalled);
}
TEST(CallbackAndVarCacheOrder, Bool)
{
RunTest<bool>("test_pref.bool.1", "test_pref.bool.2", false, true);
}
+TEST(CallbackAndVarCacheOrder, AtomicBool)
+{
+ RunTest<bool, Atomic<bool, Relaxed>>("test_pref.atomic_bool.1", "test_pref.atomic_bool.2", false, true);
+}
+
TEST(CallbackAndVarCacheOrder, Int)
{
RunTest<int32_t>("test_pref.int.1", "test_pref.int.2", -2, 3);
}
+TEST(CallbackAndVarCacheOrder, AtomicInt)
+{
+ RunTest<int32_t, Atomic<int32_t, Relaxed>>("test_pref.atomic_int.1", "test_pref.atomic_int.2", -3, 4);
+}
+
TEST(CallbackAndVarCacheOrder, Uint)
{
RunTest<uint32_t>("test_pref.uint.1", "test_pref.uint.2", 4u, 5u);
}
TEST(CallbackAndVarCacheOrder, AtomicUint)
{
RunTest<uint32_t, Atomic<uint32_t, Relaxed>>(