/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Referenced via macro definitions #include"mozilla/ErrorResult.h"
class PickleIterator;
namespace IPC { class Message; class MessageReader; class MessageWriter;
} // namespace IPC
namespace mozilla { namespace ipc { class IProtocol; class IPCResult; template <typename T> struct IPDLParamTraits;
} // namespace ipc
namespace dom { class ContentParent; class ContentChild; template <typename T> class MaybeDiscarded;
namespace syncedcontext {
template <size_t I> using Index = typename std::integral_constant<size_t, I>;
// We're going to use the empty base optimization for synced fields of different // sizes, so we define an empty class for that purpose. template <size_t I, size_t S> struct Empty {};
// A templated container for a synced field. I is the index and T is the type. template <size_t I, typename T> struct Field {
T mField{};
};
// SizedField is a Field with a helper to define either an "empty" field, or a // field of a given type. template <size_t I, typename T, size_t S> using SizedField = std::conditional_t<((sizeof(T) > 8) ? 8 : sizeof(T)) == S,
Field<I, T>, Empty<I, S>>;
template <typename Context> class Transaction { public: using IndexSet = EnumSet<size_t, BitSet<Context::FieldValues::count>>;
// Set a field at the given index in this `Transaction`. Creating a // `Transaction` object and setting multiple fields on it allows for // multiple mutations to be performed atomically. template <size_t I, typename U> void Set(U&& aValue) {
mValues.Get(Index<I>{}) = std::forward<U>(aValue);
mModified += I;
}
// Apply the changes from this transaction to the specified Context in all // processes. This method will call the correct `CanSet` and `DidSet` methods, // as well as move the value. // // If the target has been discarded, changes will be ignored. // // NOTE: This method mutates `this`, clearing the modified field set.
[[nodiscard]] nsresult Commit(Context* aOwner);
// Called from `ContentParent` in response to a transaction from content.
mozilla::ipc::IPCResult CommitFromIPC(const MaybeDiscarded<Context>& aOwner,
ContentParent* aSource);
// Called from `ContentChild` in response to a transaction from the parent.
mozilla::ipc::IPCResult CommitFromIPC(const MaybeDiscarded<Context>& aOwner,
uint64_t aEpoch, ContentChild* aSource);
// Apply the changes from this transaction to the specified Context WITHOUT // syncing the changes to other processes. // // Unlike `Commit`, this method will NOT call the corresponding `CanSet` or // `DidSet` methods, and can be performed when the target context is // unattached or discarded. // // NOTE: YOU PROBABLY DO NOT WANT TO USE THIS METHOD void CommitWithoutSyncing(Context* aOwner);
// You probably don't want to directly call this method - instead call // `Commit`, which will perform the necessary synchronization. // // `Validate` must be called before calling this method. void Apply(Context* aOwner, bool aFromIPC);
// Returns the set of fields which failed to validate, or an empty set if // there were no validation errors. // // NOTE: This method mutates `this` if any changes were reverted.
IndexSet Validate(Context* aOwner, ContentParent* aSource);
template <typename Base, size_t Count> class FieldValues : public Base { public: // The number of fields stored by this type. static constexpr size_t count = Count;
// The base type will define a series of `Get` methods for looking up a field // by its field index. using Base::Get;
// Calls a generic lambda with an `Index<I>` for each index less than the // field count. template <typename F> staticvoid EachIndex(F&& aCallback) {
EachIndexInner(std::make_index_sequence<count>(),
std::forward<F>(aCallback));
}
// Storage related to synchronized context fields. Contains both a tuple of // individual field values, and epoch information for field synchronization. template <typename Values> class FieldStorage { public: // Unsafely grab a reference directly to the internal values structure which // can be modified without telling other processes about the change. // // This is only sound in specific code which is already messaging other // processes, and doesn't need to worry about epochs or other properties of // field synchronization.
Values& RawValues() { return mValues; } const Values& RawValues() const { return mValues; }
// Get an individual field by index. template <size_t I> constauto& Get() const { return RawValues().Get(Index<I>{});
}
// Set the value of a field without telling other processes about the change. // // This is only sound in specific code which is already messaging other // processes, and doesn't need to worry about epochs or other properties of // field synchronization. template <size_t I, typename U> void SetWithoutSyncing(U&& aValue) {
GetNonSyncingReference<I>() = std::move(aValue);
}
// Get a reference to a field that can modify without telling other // processes about the change. // // This is only sound in specific code which is already messaging other // processes, and doesn't need to worry about epochs or other properties of // field synchronization. template <size_t I> auto& GetNonSyncingReference() { return RawValues().Get(Index<I>{});
}
// Data Members
std::array<uint64_t, Values::count> mEpochs{};
Values mValues;
};
// Alternative return type enum for `CanSet` validators which allows specifying // more behaviour. enumclass CanSetResult : uint8_t { // The set attempt is denied. This is equivalent to returning `false`.
Deny, // The set attempt is allowed. This is equivalent to returning `true`.
Allow, // The set attempt is reverted non-fatally.
Revert,
};
// Helper type traits to use concrete types rather than generic forwarding // references for the `SetXXX` methods defined on the synced context type. // // This helps avoid potential issues where someone accidentally declares an // overload of these methods with slightly different types and different // behaviours. See bug 1659520. template <typename T> struct GetFieldSetterType { using SetterArg = T;
}; template <> struct GetFieldSetterType<nsString> { using SetterArg = const nsAString&;
}; template <> struct GetFieldSetterType<nsCString> { using SetterArg = const nsACString&;
}; template <typename T> using FieldSetterType = typename GetFieldSetterType<T>::SetterArg;
// Declare a type as a synced context type. // // clazz is the name of the type being declared, and `eachfield` is a macro // which, when called with the name of the macro, will call that macro once for // each field in the synced context. #define MOZ_DECL_SYNCED_CONTEXT(clazz, eachfield) \ public: \ /* Index constants for referring to each field in generic code */ \ enum FieldIndexes { \
eachfield(MOZ_DECL_SYNCED_CONTEXT_FIELD_INDEX) SYNCED_FIELD_COUNT \
}; \
\ /* Helper for overloading methods like `CanSet` and `DidSet` */ \ template <size_t I> \ using FieldIndex = typename ::mozilla::dom::syncedcontext::Index<I>; \
\ /* Fields contain all synced fields defined by \ * `eachfield(MOZ_DECL_SYNCED_FIELD_INHERIT)`, but only those where the size \ * of the field is equal to size Size will be present. We use SizedField to \
* remove fields of the wrong size. */ template <size_t Size> \ struct Fields : eachfield(MOZ_DECL_SYNCED_FIELD_INHERIT) \
syncedcontext::Empty<SYNCED_FIELD_COUNT, Size>{}; \
\ /* Struct containing the data for all synced fields as members. We filter \ * sizes to lay out fields of size 1, then 2, then 4 and last 8 or greater. \ * This way we don't need to consider packing when defining fields, but \ * we'll just reorder them here. \
*/ struct BaseFieldValues : public Fields<1>, \ public Fields<2>, \ public Fields<4>, \ public Fields<8> { \ template <size_t I> \ auto& Get() { \ return Get(FieldIndex<I>{}); \
} \ template <size_t I> \ constauto& Get() const { \ return Get(FieldIndex<I>{}); \
} \
eachfield(MOZ_DECL_SYNCED_CONTEXT_BASE_FIELD_GETTER) \
}; \ using FieldValues = \ typename ::mozilla::dom::syncedcontext::FieldValues<BaseFieldValues, \
SYNCED_FIELD_COUNT>; \
\ protected: \ friendclass ::mozilla::dom::syncedcontext::Transaction<clazz>; \
::mozilla::dom::syncedcontext::FieldStorage<FieldValues> mFields; \
\ public: \ /* Transaction types for bulk mutations */ \ using BaseTransaction = ::mozilla::dom::syncedcontext::Transaction<clazz>; \ class Transaction final : public BaseTransaction { \ public: \
eachfield(MOZ_DECL_SYNCED_CONTEXT_TRANSACTION_SET) \
}; \
\ /* Field name getter by field index */ \ staticconstchar* FieldIndexToName(size_t aIndex) { \ switch (aIndex) { eachfield(MOZ_DECL_SYNCED_CONTEXT_INDEX_TO_NAME) } \ return""; \
} \
eachfield(MOZ_DECL_SYNCED_CONTEXT_FIELD_GETSET)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.