Skip to content

Commit

Permalink
Tests and doc for the Threads module
Browse files Browse the repository at this point in the history
  • Loading branch information
cbritopacheco committed Feb 13, 2025
1 parent 2aebaff commit f97d477
Show file tree
Hide file tree
Showing 13 changed files with 1,101 additions and 30 deletions.
35 changes: 35 additions & 0 deletions src/Rodin/Alert/MemberFunctionException.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,51 @@

namespace Rodin::Alert
{
/**
* @brief Exception type for errors occurring in member functions.
*
* This exception class is used to capture errors in member functions,
* providing context about the class and function in which the exception
* occurred.
*
* @tparam T The type of the class where the member function resides.
* @tparam FuncName The type used to represent the function name.
*/
template <class T, class FuncName>
class MemberFunctionException : public Exception
{
public:
/// Alias for the parent exception type.
using Parent = Exception;

/**
* @brief Constructs a MemberFunctionException.
*
* This constructor formats an error message that includes the name of
* the member function and the class where the exception occurred.
*
* @param cls An instance of the class where the error occurred. (Unused
* directly, but used to deduce the class type.)
* @param funcName The name of the member function in which the error
* occurred.
*/
MemberFunctionException(const T&, const FuncName& funcName)
{
const auto& className = boost::typeindex::type_id_with_cvr<T>().pretty_name();
*this << "In member function " << Identifier::Function(funcName)
<< " of class " << Identifier::Class(className) << ": ";
}

/**
* @brief Raises the exception.
*
* Calls the parent exception's raise() method to propagate the
* exception.
*/
virtual void raise() const override
{
Parent::raise();
}
};
}

Expand Down
29 changes: 27 additions & 2 deletions src/Rodin/FlatSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,22 @@

namespace Rodin
{
/**
* @brief Functor for comparing two IndexSet objects for equality.
*
* This functor defines an operator() that compares two IndexSet objects.
* Two sets are considered equal if they have the same size and all corresponding
* elements are equal.
*/
struct IndexSetEquality
{
inline
/**
* @brief Compares two IndexSet objects for equality.
*
* @param lhs The left-hand side IndexSet.
* @param rhs The right-hand side IndexSet.
* @return true if both IndexSet objects are equal, false otherwise.
*/
bool operator()(const IndexSet& lhs, const IndexSet& rhs) const
{
if (lhs.size() != rhs.size())
Expand All @@ -23,9 +36,20 @@ namespace Rodin
}
};

/**
* @brief Functor for computing a hash value for an IndexSet.
*
* This functor defines an operator() that computes a hash value for an IndexSet
* by combining the hash values of its elements.
*/
struct IndexSetHash
{
inline
/**
* @brief Computes the hash value for the given IndexSet.
*
* @param arr The IndexSet for which to compute the hash.
* @return A size_t hash value representing the IndexSet.
*/
size_t operator()(const IndexSet& arr) const
{
size_t seed = 0;
Expand All @@ -34,4 +58,5 @@ namespace Rodin
}
};
}

#endif
129 changes: 121 additions & 8 deletions src/Rodin/Threads/Mutable.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,104 @@

