Skip to content

Commit

Permalink
curve: Fix elem_ptr caching for array.
Browse files Browse the repository at this point in the history
  • Loading branch information
heinezen committed Jan 17, 2025
1 parent e61ec89 commit ebfa043
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 31 deletions.
77 changes: 58 additions & 19 deletions libopenage/curve/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class Array : event::EventEntity {
_id{id},
_idstr{idstr},
loop{loop},
last_element{} {}
last_elements{} {}

// prevent copying because it invalidates the usage of unique ids and event
// registration. If you need to copy a curve, use the sync() method.
Expand Down Expand Up @@ -260,35 +260,50 @@ class Array : event::EventEntity {
*
* mutable as hints are updated by const read-only functions.
*/
mutable std::array<typename KeyframeContainer<T>::elem_ptr, Size> last_element = {};
mutable std::array<typename KeyframeContainer<T>::elem_ptr, Size> last_elements = {};
};


template <typename T, size_t Size>
std::pair<time::time_t, T> Array<T, Size>::frame(const time::time_t &t,
const index_t index) const {
size_t &hint = this->last_element[index];
size_t frame_index = this->containers.at(index).last(t, hint);
hint = frame_index;
return this->containers.at(index).get(frame_index).make_pair();
// find elem_ptr in container to get the last keyframe
auto hint = this->last_elements[index];
auto frame_index = this->containers.at(index).last(t, hint);

// update the hint
this->last_elements[index] = frame_index;

return this->containers.at(index).get(frame_index).as_pair();
}

template <typename T, size_t Size>
std::pair<time::time_t, T> Array<T, Size>::next_frame(const time::time_t &t,
const index_t index) const {
size_t &hint = this->last_element[index];
size_t frame_index = this->containers.at(index).last(t, hint);
hint = frame_index;
return this->containers.at(index).get(frame_index + 1).make_pair();
// find elem_ptr in container to get the last keyframe with time <= t
auto hint = this->last_elements[index];
auto frame_index = this->containers.at(index).last(t, hint);

// increment the index to get the next keyframe
frame_index++;

// update the hint
this->last_elements[index] = frame_index;

return this->containers.at(index).get(frame_index).as_pair();
}

template <typename T, size_t Size>
T Array<T, Size>::at(const time::time_t &t,
const index_t index) const {
size_t &hint = this->last_element[index];
size_t frame_index = this->containers.at(index).last(t, hint);
hint = frame_index;
return this->containers.at(index).get(frame_index).val();
// find elem_ptr in container to get the last keyframe with time <= t
auto hint = this->last_elements[index];
auto e = this->containers.at(index).last(t, hint);

// update the hint
this->last_elements[index] = e;

return this->containers.at(index).get(e).val();
}

template <typename T, size_t Size>
Expand All @@ -307,7 +322,12 @@ template <typename T, size_t Size>
void Array<T, Size>::set_insert(const time::time_t &t,
const index_t index,
T value) {
this->last_element[index] = this->containers.at(index).insert_after(Keyframe{t, value}, this->last_element[index]);
// find elem_ptr in container to get the last keyframe with time <= t
auto hint = this->last_elements[index];
auto e = this->containers.at(index).insert_after(Keyframe{t, value}, hint);

// update the hint
this->last_elements[index] = e;

this->changes(t);
}
Expand All @@ -316,9 +336,23 @@ template <typename T, size_t Size>
void Array<T, Size>::set_last(const time::time_t &t,
const index_t index,
T value) {
size_t frame_index = this->containers.at(index).insert_after(Keyframe{t, value}, this->last_element[index]);
this->last_element[index] = frame_index;
this->containers.at(index).erase_after(frame_index);
// find elem_ptr in container to get the last keyframe with time <= t
auto hint = this->last_elements[index];
auto e = this->containers.at(index).last(t, hint);

// erase max one same-time value
if (this->containers.at(index).get(e).time() == t) {
e--;
}

// erase all keyframes with time > t
this->containers.at(index).erase_after(e);

// insert the new keyframe at the end
this->containers.at(index).insert_before(Keyframe{t, value}, e);

// update the hint
this->last_elements[index] = hint;

this->changes(t);
}
Expand All @@ -327,7 +361,12 @@ template <typename T, size_t Size>
void Array<T, Size>::set_replace(const time::time_t &t,
const index_t index,
T value) {
this->containers.at(index).insert_overwrite(Keyframe{t, value}, this->last_element[index]);
// find elem_ptr in container to get the last keyframe with time <= t
auto hint = this->last_elements[index];
auto e = this->containers.at(index).insert_overwrite(Keyframe{t, value}, hint);

// update the hint
this->last_elements[index] = e;

this->changes(t);
}
Expand Down
6 changes: 3 additions & 3 deletions libopenage/curve/base_curve.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2024 the openage authors. See copying.md for legal info.
// Copyright 2017-2025 the openage authors. See copying.md for legal info.

#pragma once

Expand Down Expand Up @@ -246,7 +246,7 @@ template <typename T>
std::pair<time::time_t, const T> BaseCurve<T>::frame(const time::time_t &time) const {
auto e = this->container.last(time, this->container.size());
auto elem = this->container.get(e);
return elem.make_pair();
return elem.as_pair();
}


Expand All @@ -255,7 +255,7 @@ std::pair<time::time_t, const T> BaseCurve<T>::next_frame(const time::time_t &ti
auto e = this->container.last(time, this->container.size());
e++;
auto elem = this->container.get(e);
return elem.make_pair();
return elem.as_pair();
}

template <typename T>
Expand Down
6 changes: 3 additions & 3 deletions libopenage/curve/discrete.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2024 the openage authors. See copying.md for legal info.
// Copyright 2017-2025 the openage authors. See copying.md for legal info.

#pragma once

Expand Down Expand Up @@ -80,7 +80,7 @@ std::pair<time::time_t, T> Discrete<T>::get_time(const time::time_t &time) const
this->last_element = e;

auto elem = this->container.get(e);
return std::make_pair(elem.time, elem.value);
return elem.as_pair();
}


Expand All @@ -97,7 +97,7 @@ std::optional<std::pair<time::time_t, T>> Discrete<T>::get_previous(const time::

e--;
auto elem = this->container.get(e);
return std::make_pair(elem.time(), elem.val());
return elem.as_pair();
}

} // namespace openage::curve
12 changes: 6 additions & 6 deletions libopenage/curve/keyframe.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019-2024 the openage authors. See copying.md for legal info.
// Copyright 2019-2025 the openage authors. See copying.md for legal info.

#pragma once

Expand Down Expand Up @@ -55,12 +55,12 @@ class Keyframe {
}

/**
* Get the value and timestamp of the keyframe in form of std::pair<time, value>
* @return keyframe pair
* Get a time-value pair of this keyframe.
*
* @return Keyframe time-value pair.
*/
std::pair<time::time_t, T> make_pair() const
{
return {time(), val()};
std::pair<time::time_t, T> as_pair() const {
return {this->timestamp, this->value};
}

public:
Expand Down

0 comments on commit ebfa043

Please sign in to comment.