ThreadSafeValueCache added class and method descriptions

Also, changed callback prototype.
This commit is contained in:
Anthony J. Thibault 2015-12-29 17:08:17 -08:00
parent 17e6a04aa8
commit feb63772f3
2 changed files with 31 additions and 15 deletions

View file

@ -1172,21 +1172,17 @@ void Avatar::updatePalms() {
leftPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(leftPalmRotation);
rightPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(rightPalmRotation);
// update thread-safe cache values
_leftPalmRotationCache.update([&](glm::quat& value, bool hasPending, const glm::quat& pendingValue) {
value = leftPalmRotation;
return false;
// update thread-safe caches
_leftPalmRotationCache.merge([&](const glm::quat& value, bool hasPending, const glm::quat& pendingValue) {
return leftPalmRotation;
});
_rightPalmRotationCache.update([&](glm::quat& value, bool hasPending, const glm::quat& pendingValue) {
value = rightPalmRotation;
return false;
_rightPalmRotationCache.merge([&](const glm::quat& value, bool hasPending, const glm::quat& pendingValue) {
return rightPalmRotation;
});
_leftPalmPositionCache.update([&](glm::vec3& value, bool hasPending, const glm::vec3& pendingValue) {
value = leftPalmPosition;
return false;
_leftPalmPositionCache.merge([&](const glm::vec3& value, bool hasPending, const glm::vec3& pendingValue) {
return leftPalmPosition;
});
_rightPalmPositionCache.update([&](glm::vec3& value, bool hasPending, const glm::vec3& pendingValue) {
value = rightPalmPosition;
return false;
_rightPalmPositionCache.merge([&](const glm::vec3& value, bool hasPending, const glm::vec3& pendingValue) {
return rightPalmPosition;
});
}

View file

@ -13,17 +13,36 @@
#include <mutex>
// Helper class for for sharing a value type between threads.
// It allows many threads to get or set a value atomically.
// This provides cache semantics, any get will return the last set value.
//
// It also provides a mechanism for the owner of the cached value to reconcile
// the cached value with it's own internal values, via the merge method.
//
// For example: This can be used to copy values between C++ code running on the application thread
// and JavaScript which is running on a different thread.
template <typename T>
class ThreadSafeValueCache {
public:
ThreadSafeValueCache(const T& v) : _value { v }, _pending { v }, _hasPending { false } {}
// The callback function should have the following prototype.
// T func(const T& value, bool hasPending, const T& pendingValue);
// It will be called synchronously on the current thread possibly blocking it for a short time.
// it gives thread-safe access to the internal cache value, as well as the pending cache value
// that was set via the last set call. This gives the cache's owner the opportunity to update
// the cached value by resolving it with it's own internal state. The owner should then return
// the resolved value which will be atomically reflected into the cache.
template <typename F>
void update(const F& callback) {
void merge(F func) {
std::lock_guard<std::mutex> guard(_mutex);
_hasPending = callback((T&)_value, _hasPending, (const T&)_pending);
_value = func((const T&)_value, _hasPending, (const T&)_pending);
_hasPending = false;
}
// returns atomic copy of the cached value.
T get() const {
std::lock_guard<std::mutex> guard(_mutex);
if (_hasPending) {
@ -33,6 +52,7 @@ public:
}
}
// will reflect copy of value into the cache.
void set(const T& v) {
std::lock_guard<std::mutex> guard(_mutex);
_hasPending = true;