namespace Rodin::Threads
{
/**
* @brief A thread-safe mutable wrapper for a resource.
*
* The Mutable class encapsulates a resource and provides both read and write access
* with optional thread-safety. When RODIN_THREAD_SAFE is defined, all modifying and
* accessing operations are protected by a lock of type Lock (defaulting to Mutex).
*
* @tparam Resource The type of the resource to be encapsulated.
* @tparam Lock The type of the lock to use for thread-safety (default is Mutex).
*/
template <class Resource, class Lock = Mutex>
class Mutable
{
public:
/**
* @brief Default constructor.
*
* Constructs an empty Mutable object.
*/
constexpr
Mutable()
{}

/**
* @brief Constructs a Mutable object from a const reference.
*
* @param resource The resource to be encapsulated.
*/
constexpr
Mutable(const Resource& resource)
: m_resource(resource)
{}

/**
* @brief Constructs a Mutable object by moving a resource.
*
* @param resource The resource to be encapsulated.
*/
constexpr
Mutable(Resource&& resource)
: m_resource(std::move(resource))
{}

/**
* @brief Move constructor.
*
* Transfers the encapsulated resource from another Mutable object.
*
* @param other The Mutable object to move from.
*/
constexpr
Mutable(Mutable&& other)
: m_resource(std::move(other.m_resource))
{}

/**
* @brief Copy constructor.
*
* Copies the encapsulated resource from another Mutable object.
*
* @param other The Mutable object to copy from.
*/
constexpr
Mutable(const Mutable& other)
: m_resource(other.m_resource)
{}

/**
* @brief Assignment operator from a Resource.
*
* Assigns a new value to the encapsulated resource.
* In thread-safe builds, the assignment is performed under lock protection.
*
* @param resource The new value to assign to the resource.
* @return A reference to this Mutable object.
*/
constexpr
Mutable& operator=(const Resource& resource)
{
#ifdef RODIN_THREAD_SAFE
lock();
m_resource = resource;
unlock();
#else
m_resource = resource;
#endif
return *this;
}

/**
* @brief Move assignment operator from a Resource.
*
* Moves a new value into the encapsulated resource.
* In thread-safe builds, the assignment is performed under lock protection.
*
* @param resource The resource to move into this object.
* @return A reference to this Mutable object.
*/
constexpr
Mutable& operator=(Resource&& resource)
{
Expand All @@ -59,6 +118,15 @@ namespace Rodin::Threads
return *this;
}

/**
* @brief Copy assignment operator.
*
* Assigns the resource from another Mutable object.
* In thread-safe builds, the assignment is performed under lock protection.
*
* @param other The Mutable object to copy from.
* @return A reference to this Mutable object.
*/
constexpr
Mutable& operator=(const Mutable& other)
{
Expand All @@ -75,6 +143,15 @@ namespace Rodin::Threads
return *this;
}

/**
* @brief Move assignment operator.
*
* Transfers the resource from another Mutable object into this one.
* In thread-safe builds, the assignment is performed under lock protection.
*
* @param other The Mutable object to move from.
* @return A reference to this Mutable object.
*/
constexpr
Mutable& operator=(Mutable&& other)
{
Expand All @@ -90,32 +167,58 @@ namespace Rodin::Threads
return *this;
}

inline
/**
* @brief Provides non-const (write) access to the encapsulated resource.
*
* @return A reference to the resource.
*/
constexpr
Resource& write()
{
return m_resource;
}

inline
/**
* @brief Provides read-only access to the encapsulated resource.
*
* @return A const reference to the resource.
*/
constexpr
const Resource& read() const
{
return m_resource;
}

/**
* @brief Executes a callable with read-only access to the resource.
*
* The callable is invoked with a const reference to the resource.
* Note: The parameter name for the callable is intentionally omitted.
*
* @tparam F The type of the callable.
* @param f The callable to execute.
* @return A reference to this Mutable object.
*/
template <class F>
inline
constexpr
Mutable& read(F&&) const
Mutable& read(F&& f) const
{
static_assert(std::is_invocable_v<F, const Resource&>);
f(m_resource);
return *this;
return const_cast<Mutable&>(*this);
}

/**
* @brief Executes a callable with write access to the resource.
*
* The callable is invoked with a non-const reference to the resource.
* In thread-safe builds, the operation is performed under lock protection.
*
* @tparam F The type of the callable.
* @param f The callable to execute.
* @return A reference to this Mutable object.
*/
template <class F>
inline
constexpr
Mutable& write(F&& f)
{
Expand All @@ -132,14 +235,22 @@ namespace Rodin::Threads

#ifdef RODIN_THREAD_SAFE
protected:
inline
/**
* @brief Acquires the lock for exclusive access.
*
* This function is used internally to protect write operations.
*/
constexpr
void lock()
{
m_lock.lock();
}

inline
/**
* @brief Releases the exclusive lock.
*
* This function is used internally after write operations are completed.
*/
constexpr
void unlock()
{
Expand All @@ -149,8 +260,10 @@ namespace Rodin::Threads

private:
#ifdef RODIN_THREAD_SAFE
/// The lock used to ensure thread-safety.
Lock m_lock;
#endif
/// The encapsulated resource.
Resource m_resource;
};
}
Expand Down
6 changes: 6 additions & 0 deletions src/Rodin/Threads/Mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@

namespace Rodin::Threads
{
/**
* @brief Alias for std::mutex.
*
* This alias defines Mutex as an alternative name for std::mutex, which is
* used throughout Rodin for mutual exclusion in multithreaded contexts.
*/
using Mutex = std::mutex;
}

Expand Down
Loading

0 comments on commit f97d477

Please sign in to comment.