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

use a new mutex wrapper API #27

Merged
merged 4 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion data_tamer_cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ add_library(data_tamer ${LIB_TYPE}

src/sinks/mcap_sink.cpp
${ROS2_SINK}
include/data_tamer/details/mutex.hpp

include/data_tamer/logged_value.hpp
)

Expand Down
11 changes: 9 additions & 2 deletions data_tamer_cpp/examples/T01_basic_example.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <iostream>
#include "data_tamer/data_tamer.hpp"
#include "data_tamer/details/locked_reference.hpp"
#include "data_tamer/sinks/dummy_sink.hpp"

int main()
Expand Down Expand Up @@ -35,11 +35,18 @@ int main()

// if you want to modify it in a thread-safe manner, you can modify it like this
// while ptr exists, its mutex will be locked, so make sure you destruct it as soon as you're done!
if(auto ptr = logged_float->getLockedPtr())
if(auto ptr = logged_float->getMutablePtr())
{
*ptr += 1.1f;
}

// If you want to access logged_float by reference, but you are not planning to modify its value,
// you should use getConstPtr(), instead. In this way, you will reduce mutex contention.
if(auto ptr = logged_float->getConstPtr())
{
std::cout << "logged_float = " << *ptr << "\n";
}

// You can disable a value like this
channel->setEnabled(id1, false);
// or
Expand Down
17 changes: 13 additions & 4 deletions data_tamer_cpp/include/data_tamer/channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include "data_tamer/values.hpp"
#include "data_tamer/data_sink.hpp"
#include "data_tamer/details/mutex.hpp"
#include "data_tamer/logged_value.hpp"

#include <chrono>
Expand Down Expand Up @@ -388,13 +387,23 @@ inline T LoggedValue<T>::get()
}

template <typename T>
inline LockedPtr<T> LoggedValue<T>::getLockedPtr()
inline MutablePtr<T> LoggedValue<T>::getMutablePtr()
{
if(auto channel = channel_.lock())
{
return LockedPtr<T>(&value_, &channel->writeMutex());
return MutablePtr<T>(&value_, &channel->writeMutex());
}
return LockedPtr<T>(&value_, nullptr);
return MutablePtr<T>(&value_, nullptr);
}

template <typename T>
inline ConstPtr<T> LoggedValue<T>::getConstPtr()
{
if(auto channel = channel_.lock())
{
return ConstPtr<T>(&value_, &channel->writeMutex());
}
return ConstPtr<T>(&value_, nullptr);
}

} // namespace DataTamer
149 changes: 124 additions & 25 deletions data_tamer_cpp/include/data_tamer/details/locked_reference.hpp
Original file line number Diff line number Diff line change
@@ -1,46 +1,123 @@
#pragma once

#include "data_tamer/details/mutex.hpp"
#include <utility>
#include <shared_mutex>

namespace DataTamer
using Mutex = std::shared_mutex;

/**
* @brief The ConstPtr is a wrapper to a const
* pointer that locks a mutex in the constructor
* and unlocks it in the destructor.
*/
template <typename T>
class ConstPtr
{
public:
ConstPtr(const T* obj, Mutex* mutex);
ConstPtr(const ConstPtr&) = delete;
ConstPtr& operator=(const ConstPtr&) = delete;
ConstPtr(ConstPtr&&);
ConstPtr& operator=(ConstPtr&&);
~ConstPtr();

operator bool() const;
Mutex* mutex();
const T& operator*() const;
const T* operator->() const;

private:
const T* obj_ = nullptr;
Mutex* mutex_;
};

