added mutex to BayesTreeCliqueBase for access to cached variable and added copy/copy assignment constructors to allow for full previous functionality while adding thread safety to marginalCovariance.
parent
269dea3a24
commit
8749969977
|
@ -91,6 +91,7 @@ namespace gtsam {
|
||||||
template<class DERIVED, class FACTORGRAPH>
|
template<class DERIVED, class FACTORGRAPH>
|
||||||
size_t BayesTreeCliqueBase<DERIVED, FACTORGRAPH>::numCachedSeparatorMarginals() const
|
size_t BayesTreeCliqueBase<DERIVED, FACTORGRAPH>::numCachedSeparatorMarginals() const
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> marginalLock(cachedSeparatorMarginalMutex_);
|
||||||
if (!cachedSeparatorMarginal_)
|
if (!cachedSeparatorMarginal_)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -144,6 +145,7 @@ namespace gtsam {
|
||||||
typename BayesTreeCliqueBase<DERIVED, FACTORGRAPH>::FactorGraphType
|
typename BayesTreeCliqueBase<DERIVED, FACTORGRAPH>::FactorGraphType
|
||||||
BayesTreeCliqueBase<DERIVED, FACTORGRAPH>::separatorMarginal(
|
BayesTreeCliqueBase<DERIVED, FACTORGRAPH>::separatorMarginal(
|
||||||
Eliminate function) const {
|
Eliminate function) const {
|
||||||
|
std::lock_guard<std::mutex> marginalLock(cachedSeparatorMarginalMutex_);
|
||||||
gttic(BayesTreeCliqueBase_separatorMarginal);
|
gttic(BayesTreeCliqueBase_separatorMarginal);
|
||||||
// Check if the Separator marginal was already calculated
|
// Check if the Separator marginal was already calculated
|
||||||
if (!cachedSeparatorMarginal_) {
|
if (!cachedSeparatorMarginal_) {
|
||||||
|
@ -206,6 +208,8 @@ namespace gtsam {
|
||||||
// When a shortcut is requested, all of the shortcuts between it and the
|
// When a shortcut is requested, all of the shortcuts between it and the
|
||||||
// root are also generated. So, if this clique's cached shortcut is set,
|
// root are also generated. So, if this clique's cached shortcut is set,
|
||||||
// recursively call over all child cliques. Otherwise, it is unnecessary.
|
// recursively call over all child cliques. Otherwise, it is unnecessary.
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> marginalLock(cachedSeparatorMarginalMutex_);
|
||||||
if (cachedSeparatorMarginal_) {
|
if (cachedSeparatorMarginal_) {
|
||||||
for(derived_ptr& child: children) {
|
for(derived_ptr& child: children) {
|
||||||
child->deleteCachedShortcuts();
|
child->deleteCachedShortcuts();
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
@ -75,10 +76,28 @@ namespace gtsam {
|
||||||
/** Construct from a conditional, leaving parent and child pointers uninitialized */
|
/** Construct from a conditional, leaving parent and child pointers uninitialized */
|
||||||
BayesTreeCliqueBase(const sharedConditional& conditional) : conditional_(conditional), problemSize_(1) {}
|
BayesTreeCliqueBase(const sharedConditional& conditional) : conditional_(conditional), problemSize_(1) {}
|
||||||
|
|
||||||
|
/** Shallow copy constructor */
|
||||||
|
BayesTreeCliqueBase(const BayesTreeCliqueBase& c) : conditional_(c.conditional_), parent_(c.parent_), children(c.children), problemSize_(c.problemSize_), is_root(c.is_root) {}
|
||||||
|
|
||||||
|
/** Shallow copy assignment constructor */
|
||||||
|
BayesTreeCliqueBase& operator=(const BayesTreeCliqueBase& c) {
|
||||||
|
conditional_ = c.conditional_;
|
||||||
|
parent_ = c.parent_;
|
||||||
|
children = c.children;
|
||||||
|
problemSize_ = c.problemSize_;
|
||||||
|
is_root = c.is_root;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
/// This stores the Cached separator margnal P(S)
|
/// This stores the Cached separator marginal P(S)
|
||||||
mutable boost::optional<FactorGraphType> cachedSeparatorMarginal_;
|
mutable boost::optional<FactorGraphType> cachedSeparatorMarginal_;
|
||||||
|
/// This protects Cached seperator marginal P(S) from concurent read/writes
|
||||||
|
/// as many the functions which access it are const (hence the mutable)
|
||||||
|
/// leading to the false impression that these const functions are thread-safe
|
||||||
|
/// which is not true due to these mutable values. This is fixed by applying this mutex.
|
||||||
|
mutable std::mutex cachedSeparatorMarginalMutex_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sharedConditional conditional_;
|
sharedConditional conditional_;
|
||||||
|
@ -144,7 +163,9 @@ namespace gtsam {
|
||||||
void deleteCachedShortcuts();
|
void deleteCachedShortcuts();
|
||||||
|
|
||||||
const boost::optional<FactorGraphType>& cachedSeparatorMarginal() const {
|
const boost::optional<FactorGraphType>& cachedSeparatorMarginal() const {
|
||||||
return cachedSeparatorMarginal_; }
|
std::lock_guard<std::mutex> marginalLock(cachedSeparatorMarginalMutex_);
|
||||||
|
return cachedSeparatorMarginal_;
|
||||||
|
}
|
||||||
|
|
||||||
friend class BayesTree<DerivedType>;
|
friend class BayesTree<DerivedType>;
|
||||||
|
|
||||||
|
@ -159,7 +180,10 @@ namespace gtsam {
|
||||||
KeyVector shortcut_indices(const derived_ptr& B, const FactorGraphType& p_Cp_B) const;
|
KeyVector shortcut_indices(const derived_ptr& B, const FactorGraphType& p_Cp_B) const;
|
||||||
|
|
||||||
/** Non-recursive delete cached shortcuts and marginals - internal only. */
|
/** Non-recursive delete cached shortcuts and marginals - internal only. */
|
||||||
void deleteCachedShortcutsNonRecursive() { cachedSeparatorMarginal_ = boost::none; }
|
void deleteCachedShortcutsNonRecursive() {
|
||||||
|
std::lock_guard<std::mutex> marginalLock(cachedSeparatorMarginalMutex_);
|
||||||
|
cachedSeparatorMarginal_ = boost::none;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue