/* Copyright (C) 2019 * * This file is part of the osdev components suite * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifndef OSDEV_COMPONENTS_MQTT_LOCKGUARD_H #define OSDEV_COMPONENTS_MQTT_LOCKGUARD_H // std #include // osdev::components::mqtt::measurement #include "measure.h" #include "utils.h" /** * @brief Enable the lock measurements when macro MEASURE_LOCKS is defined. * If the macro is not defined the NOP versions of the measure macros are used. */ #ifdef MEASURE_LOCKS #define OSDEV_COMPONENTS_MEASURELOCK OSDEV_COMPONENTS_MEASUREMENT_MEASURE #define OSDEV_COMPONENTS_MEASURELOCK_SPECIFIC OSDEV_COMPONENTS_MEASUREMENT_MEASURE_SPECIFIC #else #define OSDEV_COMPONENTS_MEASURELOCK OSDEV_COMPONENTS_MEASUREMENT_MEASURE_NOP #define OSDEV_COMPONENTS_MEASURELOCK_SPECIFIC OSDEV_COMPONENTS_MEASUREMENT_MEASURE_SPECIFIC_NOP #endif /** * @brief Create a lockguard for a given mutex in a specific context. * @param mutexVariableName The name of the mutex. * @param mutexObtainer The mutex to lock. This can also be a function that returns a mutex. * If MEASURE_LOCKS is enabled this method uses a static histogram to record the timing of obtaining the lock for all instances. */ #define OSDEV_COMPONENTS_LOCKGUARD_OBTAINER(mutexVariableName, mutexObtainer) \ OSDEV_COMPONENTS_MEASURELOCK(LOCKGUARD, std::lock_guard Lock__Guard__##mutexVariableName##__(mutexObtainer), osdev::components::mqtt::measure_locking_tag, osdev::components::mqtt::MeasureLockingValue, 100) \ osdev::components::mqtt::apply_unused_parameters(Lock__Guard__##mutexVariableName##__); /** * @brief Create a lockguard for a given mutex in a specific context. * @param mutexVariableName The name of the mutex. * @param mutexObtainer The mutex to lock. This can also be a function that returns a mutex. * @param id The id that identifies this specific lock guard. Used for measuring timings. * If MEASURE_LOCKS is enabled this method uses a specific histogram instance to record the timing of obtaining this lock. */ #define OSDEV_COMPONENTS_LOCKGUARD_SPECIFIC_OBTAINER(mutexVariableName, mutexObtainer, id) \ OSDEV_COMPONENTS_MEASURELOCK_SPECIFIC(id, LOCKGUARD, std::lock_guard Lock__Guard__##mutexVariableName##__(mutexObtainer), osdev::components::mqtt::measure_locking_tag, osdev::components::mqtt::MeasureLockingValue, 100) \ osdev::components::mqtt::apply_unused_parameters(Lock__Guard__##mutexVariableName##__); /** * @brief Create a lockguard for a given recursive mutex in a specific context. * @param mutexVariableName The name of the mutex. * @param mutexObtainer The mutex to lock. This can also be a function that returns a mutex. * If MEASURE_LOCKS is enabled this method uses a static histogram to record the timing of obtaining the lock for all instances. */ #define OSDEV_COMPONENTS_RECURSIVELOCKGUARD_OBTAINER(mutexVariableName, mutexObtainer) \ OSDEV_COMPONENTS_MEASURELOCK(RECURSIVELOCKGUARD, std::lock_guard Lock__Guard__##mutexVariableName##__(mutexObtainer), osdev::components::mqtt::measure_locking_tag, osdev::components::mqtt::MeasureLockingValue, 100) \ osdev::components::mqtt::apply_unused_parameters(Lock__Guard__##mutexVariableName##__); /** * @brief Create a lockguard for a given recursive mutex in a specific context. * @param mutexVariableName The name of the mutex. * @param mutexObtainer The mutex to lock. This can also be a function that returns a mutex. * @param id The id that identifies this specific lock guard. Used for measuring timings. * If MEASURE_LOCKS is enabled this method uses a specific histogram instance to record the timing of obtaining this lock. */ #define OSDEV_COMPONENTS_RECURSIVELOCKGUARD_SPECIFIC_OBTAINER(mutexVariableName, mutexObtainer, id) \ OSDEV_COMPONENTS_MEASURELOCK_SPECIFIC(id, RECURSIVELOCKGUARD, std::lock_guard Lock__Guard__##mutexVariableName##__(mutexVariableName), osdev::components::mqtt::measure_locking_tag, osdev::components::mqtt::MeasureLockingValue, 100) \ osdev::components::mqtt::apply_unused_parameters(Lock__Guard__##mutexVariableName##__); /** * @brief Create a lockguard for a given bare mutex in a specific context. * @param mutexVariableName The name of the mutex. * If MEASURE_LOCKS is enabled this method uses a static histogram to record the timing of obtaining the lock for all instances. */ #define OSDEV_COMPONENTS_LOCKGUARD(mutexVariableName) \ OSDEV_COMPONENTS_LOCKGUARD_OBTAINER(mutexVariableName, mutexVariableName) /** * @brief Create a lockguard for a given bare mutex in a specific context. * @param mutexVariableName The name of the mutex. * @param id The id that identifies this specific lock guard. Used for measuring timings. * If MEASURE_LOCKS is enabled this method uses a specific histogram instance to record the timing of obtaining this lock. */ #define OSDEV_COMPONENTS_LOCKGUARD_SPECIFIC(mutexVariableName, id) \ OSDEV_COMPONENTS_LOCKGUARD_SPECIFIC_OBTAINER(mutexVariableName, mutexVariableName, id) /** * @brief Create a lockguard for a given bare recursive mutex in a specific context. * @param mutexVariableName The name of the mutex. * If MEASURE_LOCKS is enabled this method uses a static histogram to record the timing of obtaining the lock for all instances. */ #define OSDEV_COMPONENTS_RECURSIVELOCKGUARD(mutexVariableName) \ OSDEV_COMPONENTS_RECURSIVELOCKGUARD_OBTAINER(mutexVariableName, mutexVariableName) /** * @brief Create a lockguard for a given bare recursive mutex in a specific context. * @param mutexVariableName The name of the mutex. * @param id The id that identifies this specific lock guard. Used for measuring timings. * If MEASURE_LOCKS is enabled this method uses a static histogram to record the timing of obtaining the lock for all instances. */ #define OSDEV_COMPONENTS_RECURSIVELOCKGUARD_SPECIFIC(mutexVariableName, id) \ OSDEV_COMPONENTS_RECURSIVELOCKGUARD_SPECIFIC_OBTAINER(mutexVariableName, mutexVariableName, id) /** * @brief Defines the lock name that is used by the OSDEV_COMPONENTS_UNIQUELOCK_* macros */ #define OSDEV_COMPONENTS_UNIQUELOCK(mutexVariableName) Unique__Lock__##mutexVariableName##__ /** * @brief Create a uniqeue lock for a given mutex. * @param mutexVariableName The name of the mutex. * @param mutexObtainer The mutex to lock. This can also be a function that returns a mutex. * If MEASURE_LOCKS is enabled this method uses a static histogram to record the timing of obtaining the lock for all instances. */ #define OSDEV_COMPONENTS_UNIQUELOCK_CREATE_OBTAINER(mutexVariableName, mutexObtainer) \ OSDEV_COMPONENTS_MEASURELOCK(UNIQUELOCK_CREATE, std::unique_lock OSDEV_COMPONENTS_UNIQUELOCK(mutexVariableName)(mutexObtainer), osdev::components::mqtt::measure_locking_tag, osdev::components::mqtt::MeasureLockingValue, 100) \ osdev::components::mqtt::apply_unused_parameters(OSDEV_COMPONENTS_UNIQUELOCK(mutexVariableName)); /** * @brief Create a uniqeue lock for a given mutex. * @param mutexVariableName The name of the mutex. * @param mutexObtainer The mutex to lock. This can also be a function that returns mutex. * @param id The id that identifies this specific lock guard. Used for measuring timings. * If MEASURE_LOCKS is enabled this method uses a specific histogram instance to record the timing of obtaining this lock. */ #define OSDEV_COMPONENTS_UNIQUELOCK_CREATE_SPECIFIC_OBTAINER(mutexVariableName, mutexObtainer, id) \ OSDEV_COMPONENTS_MEASURELOCK_SPECIFIC(id, UNIQUELOCK_CREATE, std::unique_lock OSDEV_COMPONENTS_UNIQUELOCK(mutexVariableName)(mutexObtainer), osdev::components::mqtt::measure_locking_tag, osdev::components::mqtt::MeasureLockingValue, 100) \ osdev::components::mqtt::apply_unused_parameters(OSDEV_COMPONENTS_UNIQUELOCK(mutexVariableName)); /** * @brief Create a uniqeue lock for a given bare mutex. * @param mutexVariableName The name of the mutex. * If MEASURE_LOCKS is enabled this method uses a static histogram to record the timing of obtaining the lock for all instances. */ #define OSDEV_COMPONENTS_UNIQUELOCK_CREATE(mutexVariableName) \ OSDEV_COMPONENTS_UNIQUELOCK_CREATE_OBTAINER(mutexVariableName, mutexVariableName) /** * @brief Create a uniqeue lock for a given bare mutex. * @param mutexVariableName The name of the mutex. * @param id The id that identifies this specific unique lock. Used for measuring timings. * If MEASURE_LOCKS is enabled this method uses a specific histogram instance to record the timing of obtaining this lock. */ #define OSDEV_COMPONENTS_UNIQUELOCK_CREATE_SPECIFIC(mutexVariableName, id) \ OSDEV_COMPONENTS_UNIQUELOCK_CREATE_SPECIFIC_OBTAINER(mutexVariableName, mutexVariableName, id) /** * @brief Lock a given uniqeue lock. * @param mutexVariableName The name of the mutex from which the lockname is derived. * If MEASURE_LOCKS is enabled this method uses a static histogram to record the timing of obtaining the lock for all instances. */ #define OSDEV_COMPONENTS_UNIQUELOCK_LOCK(mutexVariableName) \ OSDEV_COMPONENTS_MEASURELOCK(UNIQUELOCK_LOCK, OSDEV_COMPONENTS_UNIQUELOCK(mutexVariableName).lock(), osdev::components::mqtt::measure_locking_tag, osdev::components::mqtt::MeasureLockingValue, 100) /** * @brief Lock a given uniqeue lock. * @param mutexVariableName The name of the mutex from which the lockname is derived. * @param id The id that identifies this specific unique lock guard. Used for measuring timings. * If MEASURE_LOCKS is enabled this method uses a specific histogram instance to record the timing of obtaining this lock. */ #define OSDEV_COMPONENTS_UNIQUELOCK_LOCK_SPECIFIC(mutexVariableName, id) \ OSDEV_COMPONENTS_MEASURELOCK_SPECIFIC(id, UNIQUELOCK_LOCK, OSDEV_COMPONENTS_UNIQUELOCK(mutexVariableName).lock(), osdev::components::mqtt::measure_locking_tag, osdev::components::mqtt::MeasureLockingValue, 100) /** * @brief Unlock a given uniqeue lock. * @param mutexVariableName The name of the mutex from which the lockname is derived. */ #define OSDEV_COMPONENTS_UNIQUELOCK_UNLOCK(mutexVariableName) \ OSDEV_COMPONENTS_UNIQUELOCK(mutexVariableName).unlock(); /** * @brief Unlock a given uniqeue lock. * @param mutexVariableName The name of the mutex from which the lockname is derived. * @param id The id that identifies this specific unique lock guard. Can be used for measuring timings. */ #define OSDEV_COMPONENTS_UNIQUELOCK_UNLOCK_SPECIFIC(mutexVariableName, id) \ OSDEV_COMPONENTS_UNIQUELOCK(mutexVariableName).unlock(); namespace osdev { namespace components { namespace mqtt { /** * @brief Context tag type. */ struct measure_locking_tag { }; /** * @brief Type for measuring lock timings * The unit is microseconds and the values are expected between 0 and 100 microseconds. * This type is used to construct a timing histogram. */ struct MeasureLockingValue { /** * @brief The value type of the timing value. */ using value_type = std::chrono::microseconds; const value_type minValue = value_type(0); ///< Constant mininum value. const value_type maxValue = value_type(100); ///< Constant maximum value. const char* unit = "us"; ///< The value unit. }; } // End namespace mqtt } // End namespace components } // End namespace osdev #endif // OSDEV_COMPONENTS_MQTT_LOCKGUARD_H