| Index: src/lazy-instance.h
|
| diff --git a/src/lazy-instance.h b/src/lazy-instance.h
|
| index 09dfe2154dc2992305a0b04787d8c3cca3391193..d0893e560470ee345adbd1af45cd295b998fc610 100644
|
| --- a/src/lazy-instance.h
|
| +++ b/src/lazy-instance.h
|
| @@ -65,6 +65,9 @@
|
| // static LazyInstance<MyClass, MyCreateTrait>::type my_instance =
|
| // LAZY_INSTANCE_INITIALIZER;
|
| //
|
| +// WARNING: This implementation of LazyInstance is NOT thread-safe by default.
|
| +// See ThreadSafeInitOnceTrait declared below for that.
|
| +//
|
| // Notes for advanced users:
|
| // LazyInstance can actually be used in two different ways:
|
| //
|
| @@ -104,9 +107,17 @@ struct LeakyInstanceTrait {
|
|
|
| // Traits that define how an instance is allocated and accessed.
|
|
|
| +// TODO(kalmard): __alignof__ is only defined for GCC > 4.2. Fix alignment issue
|
| +// on MIPS with other compilers.
|
| +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2))
|
| +#define LAZY_ALIGN(x) __attribute__((aligned(__alignof__(x))))
|
| +#else
|
| +#define LAZY_ALIGN(x)
|
| +#endif
|
| +
|
| template <typename T>
|
| struct StaticallyAllocatedInstanceTrait {
|
| - typedef char StorageType[sizeof(T)];
|
| + typedef char StorageType[sizeof(T)] LAZY_ALIGN(T);
|
|
|
| static T* MutableInstance(StorageType* storage) {
|
| return reinterpret_cast<T*>(storage);
|
| @@ -118,6 +129,8 @@ struct StaticallyAllocatedInstanceTrait {
|
| }
|
| };
|
|
|
| +#undef LAZY_ALIGN
|
| +
|
|
|
| template <typename T>
|
| struct DynamicallyAllocatedInstanceTrait {
|
| @@ -151,9 +164,29 @@ struct DefaultCreateTrait {
|
| };
|
|
|
|
|
| +struct ThreadSafeInitOnceTrait {
|
| + template <typename Function, typename Storage>
|
| + static void Init(OnceType* once, Function function, Storage storage) {
|
| + CallOnce(once, function, storage);
|
| + }
|
| +};
|
| +
|
| +
|
| +// Initialization trait for users who don't care about thread-safety.
|
| +struct SingleThreadInitOnceTrait {
|
| + template <typename Function, typename Storage>
|
| + static void Init(OnceType* once, Function function, Storage storage) {
|
| + if (*once == ONCE_STATE_UNINITIALIZED) {
|
| + function(storage);
|
| + *once = ONCE_STATE_DONE;
|
| + }
|
| + }
|
| +};
|
| +
|
| +
|
| // TODO(pliard): Handle instances destruction (using global destructors).
|
| template <typename T, typename AllocationTrait, typename CreateTrait,
|
| - typename DestroyTrait /* not used yet. */ >
|
| + typename InitOnceTrait, typename DestroyTrait /* not used yet. */>
|
| struct LazyInstanceImpl {
|
| public:
|
| typedef typename AllocationTrait::StorageType StorageType;
|
| @@ -164,7 +197,12 @@ struct LazyInstanceImpl {
|
| }
|
|
|
| void Init() const {
|
| - CallOnce(&once_, &InitInstance, &storage_);
|
| + InitOnceTrait::Init(
|
| + &once_,
|
| + // Casts to void* are needed here to avoid breaking strict aliasing
|
| + // rules.
|
| + reinterpret_cast<void(*)(void*)>(&InitInstance), // NOLINT
|
| + reinterpret_cast<void*>(&storage_));
|
| }
|
|
|
| public:
|
| @@ -180,35 +218,40 @@ struct LazyInstanceImpl {
|
|
|
| mutable OnceType once_;
|
| // Note that the previous field, OnceType, is an AtomicWord which guarantees
|
| - // the correct alignment of the storage field below.
|
| + // 4-byte alignment of the storage field below. If compiling with GCC (>4.2),
|
| + // the LAZY_ALIGN macro above will guarantee correctness for any alignment.
|
| mutable StorageType storage_;
|
| };
|
|
|
|
|
| template <typename T,
|
| typename CreateTrait = DefaultConstructTrait<T>,
|
| + typename InitOnceTrait = SingleThreadInitOnceTrait,
|
| typename DestroyTrait = LeakyInstanceTrait<T> >
|
| struct LazyStaticInstance {
|
| - typedef LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>, CreateTrait,
|
| - DestroyTrait> type;
|
| + typedef LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>,
|
| + CreateTrait, InitOnceTrait, DestroyTrait> type;
|
| };
|
|
|
|
|
| template <typename T,
|
| typename CreateTrait = DefaultConstructTrait<T>,
|
| + typename InitOnceTrait = SingleThreadInitOnceTrait,
|
| typename DestroyTrait = LeakyInstanceTrait<T> >
|
| struct LazyInstance {
|
| // A LazyInstance is a LazyStaticInstance.
|
| - typedef typename LazyStaticInstance<T, CreateTrait, DestroyTrait>::type type;
|
| + typedef typename LazyStaticInstance<T, CreateTrait, InitOnceTrait,
|
| + DestroyTrait>::type type;
|
| };
|
|
|
|
|
| template <typename T,
|
| typename CreateTrait = DefaultConstructTrait<T>,
|
| + typename InitOnceTrait = SingleThreadInitOnceTrait,
|
| typename DestroyTrait = LeakyInstanceTrait<T> >
|
| struct LazyDynamicInstance {
|
| - typedef LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>, CreateTrait,
|
| - DestroyTrait> type;
|
| + typedef LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>,
|
| + CreateTrait, InitOnceTrait, DestroyTrait> type;
|
| };
|
|
|
| } } // namespace v8::internal
|
|
|