Fabric: Fixing a concurrency issue in RawProp parsing infra
Summary: Previously, we stored `keyIndex_` in a Parser object which is incorrect because it makes the parsing process thread-unsafe (the Parser is shared between parsing processes). That worked previously most of the time because we never parsed props concurrently but we actually do this in the native animation library. Reviewed By: yungsters Differential Revision: D16064557 fbshipit-source-id: 211f4301d0746e0f5126a1dcdd59f1ae9a420aa9
This commit is contained in:
Родитель
9ece5bda9b
Коммит
902541e874
|
@ -116,6 +116,12 @@ class RawProps final {
|
|||
// Case 2: Source data is represented as `folly::dynamic`.
|
||||
folly::dynamic dynamic_;
|
||||
|
||||
/*
|
||||
* The index of a prop value that was evaluated on the previous iterations of
|
||||
* calling `at()`.
|
||||
*/
|
||||
mutable int keyIndexCursor_{0};
|
||||
|
||||
/*
|
||||
* Parsed artefacts:
|
||||
* To be used by `RawPropParser`.
|
||||
|
|
|
@ -17,6 +17,8 @@ RawValue const *RawPropsParser::at(
|
|||
RawProps const &rawProps,
|
||||
RawPropsKey const &key) const {
|
||||
if (UNLIKELY(!ready_)) {
|
||||
// This is not thread-safe part; this happens only during initialization of
|
||||
// a `ComponentDescriptor` where it is actually safe.
|
||||
keys_.push_back(key);
|
||||
nameToIndex_.insert(key, size_);
|
||||
size_++;
|
||||
|
@ -24,14 +26,14 @@ RawValue const *RawPropsParser::at(
|
|||
}
|
||||
|
||||
do {
|
||||
keyIndex_++;
|
||||
rawProps.keyIndexCursor_++;
|
||||
|
||||
if (UNLIKELY(keyIndex_ >= size_)) {
|
||||
keyIndex_ = 0;
|
||||
if (UNLIKELY(rawProps.keyIndexCursor_ >= size_)) {
|
||||
rawProps.keyIndexCursor_ = 0;
|
||||
}
|
||||
} while (UNLIKELY(key != keys_[keyIndex_]));
|
||||
} while (UNLIKELY(key != keys_[rawProps.keyIndexCursor_]));
|
||||
|
||||
auto valueIndex = rawProps.keyIndexToValueIndex_[keyIndex_];
|
||||
auto valueIndex = rawProps.keyIndexToValueIndex_[rawProps.keyIndexCursor_];
|
||||
return valueIndex == kRawPropsValueIndexEmpty ? nullptr
|
||||
: &rawProps.values_[valueIndex];
|
||||
}
|
||||
|
@ -39,13 +41,14 @@ RawValue const *RawPropsParser::at(
|
|||
void RawPropsParser::postPrepare() {
|
||||
ready_ = true;
|
||||
nameToIndex_.reindex();
|
||||
// Next increment will give `0`.
|
||||
keyIndex_ = size_ - 1;
|
||||
}
|
||||
|
||||
void RawPropsParser::preparse(RawProps const &rawProps) const {
|
||||
rawProps.keyIndexToValueIndex_.resize(size_, kRawPropsValueIndexEmpty);
|
||||
|
||||
// Resetting the cursor, the next increment will give `0`.
|
||||
rawProps.keyIndexCursor_ = size_ - 1;
|
||||
|
||||
switch (rawProps.mode_) {
|
||||
case RawProps::Mode::Empty:
|
||||
return;
|
||||
|
|
|
@ -69,8 +69,6 @@ class RawPropsParser final {
|
|||
mutable better::small_vector<RawPropsKey, kNumberOfPropsPerComponentSoftCap>
|
||||
keys_{};
|
||||
mutable RawPropsKeyMap nameToIndex_{};
|
||||
|
||||
mutable int keyIndex_{0};
|
||||
mutable int size_{0};
|
||||
mutable bool ready_{false};
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче