Removed redundant 'Bloom' namespace from entire codebase

This commit is contained in:
Nav
2023-08-13 15:47:51 +01:00
parent 0935ba65cf
commit 5896306f1a
555 changed files with 6254 additions and 6510 deletions

View File

@@ -5,109 +5,106 @@
#include <optional>
#include <set>
namespace Bloom
/**
* Simple bidirectional map
*
* This should only be used for small maps, with small elements (enums, string literals, etc).
*
* TODO: This needs some work - was written as a quick implementation with minimal requirements.
* TODO: Add support for inserting/deleting elements (outside of construction).
*
* @tparam TypeA
* @tparam TypeB
*/
template<typename TypeA, typename TypeB>
class BiMap
{
/**
* Simple bidirectional map
*
* This should only be used for small maps, with small elements (enums, string literals, etc).
*
* TODO: This needs some work - was written as a quick implementation with minimal requirements.
* TODO: Add support for inserting/deleting elements (outside of construction).
*
* @tparam TypeA
* @tparam TypeB
*/
template<typename TypeA, typename TypeB>
class BiMap
{
public:
BiMap(std::initializer_list<std::pair<TypeA, TypeB>> elements) {
for (auto it = elements.begin(); it != elements.end(); ++it) {
this->map.insert(std::pair<TypeA, TypeB>{it->first, it->second});
this->flippedMap.insert(std::pair<TypeB, TypeA>(it->second, it->first));
}
public:
BiMap(std::initializer_list<std::pair<TypeA, TypeB>> elements) {
for (auto it = elements.begin(); it != elements.end(); ++it) {
this->map.insert(std::pair<TypeA, TypeB>{it->first, it->second});
this->flippedMap.insert(std::pair<TypeB, TypeA>(it->second, it->first));
}
}
bool contains(const TypeA& key) const {
return this->map.find(key) != this->map.end();
}
bool contains(const TypeB& key) const {
return this->flippedMap.find(key) != this->flippedMap.end();
}
auto find(const TypeA& key) const {
const auto valueIt = this->map.find(key);
return valueIt != this->map.end() ? std::optional(valueIt) : std::nullopt;
}
auto find(const TypeB& key) const {
const auto valueIt = this->flippedMap.find(key);
return valueIt != this->flippedMap.end() ? std::optional(valueIt) : std::nullopt;
}
std::optional<TypeB> valueAt(const TypeA& key) const {
std::optional<TypeB> output;
const auto valueIt = this->map.find(key);
if (valueIt != this->map.end()) {
output = valueIt->second;
}
bool contains(const TypeA& key) const {
return this->map.find(key) != this->map.end();
return output;
}
std::optional<TypeA> valueAt(const TypeB& key) const {
std::optional<TypeA> output;
const auto valueIt = this->flippedMap.find(key);
if (valueIt != this->flippedMap.end()) {
output = valueIt->second;
}
bool contains(const TypeB& key) const {
return this->flippedMap.find(key) != this->flippedMap.end();
return output;
}
const TypeB& at(const TypeA& key) const {
return this->map.at(key);
}
const TypeA& at(const TypeB& key) const {
return this->flippedMap.at(key);
}
[[nodiscard]] std::unordered_map<TypeA, TypeB> getMap() const {
return this->map;
}
[[nodiscard]] std::set<TypeB> getKeys() const {
auto keys = std::set<TypeB>();
for (const auto& [key, value] : this->map) {
keys.insert(key);
}
auto find(const TypeA& key) const {
const auto valueIt = this->map.find(key);
return valueIt != this->map.end() ? std::optional(valueIt) : std::nullopt;
return keys;
}
[[nodiscard]] std::set<TypeB> getValues() const {
auto values = std::set<TypeB>();
for (const auto& [key, value] : this->map) {
values.insert(value);
}
auto find(const TypeB& key) const {
const auto valueIt = this->flippedMap.find(key);
return valueIt != this->flippedMap.end() ? std::optional(valueIt) : std::nullopt;
}
return values;
}
std::optional<TypeB> valueAt(const TypeA& key) const {
std::optional<TypeB> output;
void insert(const std::pair<TypeA, TypeB>& pair) {
auto insertResultPair = this->map.insert(pair);
this->flippedMap.insert(std::pair<TypeB, TypeA>(pair.second, pair.first));
}
const auto valueIt = this->map.find(key);
if (valueIt != this->map.end()) {
output = valueIt->second;
}
return output;
}
std::optional<TypeA> valueAt(const TypeB& key) const {
std::optional<TypeA> output;
const auto valueIt = this->flippedMap.find(key);
if (valueIt != this->flippedMap.end()) {
output = valueIt->second;
}
return output;
}
const TypeB& at(const TypeA& key) const {
return this->map.at(key);
}
const TypeA& at(const TypeB& key) const {
return this->flippedMap.at(key);
}
[[nodiscard]] std::unordered_map<TypeA, TypeB> getMap() const {
return this->map;
}
[[nodiscard]] std::set<TypeB> getKeys() const {
auto keys = std::set<TypeB>();
for (const auto& [key, value] : this->map) {
keys.insert(key);
}
return keys;
}
[[nodiscard]] std::set<TypeB> getValues() const {
auto values = std::set<TypeB>();
for (const auto& [key, value] : this->map) {
values.insert(value);
}
return values;
}
void insert(const std::pair<TypeA, TypeB>& pair) {
auto insertResultPair = this->map.insert(pair);
this->flippedMap.insert(std::pair<TypeB, TypeA>(pair.second, pair.first));
}
private:
std::unordered_map<TypeA, TypeB> map = {};
std::unordered_map<TypeB, TypeA> flippedMap = {};
};
}
private:
std::unordered_map<TypeA, TypeB> map = {};
std::unordered_map<TypeB, TypeA> flippedMap = {};
};

View File

@@ -1,26 +1,23 @@
#include "ConditionVariableNotifier.hpp"
namespace Bloom
{
void ConditionVariableNotifier::notify() {
const auto lock = std::unique_lock(this->mutex);
this->notified = true;
this->conditionalVariable.notify_all();
}
void ConditionVariableNotifier::waitForNotification(std::optional<std::chrono::milliseconds> timeout) {
const auto predicate = [this] {
return this->notified;
};
auto lock = std::unique_lock(this->mutex);
if (timeout.has_value()) {
this->conditionalVariable.wait_for(lock, timeout.value(), predicate);
} else {
this->conditionalVariable.wait(lock, predicate);
}
this->notified = false;
}
void ConditionVariableNotifier::notify() {
const auto lock = std::unique_lock(this->mutex);
this->notified = true;
this->conditionalVariable.notify_all();
}
void ConditionVariableNotifier::waitForNotification(std::optional<std::chrono::milliseconds> timeout) {
const auto predicate = [this] {
return this->notified;
};
auto lock = std::unique_lock(this->mutex);
if (timeout.has_value()) {
this->conditionalVariable.wait_for(lock, timeout.value(), predicate);
} else {
this->conditionalVariable.wait(lock, predicate);
}
this->notified = false;
}

View File

@@ -7,40 +7,37 @@
#include "NotifierInterface.hpp"
namespace Bloom
/**
* The ConditionVariableNotifier class is an implementation of the NotifierInterface, using an
* std::condition_variable.
*/
class ConditionVariableNotifier: public NotifierInterface
{
/**
* The ConditionVariableNotifier class is an implementation of the NotifierInterface, using an
* std::condition_variable.
public:
ConditionVariableNotifier() = default;
~ConditionVariableNotifier() override = default;
/*
* ConditionVariableNotifier objects should not be copied.
*/
class ConditionVariableNotifier: public NotifierInterface
{
public:
ConditionVariableNotifier() = default;
~ConditionVariableNotifier() override = default;
ConditionVariableNotifier(ConditionVariableNotifier& other) = delete;
ConditionVariableNotifier& operator = (ConditionVariableNotifier& other) = delete;
/*
* ConditionVariableNotifier objects should not be copied.
*/
ConditionVariableNotifier(ConditionVariableNotifier& other) = delete;
ConditionVariableNotifier& operator = (ConditionVariableNotifier& other) = delete;
/*
* TODO: Implement this.
*/
ConditionVariableNotifier(ConditionVariableNotifier&& other) noexcept = delete;
ConditionVariableNotifier& operator = (ConditionVariableNotifier&& other) = delete;
/*
* TODO: Implement this.
*/
ConditionVariableNotifier(ConditionVariableNotifier&& other) noexcept = delete;
ConditionVariableNotifier& operator = (ConditionVariableNotifier&& other) = delete;
void notify() override;
void notify() override;
/**
* Blocks until the contained std::conditional_variable is notified.
*/
void waitForNotification(std::optional<std::chrono::milliseconds> timeout = std::nullopt);
/**
* Blocks until the contained std::conditional_variable is notified.
*/
void waitForNotification(std::optional<std::chrono::milliseconds> timeout = std::nullopt);
private:
std::mutex mutex;
std::condition_variable conditionalVariable;
bool notified = false;
};
}
private:
std::mutex mutex;
std::condition_variable conditionalVariable;
bool notified = false;
};

View File

@@ -2,13 +2,11 @@
#include <type_traits>
namespace Bloom {
template<typename Type>
requires std::is_pointer<Type>::value
struct DereferenceLessComparator
{
constexpr bool operator () (const Type& lhs, const Type& rhs) const {
return *lhs < *rhs;
}
};
}
template<typename Type>
requires std::is_pointer<Type>::value
struct DereferenceLessComparator
{
constexpr bool operator () (const Type& lhs, const Type& rhs) const {
return *lhs < *rhs;
}
};

View File

@@ -6,21 +6,18 @@
#include "src/Targets/TargetMemory.hpp"
namespace Bloom
class EnumToStringMappings
{
class EnumToStringMappings
{
public:
static const inline BiMap<Targets::TargetMemoryType, QString> targetMemoryTypes = {
{Targets::TargetMemoryType::RAM, "ram"},
{Targets::TargetMemoryType::EEPROM, "eeprom"},
{Targets::TargetMemoryType::FLASH, "flash"},
{Targets::TargetMemoryType::OTHER, "other"},
};
static const inline BiMap<Targets::TargetMemoryEndianness, QString> targetMemoryEndianness = {
{Targets::TargetMemoryEndianness::LITTLE, "little"},
{Targets::TargetMemoryEndianness::BIG, "big"},
};
public:
static const inline BiMap<Targets::TargetMemoryType, QString> targetMemoryTypes = {
{Targets::TargetMemoryType::RAM, "ram"},
{Targets::TargetMemoryType::EEPROM, "eeprom"},
{Targets::TargetMemoryType::FLASH, "flash"},
{Targets::TargetMemoryType::OTHER, "other"},
};
}
static const inline BiMap<Targets::TargetMemoryEndianness, QString> targetMemoryEndianness = {
{Targets::TargetMemoryEndianness::LITTLE, "little"},
{Targets::TargetMemoryEndianness::BIG, "big"},
};
};

View File

@@ -7,71 +7,68 @@
#include "src/Exceptions/Exception.hpp"
namespace Bloom
{
using Exceptions::Exception;
using Exceptions::Exception;
EpollInstance::EpollInstance() {
this->fileDescriptor = ::epoll_create(1);
EpollInstance::EpollInstance() {
this->fileDescriptor = ::epoll_create(1);
if (this->fileDescriptor < 0) {
throw Exception(
"Failed to create epoll instance - error number " + std::to_string(errno)
+ " returned."
);
}
}
void EpollInstance::addEntry(int fileDescriptor, std::uint16_t eventMask) {
struct ::epoll_event event = {
.events = eventMask,
.data = {
.fd = fileDescriptor
}
};
if (::epoll_ctl(this->fileDescriptor.value(), EPOLL_CTL_ADD, fileDescriptor, &event) != 0) {
throw Exception(
"Failed to add entry to epoll instance - error number " + std::to_string(errno) + " returned."
);
}
}
void EpollInstance::removeEntry(int fileDescriptor) {
if (::epoll_ctl(this->fileDescriptor.value(), EPOLL_CTL_DEL, fileDescriptor, NULL) != 0) {
throw Exception(
"Failed to remove entry from epoll instance - error number " + std::to_string(errno)
+ " returned."
);
}
}
std::optional<int> EpollInstance::waitForEvent(std::optional<std::chrono::milliseconds> timeout) const {
std::array<struct epoll_event, 1> events = {};
const auto eventCount = ::epoll_wait(
this->fileDescriptor.value(),
events.data(),
1,
timeout.has_value() ? static_cast<int>(timeout->count()) : -1
if (this->fileDescriptor < 0) {
throw Exception(
"Failed to create epoll instance - error number " + std::to_string(errno)
+ " returned."
);
if (eventCount < 1) {
return std::nullopt;
}
return static_cast<int>(events.at(0).data.fd);
}
EpollInstance::EpollInstance(EpollInstance&& other) noexcept
: fileDescriptor(other.fileDescriptor)
{
other.fileDescriptor = std::nullopt;
}
EpollInstance::~EpollInstance() noexcept {
if (this->fileDescriptor.value_or(-1) >= 0) {
::close(this->fileDescriptor.value());
}
}
}
void EpollInstance::addEntry(int fileDescriptor, std::uint16_t eventMask) {
struct ::epoll_event event = {
.events = eventMask,
.data = {
.fd = fileDescriptor
}
};
if (::epoll_ctl(this->fileDescriptor.value(), EPOLL_CTL_ADD, fileDescriptor, &event) != 0) {
throw Exception(
"Failed to add entry to epoll instance - error number " + std::to_string(errno) + " returned."
);
}
}
void EpollInstance::removeEntry(int fileDescriptor) {
if (::epoll_ctl(this->fileDescriptor.value(), EPOLL_CTL_DEL, fileDescriptor, NULL) != 0) {
throw Exception(
"Failed to remove entry from epoll instance - error number " + std::to_string(errno)
+ " returned."
);
}
}
std::optional<int> EpollInstance::waitForEvent(std::optional<std::chrono::milliseconds> timeout) const {
std::array<struct epoll_event, 1> events = {};
const auto eventCount = ::epoll_wait(
this->fileDescriptor.value(),
events.data(),
1,
timeout.has_value() ? static_cast<int>(timeout->count()) : -1
);
if (eventCount < 1) {
return std::nullopt;
}
return static_cast<int>(events.at(0).data.fd);
}
EpollInstance::EpollInstance(EpollInstance&& other) noexcept
: fileDescriptor(other.fileDescriptor)
{
other.fileDescriptor = std::nullopt;
}
EpollInstance::~EpollInstance() noexcept {
if (this->fileDescriptor.value_or(-1) >= 0) {
::close(this->fileDescriptor.value());
}
}

View File

@@ -5,62 +5,59 @@
#include <optional>
#include <chrono>
namespace Bloom
/**
* RAII wrapper for an epoll instance.
*
* See https://man7.org/linux/man-pages/man7/epoll.7.html for more on the Linux epoll API.
*/
class EpollInstance
{
public:
EpollInstance();
/**
* RAII wrapper for an epoll instance.
* Adds an entry to the epoll instance.
*
* See https://man7.org/linux/man-pages/man7/epoll.7.html for more on the Linux epoll API.
* @param fileDescriptor
* @param eventMask
*/
class EpollInstance
{
public:
EpollInstance();
void addEntry(int fileDescriptor, std::uint16_t eventMask);
/**
* Adds an entry to the epoll instance.
*
* @param fileDescriptor
* @param eventMask
*/
void addEntry(int fileDescriptor, std::uint16_t eventMask);
/**
* Removes an entry from the epoll instance.
*
* @param fileDescriptor
*/
void removeEntry(int fileDescriptor);
/**
* Removes an entry from the epoll instance.
*
* @param fileDescriptor
*/
void removeEntry(int fileDescriptor);
/**
* Waits on the epoll instance until an event occurs for any of the registered files.
*
* @param timeout
* Millisecond timeout. If not provided, no timeout will be applied and this function will block until an
* event occurs.
*
* @return
* The file descriptor of the file for which the event occurred, or std::nullopt if a timeout was reached.
*/
[[nodiscard]] std::optional<int> waitForEvent(
std::optional<std::chrono::milliseconds> timeout = std::nullopt
) const;
/**
* Waits on the epoll instance until an event occurs for any of the registered files.
*
* @param timeout
* Millisecond timeout. If not provided, no timeout will be applied and this function will block until an
* event occurs.
*
* @return
* The file descriptor of the file for which the event occurred, or std::nullopt if a timeout was reached.
*/
[[nodiscard]] std::optional<int> waitForEvent(
std::optional<std::chrono::milliseconds> timeout = std::nullopt
) const;
/*
* EpollInstance objects should not be copied.
*/
EpollInstance(EpollInstance& other) = delete;
EpollInstance& operator = (EpollInstance& other) = delete;
/*
* EpollInstance objects should not be copied.
*/
EpollInstance(EpollInstance& other) = delete;
EpollInstance& operator = (EpollInstance& other) = delete;
/*
* TODO: Implement this. For now, use the move constructor.
*/
EpollInstance& operator = (EpollInstance&& other) = delete;
/*
* TODO: Implement this. For now, use the move constructor.
*/
EpollInstance& operator = (EpollInstance&& other) = delete;
EpollInstance(EpollInstance&& other) noexcept;
~EpollInstance() noexcept;
EpollInstance(EpollInstance&& other) noexcept;
~EpollInstance() noexcept;
private:
std::optional<int> fileDescriptor;
};
}
private:
std::optional<int> fileDescriptor;
};

View File

@@ -7,49 +7,46 @@
#include "src/Exceptions/Exception.hpp"
namespace Bloom
{
using Exceptions::Exception;
using Exceptions::Exception;
EventFdNotifier::EventFdNotifier() {
this->fileDescriptor = ::eventfd(0, ::EFD_NONBLOCK);
EventFdNotifier::EventFdNotifier() {
this->fileDescriptor = ::eventfd(0, ::EFD_NONBLOCK);
if (this->fileDescriptor < 0) {
throw Exception(
"Failed to create eventfd object - error number " + std::to_string(errno)
+ " returned."
);
}
}
EventFdNotifier::EventFdNotifier(EventFdNotifier&& other) noexcept
: fileDescriptor(other.fileDescriptor)
{
other.fileDescriptor = std::nullopt;
}
EventFdNotifier::~EventFdNotifier() noexcept {
this->close();
}
void EventFdNotifier::notify() {
if (::eventfd_write(this->fileDescriptor.value(), 1) < 0) {
throw Exceptions::Exception("Failed to increment eventfd counter - error number: "
+ std::to_string(errno));
}
}
void EventFdNotifier::clear() {
::eventfd_t counter = {};
if (::eventfd_read(this->fileDescriptor.value(), &counter) < 0 && errno != EAGAIN) {
throw Exceptions::Exception("Failed to clear EventFdNotifier object - eventfd_read failed - "
"error number: " + std::to_string(errno));
}
}
void EventFdNotifier::close() {
if (this->fileDescriptor.value_or(-1) >= 0) {
::close(this->fileDescriptor.value());
}
if (this->fileDescriptor < 0) {
throw Exception(
"Failed to create eventfd object - error number " + std::to_string(errno)
+ " returned."
);
}
}
EventFdNotifier::EventFdNotifier(EventFdNotifier&& other) noexcept
: fileDescriptor(other.fileDescriptor)
{
other.fileDescriptor = std::nullopt;
}
EventFdNotifier::~EventFdNotifier() noexcept {
this->close();
}
void EventFdNotifier::notify() {
if (::eventfd_write(this->fileDescriptor.value(), 1) < 0) {
throw Exceptions::Exception("Failed to increment eventfd counter - error number: "
+ std::to_string(errno));
}
}
void EventFdNotifier::clear() {
::eventfd_t counter = {};
if (::eventfd_read(this->fileDescriptor.value(), &counter) < 0 && errno != EAGAIN) {
throw Exceptions::Exception("Failed to clear EventFdNotifier object - eventfd_read failed - "
"error number: " + std::to_string(errno));
}
}
void EventFdNotifier::close() {
if (this->fileDescriptor.value_or(-1) >= 0) {
::close(this->fileDescriptor.value());
}
}

View File

@@ -4,41 +4,38 @@
#include "NotifierInterface.hpp"
namespace Bloom
/**
* RAII wrapper for a Linux eventfd object, used to implement the NotifierInterface.
*/
class EventFdNotifier: public NotifierInterface
{
/**
* RAII wrapper for a Linux eventfd object, used to implement the NotifierInterface.
public:
EventFdNotifier();
/*
* EventNotifier objects should not be copied.
*/
class EventFdNotifier: public NotifierInterface
{
public:
EventFdNotifier();
EventFdNotifier(EventFdNotifier& other) = delete;
EventFdNotifier& operator = (EventFdNotifier& other) = delete;
/*
* EventNotifier objects should not be copied.
*/
EventFdNotifier(EventFdNotifier& other) = delete;
EventFdNotifier& operator = (EventFdNotifier& other) = delete;
/*
* TODO: Implement this. For now, use the move constructor.
*/
EventFdNotifier& operator = (EventFdNotifier&& other) = delete;
/*
* TODO: Implement this. For now, use the move constructor.
*/
EventFdNotifier& operator = (EventFdNotifier&& other) = delete;
EventFdNotifier(EventFdNotifier&& other) noexcept;
~EventFdNotifier() noexcept override;
EventFdNotifier(EventFdNotifier&& other) noexcept;
~EventFdNotifier() noexcept override;
[[nodiscard]] int getFileDescriptor() const {
return this->fileDescriptor.value();
}
[[nodiscard]] int getFileDescriptor() const {
return this->fileDescriptor.value();
}
void notify() override;
void notify() override;
void clear();
void clear();
private:
std::optional<int> fileDescriptor;
private:
std::optional<int> fileDescriptor;
void close();
};
}
void close();
};

View File

@@ -1,37 +1,34 @@
#pragma once
namespace Bloom
/**
* The NotifierInterface class describes an interface for notifying different components, within Bloom, of something
* important that has just happened.
*
* It's important to note that this interface only describes the issuing of notifications. It *does not* describe
* the listening for notifications. The listening can be defined by the implementation.
*
* For example, consider the EventFdNotifier implementation. That class is just an RAII wrapper for a Linux eventfd
* object. Notifications are recorded by incrementing the eventfd counter. And they can be listened for, using
* Linux system functions like poll(), select(), and similar.
*
* The EventListener class can hold a pointer to a NotifierInterface, where it will invoke
* NotifierInterface::notify() everytime a new event is registered on the listener.
*/
class NotifierInterface
{
public:
NotifierInterface() = default;
virtual ~NotifierInterface() noexcept = default;
NotifierInterface(NotifierInterface& other) = delete;
NotifierInterface& operator = (NotifierInterface& other) = delete;
NotifierInterface& operator = (NotifierInterface&& other) = delete;
NotifierInterface(NotifierInterface&& other) noexcept = default;
/**
* The NotifierInterface class describes an interface for notifying different components, within Bloom, of something
* important that has just happened.
*
* It's important to note that this interface only describes the issuing of notifications. It *does not* describe
* the listening for notifications. The listening can be defined by the implementation.
*
* For example, consider the EventFdNotifier implementation. That class is just an RAII wrapper for a Linux eventfd
* object. Notifications are recorded by incrementing the eventfd counter. And they can be listened for, using
* Linux system functions like poll(), select(), and similar.
*
* The EventListener class can hold a pointer to a NotifierInterface, where it will invoke
* NotifierInterface::notify() everytime a new event is registered on the listener.
* Should record a notification.
*/
class NotifierInterface
{
public:
NotifierInterface() = default;
virtual ~NotifierInterface() noexcept = default;
NotifierInterface(NotifierInterface& other) = delete;
NotifierInterface& operator = (NotifierInterface& other) = delete;
NotifierInterface& operator = (NotifierInterface&& other) = delete;
NotifierInterface(NotifierInterface&& other) noexcept = default;
/**
* Should record a notification.
*/
virtual void notify() = 0;
};
}
virtual void notify() = 0;
};

View File

@@ -3,76 +3,73 @@
#include <mutex>
#include <utility>
namespace Bloom
/**
* Wrapper for synchronised access to a resource.
*
* @tparam Type
*/
template<typename Type>
class Synchronised
{
/**
* Wrapper for synchronised access to a resource.
*
* @tparam Type
*/
template<typename Type>
class Synchronised
public:
class Accessor
{
public:
class Accessor
{
public:
constexpr Accessor(std::mutex& mutex, Type& value)
: lock(std::unique_lock(mutex))
, value(value)
{}
constexpr Type* operator -> () noexcept {
return &(this->value);
}
constexpr const Type* operator -> () const noexcept {
return &(this->value);
}
constexpr Type& operator * () noexcept {
return this->value;
}
constexpr const Type& operator * () const noexcept {
return this->value;
}
private:
std::unique_lock<std::mutex> lock;
Type& value;
};
Synchronised() = default;
explicit Synchronised(Type value)
: value(std::move(value))
constexpr Accessor(std::mutex& mutex, Type& value)
: lock(std::unique_lock(mutex))
, value(value)
{}
Accessor accessor() {
return Accessor(this->mutex, this->value);
constexpr Type* operator -> () noexcept {
return &(this->value);
}
/**
* Don't use this unless you already hold a raw (not managed by an Accessor) lock to the contained value.
*
* This should only be used in instances where you need to hold a raw lock, like in the `stop_waiting`
* predicate function for a call to std::condition_variable::wait().
*
* In all other instances, you should use Synchronised::accessor().
*
* @return
*/
Type& unsafeReference() {
constexpr const Type* operator -> () const noexcept {
return &(this->value);
}
constexpr Type& operator * () noexcept {
return this->value;
}
std::unique_lock<std::mutex> lock() {
return std::unique_lock(this->mutex);
constexpr const Type& operator * () const noexcept {
return this->value;
}
private:
Type value;
std::mutex mutex;
std::unique_lock<std::mutex> lock;
Type& value;
};
}
Synchronised() = default;
explicit Synchronised(Type value)
: value(std::move(value))
{}
Accessor accessor() {
return Accessor(this->mutex, this->value);
}
/**
* Don't use this unless you already hold a raw (not managed by an Accessor) lock to the contained value.
*
* This should only be used in instances where you need to hold a raw lock, like in the `stop_waiting`
* predicate function for a call to std::condition_variable::wait().
*
* In all other instances, you should use Synchronised::accessor().
*
* @return
*/
Type& unsafeReference() {
return this->value;
}
std::unique_lock<std::mutex> lock() {
return std::unique_lock(this->mutex);
}
private:
Type value;
std::mutex mutex;
};

View File

@@ -5,50 +5,47 @@
#include <cassert>
#include <atomic>
namespace Bloom
enum class ThreadState: std::uint8_t
{
enum class ThreadState: std::uint8_t
{
UNINITIALISED,
READY,
STOPPED,
STARTING,
SHUTDOWN_INITIATED,
};
UNINITIALISED,
READY,
STOPPED,
STARTING,
SHUTDOWN_INITIATED,
};
class Thread
{
public:
Thread() = default;
virtual ~Thread() = default;
class Thread
{
public:
Thread() = default;
virtual ~Thread() = default;
Thread(const Thread& other) = delete;
Thread(Thread&& other) = delete;
Thread(const Thread& other) = delete;
Thread(Thread&& other) = delete;
Thread& operator = (const Thread& other) = delete;
Thread& operator = (Thread&& other) = delete;
Thread& operator = (const Thread& other) = delete;
Thread& operator = (Thread&& other) = delete;
ThreadState getThreadState() {
return this->threadState;
}
ThreadState getThreadState() {
return this->threadState;
}
protected:
std::atomic<ThreadState> threadState = ThreadState::UNINITIALISED;
protected:
std::atomic<ThreadState> threadState = ThreadState::UNINITIALISED;
/**
* Disables signal interrupts on current thread.
*/
static void blockAllSignals() {
sigset_t set = {};
sigfillset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
}
/**
* Disables signal interrupts on current thread.
*/
static void blockAllSignals() {
sigset_t set = {};
sigfillset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
}
void setName(const std::string& name) {
// POSIX thread names cannot exceed 16 characters, including the terminating null byte.
assert(name.size() <= 15);
void setName(const std::string& name) {
// POSIX thread names cannot exceed 16 characters, including the terminating null byte.
assert(name.size() <= 15);
pthread_setname_np(pthread_self(), name.c_str());
}
};
}
pthread_setname_np(pthread_self(), name.c_str());
}
};

View File

@@ -2,20 +2,17 @@
#include <yaml-cpp/yaml.h>
namespace Bloom
class YamlUtilities
{
class YamlUtilities
{
public:
template <typename Type>
static bool isCastable(const YAML::Node& node) {
try {
node.as<Type>();
return true;
public:
template <typename Type>
static bool isCastable(const YAML::Node& node) {
try {
node.as<Type>();
return true;
} catch (YAML::BadConversion&) {
return false;
}
} catch (YAML::BadConversion&) {
return false;
}
};
}
}
};