/**
* @brief The MutablePtr is a wrapper to a
* @brief The ConstPtr is a wrapper to a
* pointer that locks a mutex in the constructor
* and unlocks it in the destructor.
* It allows the user to access the reference/pointer and modify the object.
*/
template <typename T>
class LockedPtr
class MutablePtr
{
public:
LockedPtr(T* obj, Mutex* mutex);
LockedPtr(const LockedPtr&) = delete;
LockedPtr& operator=(const LockedPtr&) = delete;
LockedPtr(LockedPtr&&);
LockedPtr& operator=(LockedPtr&&);
~LockedPtr();

/// True if the object is not nullptr
operator bool() const { return obj_ != nullptr; }
/// Return the reference
T& operator*() { return *obj_; }
/// Return the pointer
T* operator->() { return obj_; }
MutablePtr(T* obj, Mutex* mutex);
MutablePtr(const MutablePtr&) = delete;
MutablePtr& operator=(const MutablePtr&) = delete;
MutablePtr(MutablePtr&&);
MutablePtr& operator=(MutablePtr&&);
~MutablePtr();

operator bool() const;
Mutex* mutex();
T& operator*();
T* operator->();

private:
T* obj_ = nullptr;
Mutex* mutex_ = nullptr;
Mutex* mutex_;
};

//----------------------------------------------------
//----------------------------------------------------
//----------------------------------------------------

template <typename T>
inline LockedPtr<T>::LockedPtr(T* obj, Mutex* mutex) : obj_(obj), mutex_(mutex)
inline ConstPtr<T>::ConstPtr(const T* obj, Mutex* mutex) : obj_(obj), mutex_(mutex)
{
if(mutex_)
{
mutex_->lock_shared();
}
}

template <typename T>
inline ConstPtr<T>::ConstPtr(ConstPtr&& other) : obj_(other.obj_), mutex_(other.mutex_)
{}

template <typename T>
inline ConstPtr<T>& ConstPtr<T>::operator=(ConstPtr&& other)
{
mutex_ = other.mutex_;
std::swap(obj_, other.obj_);
return *this;
}

template <typename T>
inline ConstPtr<T>::~ConstPtr()
{
if(mutex_)
{
mutex_->unlock_shared();
}
}

template <typename T>
inline ConstPtr<T>::operator bool() const
{
return obj_ != nullptr;
}

template <typename T>
inline Mutex *ConstPtr<T>::mutex()
{
return mutex_;
}

template <typename T>
inline const T& ConstPtr<T>::operator*() const
{
return *obj_;
}

template <typename T>
inline const T* ConstPtr<T>::operator->() const
{
return obj_;
}

//----------------------------------------------------

template <typename T>
inline MutablePtr<T>::MutablePtr(T* obj, Mutex *mutex) : obj_(obj), mutex_(mutex)
{
if(mutex_)
{
Expand All @@ -49,26 +126,48 @@ inline LockedPtr<T>::LockedPtr(T* obj, Mutex* mutex) : obj_(obj), mutex_(mutex)
}

template <typename T>
inline LockedPtr<T>::LockedPtr(LockedPtr&& other) : mutex_(other.mutex_)
inline MutablePtr<T>::MutablePtr(MutablePtr&& other) : mutex_(other.mutex_)
{
std::swap(obj_, other.obj_);
}

template <typename T>
inline LockedPtr<T>& LockedPtr<T>::operator=(LockedPtr<T>&& other)
inline MutablePtr<T>& MutablePtr<T>::operator=(MutablePtr<T>&& other)
{
mutex_ = other.mutex_;
std::swap(obj_, other.obj_);
return *this;
}

template <typename T>
inline LockedPtr<T>::~LockedPtr()
inline MutablePtr<T>::~MutablePtr()
{
if(mutex_)
{
mutex_->unlock();
}
}

} // namespace DataTamer
template <typename T>
inline MutablePtr<T>::operator bool() const
{
return obj_ != nullptr;
}

template <typename T>
inline Mutex* MutablePtr<T>::mutex()
{
return mutex_;
}

template <typename T>
inline T& MutablePtr<T>::operator*()
{
return *obj_;
}

template <typename T>
inline T* MutablePtr<T>::operator->()
{
return obj_;
}
116 changes: 0 additions & 116 deletions data_tamer_cpp/include/data_tamer/details/mutex.hpp

This file was deleted.

Loading
Loading