Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch to use a shared lock with upgrade instead of only a unique lock for message_mutex_ #101

Merged
merged 1 commit into from
Apr 21, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions tf2_ros/include/tf2_ros/message_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ class MessageFilter : public MessageFilterBase, public message_filters::SimpleFi
*/
void clear()
{
boost::mutex::scoped_lock lock(messages_mutex_);
boost::unique_lock< boost::shared_mutex > unique_lock(messages_mutex_);

TF2_ROS_MESSAGEFILTER_DEBUG("%s", "Cleared");

Expand Down Expand Up @@ -359,7 +359,7 @@ class MessageFilter : public MessageFilterBase, public message_filters::SimpleFi
}
}

boost::mutex::scoped_lock lock(messages_mutex_);

// We can transform already
if (info.success_count == expected_success_count_)
{
Expand All @@ -370,6 +370,9 @@ class MessageFilter : public MessageFilterBase, public message_filters::SimpleFi
// If this message is about to push us past our queue size, erase the oldest message
if (queue_size_ != 0 && message_count_ + 1 > queue_size_)
{
// While we're using the reference keep a shared lock on the messages.
boost::shared_lock< boost::shared_mutex > shared_lock(messages_mutex_);

++dropped_message_count_;
const MessageInfo& front = messages_.front();
TF2_ROS_MESSAGEFILTER_DEBUG("Removed oldest message because buffer is full, count now %d (frame_id=%s, stamp=%f)", message_count_,
Expand All @@ -383,13 +386,20 @@ class MessageFilter : public MessageFilterBase, public message_filters::SimpleFi
}

messageDropped(front.event, filter_failure_reasons::Unknown);

// Unlock the shared lock and get a unique lock. Upgradeable lock is used in transformable.
// There can only be one upgrade lock. It's important the cancelTransformableRequest not deadlock with transformable.
// They both require the transformable_requests_mutex_ in BufferCore.
shared_lock.unlock();
// There is a very slight race condition if an older message arrives in this gap.
boost::unique_lock< boost::shared_mutex > unique_lock(messages_mutex_);
messages_.pop_front();
--message_count_;
--message_count_;
}

// Add the message to our list
info.event = evt;
// Lock access to the messages_ before modifying them.
boost::unique_lock< boost::shared_mutex > unique_lock(messages_mutex_);
messages_.push_back(info);
++message_count_;
}
Expand Down Expand Up @@ -456,7 +466,7 @@ class MessageFilter : public MessageFilterBase, public message_filters::SimpleFi
{
namespace mt = ros::message_traits;

boost::mutex::scoped_lock lock(messages_mutex_);
boost::upgrade_lock< boost::shared_mutex > lock(messages_mutex_);

// find the message this request is associated with
typename L_MessageInfo::iterator msg_it = messages_.begin();
Expand Down Expand Up @@ -519,6 +529,8 @@ class MessageFilter : public MessageFilterBase, public message_filters::SimpleFi
can_transform = false;
}

// We will be mutating messages now, require unique lock
boost::upgrade_to_unique_lock< boost::shared_mutex > uniqueLock(lock);
if (can_transform)
{
TF2_ROS_MESSAGEFILTER_DEBUG("Message ready in frame %s at time %.3f, count now %d", frame_id.c_str(), stamp.toSec(), message_count_ - 1);
Expand Down Expand Up @@ -678,7 +690,7 @@ class MessageFilter : public MessageFilterBase, public message_filters::SimpleFi
typedef std::list<MessageInfo> L_MessageInfo;
L_MessageInfo messages_;
uint32_t message_count_; ///< The number of messages in the list. Used because <container>.size() may have linear cost
boost::mutex messages_mutex_; ///< The mutex used for locking message list operations
boost::shared_mutex messages_mutex_; ///< The mutex used for locking message list operations
uint32_t expected_success_count_;

bool warned_about_empty_frame_id_;
Expand Down