diff --git a/.github/workflows/buildsCI.yaml b/.github/workflows/buildsCI.yaml index 7754d57a00..34a0c3e0dd 100644 --- a/.github/workflows/buildsCI.yaml +++ b/.github/workflows/buildsCI.yaml @@ -30,10 +30,16 @@ jobs: run: | New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force + - name: Check_API + shell: bash + run: | + cd scripts + ./api_check.sh + cd .. + - name: PreBuild shell: bash run: | - cd scripts && ./api_check.sh && cd .. mkdir build - name: Configure CMake @@ -96,10 +102,16 @@ jobs: run: | New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force + - name: Check_API + shell: bash + run: | + cd scripts + ./api_check.sh + cd .. + - name: PreBuild shell: bash run: | - cd scripts && ./api_check.sh && cd .. mkdir build - name: Configure CMake @@ -136,10 +148,16 @@ jobs: run: | New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force + - name: Check_API + shell: bash + run: | + cd scripts + ./api_check.sh + cd .. + - name: PreBuild shell: bash run: | - cd scripts && ./api_check.sh && cd .. mkdir build - name: Configure CMake @@ -166,11 +184,18 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Check_API + shell: bash + run: | + cd scripts + ./api_check.sh + cd .. + - name: Prebuild shell: bash run: | - cd scripts && ./api_check.sh && cd .. - mkdir build && cd build + mkdir build + cd build export LRS_LOG_LEVEL="DEBUG"; sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test; sudo apt-get update; @@ -234,12 +259,20 @@ jobs: sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 60 --slave /usr/bin/g++ g++ /usr/bin/g++-5; sudo apt-get install libglfw3-dev libglfw3; + - name: Check_API + shell: bash + run: | + cd scripts + ./api_check.sh + cd .. + - name: Build shell: bash run: | - cd scripts && ./api_check.sh && cd .. mkdir build - cd ./scripts && ./pr_check.sh && cd ../build + cd ./scripts + ./pr_check.sh + cd ../build cmake .. -DBUILD_EXAMPLES=true -DBUILD_WITH_TM2=true -DBUILD_SHARED_LIBS=false -DCHECK_FOR_UPDATES=true -DBUILD_PYTHON_BINDINGS=true -DPYBIND11_PYTHON_VERSION=3.5 cmake --build . --config ${{env.LRS_BUILD_CONFIG}} -- -j4 @@ -253,11 +286,17 @@ jobs: - uses: actions/checkout@v2 + - name: Check_API + shell: bash + run: | + cd scripts + ./api_check.sh + cd .. + - name: Prebuild shell: bash run: | set -x - cd ./scripts && ./api_check.sh && cd .. # Workaround for nvm failure: https://github.com/appleboy/ssh-action/issues/70 export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" @@ -300,9 +339,16 @@ jobs: steps: - uses: actions/checkout@v2 + + - name: Check_API + shell: bash + run: | + cd scripts + ./api_check.sh + cd .. + - name: Prebuild run: | - cd scripts && ./api_check.sh && cd .. mkdir build # install coreutils for greadlink use brew install coreutils @@ -326,10 +372,15 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Check_API + shell: bash + run: | + cd scripts + ./api_check.sh + cd .. - name: Prebuild shell: bash run: | - cd scripts && ./api_check.sh && cd .. mkdir build wget https://dl.google.com/android/repository/android-ndk-r20b-linux-x86_64.zip; unzip -q android-ndk-r20b-linux-x86_64.zip -d ./; diff --git a/src/basics.h b/src/basics.h index ebc1c46132..5be455178b 100644 --- a/src/basics.h +++ b/src/basics.h @@ -1,16 +1,16 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2021 Intel Corporation. All Rights Reserved. - -#pragma once - - -// Disable declspec(dllexport) warnings: -// Classes exported via LRS_EXTENSION_API are **not** part of official librealsense API (at least for now) -// Any extension relying on these APIs must be compiled and distributed together with realsense2.dll -#pragma warning(disable : 4275) /* disable: C4275: non dll-interface class used as base for dll-interface class */ -#pragma warning(disable : 4251) /* disable: C4251: class needs to have dll-interface to be used by clients of class */ -#ifdef WIN32 -#define LRS_EXTENSION_API __declspec(dllexport) -#else -#define LRS_EXTENSION_API -#endif +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2021 Intel Corporation. All Rights Reserved. + +#pragma once + + +// Disable declspec(dllexport) warnings: +// Classes exported via LRS_EXTENSION_API are **not** part of official librealsense API (at least for now) +// Any extension relying on these APIs must be compiled and distributed together with realsense2.dll +#pragma warning(disable : 4275) /* disable: C4275: non dll-interface class used as base for dll-interface class */ +#pragma warning(disable : 4251) /* disable: C4251: class needs to have dll-interface to be used by clients of class */ +#ifdef WIN32 +#define LRS_EXTENSION_API __declspec(dllexport) +#else +#define LRS_EXTENSION_API +#endif diff --git a/src/callback-invocation.h b/src/callback-invocation.h index 8d44fbbfa5..162a905176 100644 --- a/src/callback-invocation.h +++ b/src/callback-invocation.h @@ -1,67 +1,67 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2021 Intel Corporation. All Rights Reserved. - -#pragma once - -#include "small-heap.h" - -#include - - -namespace librealsense { - - -struct callback_invocation -{ - std::chrono::high_resolution_clock::time_point started; - std::chrono::high_resolution_clock::time_point ended; -}; - -typedef small_heap< callback_invocation, 1 > callbacks_heap; - -struct callback_invocation_holder -{ - callback_invocation_holder() - : invocation( nullptr ) - , owner( nullptr ) - { - } - callback_invocation_holder( const callback_invocation_holder & ) = delete; - callback_invocation_holder & operator=( const callback_invocation_holder & ) = delete; - - callback_invocation_holder( callback_invocation_holder && other ) - : invocation( other.invocation ) - , owner( other.owner ) - { - other.invocation = nullptr; - } - - callback_invocation_holder( callback_invocation * invocation, callbacks_heap * owner ) - : invocation( invocation ) - , owner( owner ) - { - } - - ~callback_invocation_holder() - { - if( invocation ) - owner->deallocate( invocation ); - } - - callback_invocation_holder & operator=( callback_invocation_holder && other ) - { - invocation = other.invocation; - owner = other.owner; - other.invocation = nullptr; - return *this; - } - - operator bool() { return invocation != nullptr; } - -private: - callback_invocation * invocation; - callbacks_heap * owner; -}; - - -} // namespace librealsense +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2021 Intel Corporation. All Rights Reserved. + +#pragma once + +#include "small-heap.h" + +#include + + +namespace librealsense { + + +struct callback_invocation +{ + std::chrono::high_resolution_clock::time_point started; + std::chrono::high_resolution_clock::time_point ended; +}; + +typedef small_heap< callback_invocation, 1 > callbacks_heap; + +struct callback_invocation_holder +{ + callback_invocation_holder() + : invocation( nullptr ) + , owner( nullptr ) + { + } + callback_invocation_holder( const callback_invocation_holder & ) = delete; + callback_invocation_holder & operator=( const callback_invocation_holder & ) = delete; + + callback_invocation_holder( callback_invocation_holder && other ) + : invocation( other.invocation ) + , owner( other.owner ) + { + other.invocation = nullptr; + } + + callback_invocation_holder( callback_invocation * invocation, callbacks_heap * owner ) + : invocation( invocation ) + , owner( owner ) + { + } + + ~callback_invocation_holder() + { + if( invocation ) + owner->deallocate( invocation ); + } + + callback_invocation_holder & operator=( callback_invocation_holder && other ) + { + invocation = other.invocation; + owner = other.owner; + other.invocation = nullptr; + return *this; + } + + operator bool() { return invocation != nullptr; } + +private: + callback_invocation * invocation; + callbacks_heap * owner; +}; + + +} // namespace librealsense diff --git a/src/ds5/ds5-device.cpp b/src/ds5/ds5-device.cpp index fbcce72477..062dca68ce 100644 --- a/src/ds5/ds5-device.cpp +++ b/src/ds5/ds5-device.cpp @@ -1089,32 +1089,32 @@ namespace librealsense auto exposure_range = depth_sensor.get_option(RS2_OPTION_EXPOSURE).get_range(); auto gain_range = depth_sensor.get_option(RS2_OPTION_GAIN).get_range(); - option_range enable_range = { 0.f /*min*/, 1.f /*max*/, 1.f /*step*/, 0.f /*default*/ }; + option_range enable_range = { 0.f /*min*/, 1.f /*max*/, 1.f /*step*/, 0.f /*default*/ }; - //GAIN Limit - auto gain_limit_toggle_control = std::make_shared(RS2_OPTION_AUTO_GAIN_LIMIT_TOGGLE, enable_range, "Toggle Auto-Gain Limit", *_hw_monitor); - _gain_limit_value_control = std::make_shared(*_hw_monitor, &depth_sensor, gain_range, gain_limit_toggle_control); - depth_sensor.register_option(RS2_OPTION_AUTO_GAIN_LIMIT_TOGGLE, gain_limit_toggle_control); + //GAIN Limit + auto gain_limit_toggle_control = std::make_shared(RS2_OPTION_AUTO_GAIN_LIMIT_TOGGLE, enable_range, "Toggle Auto-Gain Limit", *_hw_monitor); + _gain_limit_value_control = std::make_shared(*_hw_monitor, &depth_sensor, gain_range, gain_limit_toggle_control); + depth_sensor.register_option(RS2_OPTION_AUTO_GAIN_LIMIT_TOGGLE, gain_limit_toggle_control); - depth_sensor.register_option(RS2_OPTION_AUTO_GAIN_LIMIT, - std::make_shared( - _gain_limit_value_control, - gain_limit_toggle_control + depth_sensor.register_option(RS2_OPTION_AUTO_GAIN_LIMIT, + std::make_shared( + _gain_limit_value_control, + gain_limit_toggle_control - )); + )); - // EXPOSURE Limit - auto ae_limit_toggle_control = std::make_shared(RS2_OPTION_AUTO_EXPOSURE_LIMIT_TOGGLE, enable_range, "Toggle Auto-Exposure Limit", *_hw_monitor); - _ae_limit_value_control = std::make_shared(*_hw_monitor, &depth_sensor, exposure_range, ae_limit_toggle_control); - depth_sensor.register_option(RS2_OPTION_AUTO_EXPOSURE_LIMIT_TOGGLE, ae_limit_toggle_control); + // EXPOSURE Limit + auto ae_limit_toggle_control = std::make_shared(RS2_OPTION_AUTO_EXPOSURE_LIMIT_TOGGLE, enable_range, "Toggle Auto-Exposure Limit", *_hw_monitor); + _ae_limit_value_control = std::make_shared(*_hw_monitor, &depth_sensor, exposure_range, ae_limit_toggle_control); + depth_sensor.register_option(RS2_OPTION_AUTO_EXPOSURE_LIMIT_TOGGLE, ae_limit_toggle_control); - depth_sensor.register_option(RS2_OPTION_AUTO_EXPOSURE_LIMIT, - std::make_shared( - _ae_limit_value_control, - ae_limit_toggle_control + depth_sensor.register_option(RS2_OPTION_AUTO_EXPOSURE_LIMIT, + std::make_shared( + _ae_limit_value_control, + ae_limit_toggle_control - )); - } + )); + } }); //group_multiple_fw_calls // attributes of md_capture_timing diff --git a/src/easyloggingpp.h b/src/easyloggingpp.h index 56ce1d9bb4..31a36ed036 100644 --- a/src/easyloggingpp.h +++ b/src/easyloggingpp.h @@ -1,47 +1,47 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2021 Intel Corporation. All Rights Reserved. - -#pragma once - -#if BUILD_EASYLOGGINGPP -#include "../third-party/easyloggingpp/src/easylogging++.h" - - -#ifdef __ANDROID__ -#include -#include - -#define ANDROID_LOG_TAG "librs" - -#define LOG_INFO(...) do { std::ostringstream ss; ss << __VA_ARGS__; __android_log_write( ANDROID_LOG_INFO, ANDROID_LOG_TAG, ss.str().c_str() ); } while(false) -#define LOG_WARNING(...) do { std::ostringstream ss; ss << __VA_ARGS__; __android_log_write( ANDROID_LOG_WARN, ANDROID_LOG_TAG, ss.str().c_str() ); } while(false) -#define LOG_ERROR(...) do { std::ostringstream ss; ss << __VA_ARGS__; __android_log_write( ANDROID_LOG_ERROR, ANDROID_LOG_TAG, ss.str().c_str() ); } while(false) -#define LOG_FATAL(...) do { std::ostringstream ss; ss << __VA_ARGS__; __android_log_write( ANDROID_LOG_ERROR, ANDROID_LOG_TAG, ss.str().c_str() ); } while(false) -#ifdef NDEBUG -#define LOG_DEBUG(...) -#else -#define LOG_DEBUG(...) do { std::ostringstream ss; ss << __VA_ARGS__; __android_log_write( ANDROID_LOG_DEBUG, ANDROID_LOG_TAG, ss.str().c_str() ); } while(false) -#endif - -#else //__ANDROID__ - -#define LOG_DEBUG(...) do { CLOG(DEBUG ,"librealsense") << __VA_ARGS__; } while(false) -#define LOG_INFO(...) do { CLOG(INFO ,"librealsense") << __VA_ARGS__; } while(false) -#define LOG_WARNING(...) do { CLOG(WARNING ,"librealsense") << __VA_ARGS__; } while(false) -#define LOG_ERROR(...) do { CLOG(ERROR ,"librealsense") << __VA_ARGS__; } while(false) -#define LOG_FATAL(...) do { CLOG(FATAL ,"librealsense") << __VA_ARGS__; } while(false) - -#endif // __ANDROID__ - - -#else // BUILD_EASYLOGGINGPP - - -#define LOG_DEBUG(...) do { ; } while(false) -#define LOG_INFO(...) do { ; } while(false) -#define LOG_WARNING(...) do { ; } while(false) -#define LOG_ERROR(...) do { ; } while(false) -#define LOG_FATAL(...) do { ; } while(false) - - -#endif // BUILD_EASYLOGGINGPP +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2021 Intel Corporation. All Rights Reserved. + +#pragma once + +#if BUILD_EASYLOGGINGPP +#include "../third-party/easyloggingpp/src/easylogging++.h" + + +#ifdef __ANDROID__ +#include +#include + +#define ANDROID_LOG_TAG "librs" + +#define LOG_INFO(...) do { std::ostringstream ss; ss << __VA_ARGS__; __android_log_write( ANDROID_LOG_INFO, ANDROID_LOG_TAG, ss.str().c_str() ); } while(false) +#define LOG_WARNING(...) do { std::ostringstream ss; ss << __VA_ARGS__; __android_log_write( ANDROID_LOG_WARN, ANDROID_LOG_TAG, ss.str().c_str() ); } while(false) +#define LOG_ERROR(...) do { std::ostringstream ss; ss << __VA_ARGS__; __android_log_write( ANDROID_LOG_ERROR, ANDROID_LOG_TAG, ss.str().c_str() ); } while(false) +#define LOG_FATAL(...) do { std::ostringstream ss; ss << __VA_ARGS__; __android_log_write( ANDROID_LOG_ERROR, ANDROID_LOG_TAG, ss.str().c_str() ); } while(false) +#ifdef NDEBUG +#define LOG_DEBUG(...) +#else +#define LOG_DEBUG(...) do { std::ostringstream ss; ss << __VA_ARGS__; __android_log_write( ANDROID_LOG_DEBUG, ANDROID_LOG_TAG, ss.str().c_str() ); } while(false) +#endif + +#else //__ANDROID__ + +#define LOG_DEBUG(...) do { CLOG(DEBUG ,"librealsense") << __VA_ARGS__; } while(false) +#define LOG_INFO(...) do { CLOG(INFO ,"librealsense") << __VA_ARGS__; } while(false) +#define LOG_WARNING(...) do { CLOG(WARNING ,"librealsense") << __VA_ARGS__; } while(false) +#define LOG_ERROR(...) do { CLOG(ERROR ,"librealsense") << __VA_ARGS__; } while(false) +#define LOG_FATAL(...) do { CLOG(FATAL ,"librealsense") << __VA_ARGS__; } while(false) + +#endif // __ANDROID__ + + +#else // BUILD_EASYLOGGINGPP + + +#define LOG_DEBUG(...) do { ; } while(false) +#define LOG_INFO(...) do { ; } while(false) +#define LOG_WARNING(...) do { ; } while(false) +#define LOG_ERROR(...) do { ; } while(false) +#define LOG_FATAL(...) do { ; } while(false) + + +#endif // BUILD_EASYLOGGINGPP diff --git a/src/librealsense-exception.h b/src/librealsense-exception.h index 138036aab3..a4c2314e18 100644 --- a/src/librealsense-exception.h +++ b/src/librealsense-exception.h @@ -1,144 +1,144 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2021 Intel Corporation. All Rights Reserved. - -#pragma once - -#include -#include "easyloggingpp.h" -#include "basics.h" // LRS_EXTENSION_API - -#include -#include - - -namespace librealsense { - - -class librealsense_exception : public std::exception -{ -public: - const char * get_message() const noexcept { return _msg.c_str(); } - - rs2_exception_type get_exception_type() const noexcept { return _exception_type; } - - const char * what() const noexcept override { return _msg.c_str(); } - -protected: - librealsense_exception( const std::string & msg, rs2_exception_type exception_type ) noexcept - : _msg( msg ) - , _exception_type( exception_type ) - { - } - -private: - std::string _msg; - rs2_exception_type _exception_type; -}; - - -class LRS_EXTENSION_API recoverable_exception : public librealsense_exception -{ -public: - recoverable_exception( const std::string & msg, rs2_exception_type exception_type ) noexcept; -}; - - -class unrecoverable_exception : public librealsense_exception -{ -public: - unrecoverable_exception( const std::string & msg, rs2_exception_type exception_type ) noexcept - : librealsense_exception( msg, exception_type ) - { - LOG_ERROR( msg ); - } -}; - - -class io_exception : public unrecoverable_exception -{ -public: - io_exception( const std::string & msg ) noexcept - : unrecoverable_exception( msg, RS2_EXCEPTION_TYPE_IO ) - { - } -}; - - -class camera_disconnected_exception : public unrecoverable_exception -{ -public: - camera_disconnected_exception( const std::string & msg ) noexcept - : unrecoverable_exception( msg, RS2_EXCEPTION_TYPE_CAMERA_DISCONNECTED ) - { - } -}; - - -class backend_exception : public unrecoverable_exception -{ -public: - backend_exception( const std::string & msg, rs2_exception_type exception_type ) noexcept - : unrecoverable_exception( msg, exception_type ) - { - } -}; - - -class linux_backend_exception : public backend_exception -{ -public: - linux_backend_exception( const std::string & msg ) noexcept - : backend_exception( generate_last_error_message( msg ), RS2_EXCEPTION_TYPE_BACKEND ) - { - } - -private: - std::string generate_last_error_message( const std::string & msg ) const - { - return msg + " Last Error: " + strerror( errno ); - } -}; - - -class windows_backend_exception : public backend_exception -{ -public: - // TODO: get last error - windows_backend_exception( const std::string & msg ) noexcept - : backend_exception( msg, RS2_EXCEPTION_TYPE_BACKEND ) - { - } -}; - - -class invalid_value_exception : public recoverable_exception -{ -public: - invalid_value_exception( const std::string & msg ) noexcept - : recoverable_exception( msg, RS2_EXCEPTION_TYPE_INVALID_VALUE ) - { - } -}; - - -class wrong_api_call_sequence_exception : public recoverable_exception -{ -public: - wrong_api_call_sequence_exception( const std::string & msg ) noexcept - : recoverable_exception( msg, RS2_EXCEPTION_TYPE_WRONG_API_CALL_SEQUENCE ) - { - } -}; - - -class not_implemented_exception : public recoverable_exception -{ -public: - not_implemented_exception( const std::string & msg ) noexcept - : recoverable_exception( msg, RS2_EXCEPTION_TYPE_NOT_IMPLEMENTED ) - { - } -}; - - -} // namespace librealsense +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2021 Intel Corporation. All Rights Reserved. + +#pragma once + +#include +#include "easyloggingpp.h" +#include "basics.h" // LRS_EXTENSION_API + +#include +#include + + +namespace librealsense { + + +class librealsense_exception : public std::exception +{ +public: + const char * get_message() const noexcept { return _msg.c_str(); } + + rs2_exception_type get_exception_type() const noexcept { return _exception_type; } + + const char * what() const noexcept override { return _msg.c_str(); } + +protected: + librealsense_exception( const std::string & msg, rs2_exception_type exception_type ) noexcept + : _msg( msg ) + , _exception_type( exception_type ) + { + } + +private: + std::string _msg; + rs2_exception_type _exception_type; +}; + + +class LRS_EXTENSION_API recoverable_exception : public librealsense_exception +{ +public: + recoverable_exception( const std::string & msg, rs2_exception_type exception_type ) noexcept; +}; + + +class unrecoverable_exception : public librealsense_exception +{ +public: + unrecoverable_exception( const std::string & msg, rs2_exception_type exception_type ) noexcept + : librealsense_exception( msg, exception_type ) + { + LOG_ERROR( msg ); + } +}; + + +class io_exception : public unrecoverable_exception +{ +public: + io_exception( const std::string & msg ) noexcept + : unrecoverable_exception( msg, RS2_EXCEPTION_TYPE_IO ) + { + } +}; + + +class camera_disconnected_exception : public unrecoverable_exception +{ +public: + camera_disconnected_exception( const std::string & msg ) noexcept + : unrecoverable_exception( msg, RS2_EXCEPTION_TYPE_CAMERA_DISCONNECTED ) + { + } +}; + + +class backend_exception : public unrecoverable_exception +{ +public: + backend_exception( const std::string & msg, rs2_exception_type exception_type ) noexcept + : unrecoverable_exception( msg, exception_type ) + { + } +}; + + +class linux_backend_exception : public backend_exception +{ +public: + linux_backend_exception( const std::string & msg ) noexcept + : backend_exception( generate_last_error_message( msg ), RS2_EXCEPTION_TYPE_BACKEND ) + { + } + +private: + std::string generate_last_error_message( const std::string & msg ) const + { + return msg + " Last Error: " + strerror( errno ); + } +}; + + +class windows_backend_exception : public backend_exception +{ +public: + // TODO: get last error + windows_backend_exception( const std::string & msg ) noexcept + : backend_exception( msg, RS2_EXCEPTION_TYPE_BACKEND ) + { + } +}; + + +class invalid_value_exception : public recoverable_exception +{ +public: + invalid_value_exception( const std::string & msg ) noexcept + : recoverable_exception( msg, RS2_EXCEPTION_TYPE_INVALID_VALUE ) + { + } +}; + + +class wrong_api_call_sequence_exception : public recoverable_exception +{ +public: + wrong_api_call_sequence_exception( const std::string & msg ) noexcept + : recoverable_exception( msg, RS2_EXCEPTION_TYPE_WRONG_API_CALL_SEQUENCE ) + { + } +}; + + +class not_implemented_exception : public recoverable_exception +{ +public: + not_implemented_exception( const std::string & msg ) noexcept + : recoverable_exception( msg, RS2_EXCEPTION_TYPE_NOT_IMPLEMENTED ) + { + } +}; + + +} // namespace librealsense diff --git a/src/linux/udev-device-watcher.cpp b/src/linux/udev-device-watcher.cpp index b5efb9161f..c0bd866b1d 100644 --- a/src/linux/udev-device-watcher.cpp +++ b/src/linux/udev-device-watcher.cpp @@ -1,224 +1,224 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2021 Intel Corporation. All Rights Reserved. - -#include "udev-device-watcher.h" - -#include - -#include -#include - -using std::string; -using std::runtime_error; - - -namespace { - - - void foreach_device_prop( struct udev_device * udev_dev, - std::function< void( std::string const & param, std::string const & value ) > callback ) - { - struct udev_list_entry * prop_entry; - udev_list_entry_foreach( prop_entry, udev_device_get_properties_list_entry( udev_dev ) ) - { - const string prop_name = udev_list_entry_get_name( prop_entry ); - const string prop_value = udev_list_entry_get_value( prop_entry ); - - callback( prop_name, prop_value ); - } - } - - - std::string udev_string( struct udev_device * dev ) - { - std::ostringstream os; - if( ! dev ) - os << "null"; - else - { - char const * sysname = udev_device_get_sysname( dev ); - char const * model = udev_device_get_property_value( dev, "ID_MODEL" ); - if( ! model || strncmp( model, "Intel", 5 )) - model = sysname; - os << model; - if( model != sysname ) - os << " [" << sysname << ']'; - //os << udev_device_get_syspath( dev ); - - // Enable to get a list of all properties - // For usb_device: - // ACTION=add BUSNUM=002 DEVNAME=/dev/bus/usb/002/125 DEVNUM=125 - // DEVPATH=/devices/pci0000:00/0000:00:14.0/usb2/2-2/2-2.4/2-2.4.4 DEVTYPE=usb_device DRIVER=usb - // ID_BUS=usb ID_MODEL=Intel_R__RealSense_TM__515 - // ID_MODEL_ENC=Intel\x28R\x29\x20RealSense\x28TM\x29\x20515 ID_MODEL_ID=0b64 ID_REVISION=1058 - // ID_SERIAL=Intel_R__RealSense_TM__Camera_Intel_R__RealSense_TM__515_00000000F0070132 - // ID_SERIAL_SHORT=00000000F0070132 ID_USB_INTERFACES=:0e0100:0e0200:ff0000:030000: - // ID_VENDOR=Intel_R__RealSense_TM__Camera - // ID_VENDOR_ENC=Intel\x28R\x29\x20RealSense\x28TM\x29\x20Camera ID_VENDOR_FROM_DATABASE=Intel Corp. - // ID_VENDOR_ID=8086 MAJOR=189 MINOR=252 PRODUCT=8086/b64/1058 SEQNUM=249377 SUBSYSTEM=usb - // TYPE=239/2/1 USEC_INITIALIZED=862653458266 - // And, for usb_interface: - // .MM_USBIFNUM=01 ACTION=add - // DEVPATH=/devices/pci0000:00/0000:00:14.0/usb2/2-2/2-2.4/2-2.4.4/2-2.4.4:1.1 DEVTYPE=usb_interface - // DRIVER=uvcvideo ID_USB_CLASS_FROM_DATABASE=Miscellaneous Device - // ID_USB_PROTOCOL_FROM_DATABASE=Interface Association ID_VENDOR_FROM_DATABASE=Intel Corp. - // INTERFACE=14/2/0 MODALIAS=usb:v8086p0B64d1058dcEFdsc02dp01ic0Eisc02ip00in01 PRODUCT=8086/b64/1058 - // SEQNUM=249386 SUBSYSTEM=usb TYPE=239/2/1 USEC_INITIALIZED=862653461483 -#if 0 - char sep = '['; - foreach_device_prop( dev, [&]( std::string const& name, std::string const & value ) - { - os << sep << name << '=' << value; - sep = ' '; - } ); - if( sep != '[' ) - os << ']'; -#endif - } - return os.str(); - } - } - - -namespace librealsense { - - -udev_device_watcher::udev_device_watcher( const platform::backend * backend ) - : _backend( backend ) - , _active_object( [this]( dispatcher::cancellable_timer timer ) { - struct pollfd fds; - fds.fd = _udev_monitor_fd; - fds.events = POLLIN; - - // Polling will block for a time but we cannot block for too long, as we want destruction to happen in - // reasonable time. So we use a short-enough period: - int const POLLING_PERIOD_MS = 100; - if( poll( &fds, 1, POLLING_PERIOD_MS ) > 0 ) - { - if( timer.was_stopped() || ! _udev_monitor || POLLIN != fds.revents ) - return; - - auto udev_dev = udev_monitor_receive_device( _udev_monitor ); - if( ! udev_dev ) - { - LOG_DEBUG( "failed to read data from udev monitor socket" ); - return; - } - - const string udev_action = udev_device_get_action( udev_dev ); - if( udev_action == "add" || udev_action == "remove" ) - { - LOG_DEBUG( "[udev] " << udev_action << " " << udev_string( udev_dev ) ); - // On remove events, we get all the device interfaces first, and lastly we get the device. - // On add events, we get the device first and only then the device interfaces. - // In any case, we get lots of adds/removes for each device. And we only want to do one enumeration -- - // so we wait for things to calm down and just remember that enumeration is needed... - _changed = true; - } - - udev_device_unref( udev_dev ); - } - else if( _changed ) - { - // Something's changed but nothing's happened in the last polling period -- let's enumerate! - LOG_DEBUG( "[udev] checking ..." ); - platform::backend_device_group curr( _backend->query_uvc_devices(), - _backend->query_usb_devices(), - _backend->query_hid_devices() ); - if( list_changed( _devices_data.uvc_devices, curr.uvc_devices ) - || list_changed( _devices_data.usb_devices, curr.usb_devices ) - || list_changed( _devices_data.hid_devices, curr.hid_devices ) ) - { - LOG_DEBUG( "[udev] changed!" ); - callback_invocation_holder callback = { _callback_inflight.allocate(), &_callback_inflight }; - if( callback ) - _callback( _devices_data, curr ); - _devices_data = curr; - } - _changed = false; - } - } ) -{ - _udev_ctx = udev_new(); - if( ! _udev_ctx ) - throw runtime_error( "could not initialize udev" ); - - _udev_monitor = udev_monitor_new_from_netlink( _udev_ctx, "udev" ); - if( ! _udev_monitor ) - { - udev_unref( _udev_ctx ); - _udev_ctx = nullptr; - throw runtime_error( "could not initialize udev monitor" ); - } - - _udev_monitor_fd = udev_monitor_get_fd( _udev_monitor ); - - if( udev_monitor_filter_add_match_subsystem_devtype( _udev_monitor, "usb", 0 ) ) - { - udev_monitor_unref( _udev_monitor ); - _udev_monitor = nullptr; - _udev_monitor_fd = -1; - udev_unref( _udev_ctx ); - _udev_ctx = nullptr; - throw runtime_error( "could not initialize udev monitor filter for \"usb\" subsystem" ); - } - - if( udev_monitor_enable_receiving( _udev_monitor ) ) - { - udev_monitor_unref( _udev_monitor ); - _udev_monitor = nullptr; - _udev_monitor_fd = -1; - udev_unref( _udev_ctx ); - _udev_ctx = nullptr; - throw runtime_error( "failed to enable the udev monitor" ); - } - - _devices_data = { _backend->query_uvc_devices(), _backend->query_usb_devices(), _backend->query_hid_devices() }; -} - - -udev_device_watcher::~udev_device_watcher() -{ - stop(); - - if( _udev_monitor_fd == -1 ) - throw runtime_error( "monitor fd was -1" ); - - /* Release the udev monitor */ - udev_monitor_unref( _udev_monitor ); - _udev_monitor = nullptr; - _udev_monitor_fd = -1; - - /* Clean up the udev context */ - udev_unref( _udev_ctx ); - _udev_ctx = nullptr; -} - - -// Scan devices using udev -bool udev_device_watcher::foreach_device( std::function< bool( struct udev_device * udev_dev ) > callback ) -{ - auto enumerator = udev_enumerate_new( _udev_ctx ); - if( ! enumerator ) - throw runtime_error( "error creating udev enumerator" ); - - udev_enumerate_add_match_subsystem( enumerator, "usb" ); - udev_enumerate_scan_devices( enumerator ); - - auto devices = udev_enumerate_get_list_entry( enumerator ); - struct udev_list_entry * device_entry; - udev_list_entry_foreach( device_entry, devices ) - { - const char * path = udev_list_entry_get_name( device_entry ); - struct udev_device * udev_dev = udev_device_new_from_syspath( _udev_ctx, path ); - - callback( udev_dev ); - - udev_device_unref( udev_dev ); - } - - udev_enumerate_unref( enumerator ); -} - - +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2021 Intel Corporation. All Rights Reserved. + +#include "udev-device-watcher.h" + +#include + +#include +#include + +using std::string; +using std::runtime_error; + + +namespace { + + + void foreach_device_prop( struct udev_device * udev_dev, + std::function< void( std::string const & param, std::string const & value ) > callback ) + { + struct udev_list_entry * prop_entry; + udev_list_entry_foreach( prop_entry, udev_device_get_properties_list_entry( udev_dev ) ) + { + const string prop_name = udev_list_entry_get_name( prop_entry ); + const string prop_value = udev_list_entry_get_value( prop_entry ); + + callback( prop_name, prop_value ); + } + } + + + std::string udev_string( struct udev_device * dev ) + { + std::ostringstream os; + if( ! dev ) + os << "null"; + else + { + char const * sysname = udev_device_get_sysname( dev ); + char const * model = udev_device_get_property_value( dev, "ID_MODEL" ); + if( ! model || strncmp( model, "Intel", 5 )) + model = sysname; + os << model; + if( model != sysname ) + os << " [" << sysname << ']'; + //os << udev_device_get_syspath( dev ); + + // Enable to get a list of all properties + // For usb_device: + // ACTION=add BUSNUM=002 DEVNAME=/dev/bus/usb/002/125 DEVNUM=125 + // DEVPATH=/devices/pci0000:00/0000:00:14.0/usb2/2-2/2-2.4/2-2.4.4 DEVTYPE=usb_device DRIVER=usb + // ID_BUS=usb ID_MODEL=Intel_R__RealSense_TM__515 + // ID_MODEL_ENC=Intel\x28R\x29\x20RealSense\x28TM\x29\x20515 ID_MODEL_ID=0b64 ID_REVISION=1058 + // ID_SERIAL=Intel_R__RealSense_TM__Camera_Intel_R__RealSense_TM__515_00000000F0070132 + // ID_SERIAL_SHORT=00000000F0070132 ID_USB_INTERFACES=:0e0100:0e0200:ff0000:030000: + // ID_VENDOR=Intel_R__RealSense_TM__Camera + // ID_VENDOR_ENC=Intel\x28R\x29\x20RealSense\x28TM\x29\x20Camera ID_VENDOR_FROM_DATABASE=Intel Corp. + // ID_VENDOR_ID=8086 MAJOR=189 MINOR=252 PRODUCT=8086/b64/1058 SEQNUM=249377 SUBSYSTEM=usb + // TYPE=239/2/1 USEC_INITIALIZED=862653458266 + // And, for usb_interface: + // .MM_USBIFNUM=01 ACTION=add + // DEVPATH=/devices/pci0000:00/0000:00:14.0/usb2/2-2/2-2.4/2-2.4.4/2-2.4.4:1.1 DEVTYPE=usb_interface + // DRIVER=uvcvideo ID_USB_CLASS_FROM_DATABASE=Miscellaneous Device + // ID_USB_PROTOCOL_FROM_DATABASE=Interface Association ID_VENDOR_FROM_DATABASE=Intel Corp. + // INTERFACE=14/2/0 MODALIAS=usb:v8086p0B64d1058dcEFdsc02dp01ic0Eisc02ip00in01 PRODUCT=8086/b64/1058 + // SEQNUM=249386 SUBSYSTEM=usb TYPE=239/2/1 USEC_INITIALIZED=862653461483 +#if 0 + char sep = '['; + foreach_device_prop( dev, [&]( std::string const& name, std::string const & value ) + { + os << sep << name << '=' << value; + sep = ' '; + } ); + if( sep != '[' ) + os << ']'; +#endif + } + return os.str(); + } + } + + +namespace librealsense { + + +udev_device_watcher::udev_device_watcher( const platform::backend * backend ) + : _backend( backend ) + , _active_object( [this]( dispatcher::cancellable_timer timer ) { + struct pollfd fds; + fds.fd = _udev_monitor_fd; + fds.events = POLLIN; + + // Polling will block for a time but we cannot block for too long, as we want destruction to happen in + // reasonable time. So we use a short-enough period: + int const POLLING_PERIOD_MS = 100; + if( poll( &fds, 1, POLLING_PERIOD_MS ) > 0 ) + { + if( timer.was_stopped() || ! _udev_monitor || POLLIN != fds.revents ) + return; + + auto udev_dev = udev_monitor_receive_device( _udev_monitor ); + if( ! udev_dev ) + { + LOG_DEBUG( "failed to read data from udev monitor socket" ); + return; + } + + const string udev_action = udev_device_get_action( udev_dev ); + if( udev_action == "add" || udev_action == "remove" ) + { + LOG_DEBUG( "[udev] " << udev_action << " " << udev_string( udev_dev ) ); + // On remove events, we get all the device interfaces first, and lastly we get the device. + // On add events, we get the device first and only then the device interfaces. + // In any case, we get lots of adds/removes for each device. And we only want to do one enumeration -- + // so we wait for things to calm down and just remember that enumeration is needed... + _changed = true; + } + + udev_device_unref( udev_dev ); + } + else if( _changed ) + { + // Something's changed but nothing's happened in the last polling period -- let's enumerate! + LOG_DEBUG( "[udev] checking ..." ); + platform::backend_device_group curr( _backend->query_uvc_devices(), + _backend->query_usb_devices(), + _backend->query_hid_devices() ); + if( list_changed( _devices_data.uvc_devices, curr.uvc_devices ) + || list_changed( _devices_data.usb_devices, curr.usb_devices ) + || list_changed( _devices_data.hid_devices, curr.hid_devices ) ) + { + LOG_DEBUG( "[udev] changed!" ); + callback_invocation_holder callback = { _callback_inflight.allocate(), &_callback_inflight }; + if( callback ) + _callback( _devices_data, curr ); + _devices_data = curr; + } + _changed = false; + } + } ) +{ + _udev_ctx = udev_new(); + if( ! _udev_ctx ) + throw runtime_error( "could not initialize udev" ); + + _udev_monitor = udev_monitor_new_from_netlink( _udev_ctx, "udev" ); + if( ! _udev_monitor ) + { + udev_unref( _udev_ctx ); + _udev_ctx = nullptr; + throw runtime_error( "could not initialize udev monitor" ); + } + + _udev_monitor_fd = udev_monitor_get_fd( _udev_monitor ); + + if( udev_monitor_filter_add_match_subsystem_devtype( _udev_monitor, "usb", 0 ) ) + { + udev_monitor_unref( _udev_monitor ); + _udev_monitor = nullptr; + _udev_monitor_fd = -1; + udev_unref( _udev_ctx ); + _udev_ctx = nullptr; + throw runtime_error( "could not initialize udev monitor filter for \"usb\" subsystem" ); + } + + if( udev_monitor_enable_receiving( _udev_monitor ) ) + { + udev_monitor_unref( _udev_monitor ); + _udev_monitor = nullptr; + _udev_monitor_fd = -1; + udev_unref( _udev_ctx ); + _udev_ctx = nullptr; + throw runtime_error( "failed to enable the udev monitor" ); + } + + _devices_data = { _backend->query_uvc_devices(), _backend->query_usb_devices(), _backend->query_hid_devices() }; +} + + +udev_device_watcher::~udev_device_watcher() +{ + stop(); + + if( _udev_monitor_fd == -1 ) + throw runtime_error( "monitor fd was -1" ); + + /* Release the udev monitor */ + udev_monitor_unref( _udev_monitor ); + _udev_monitor = nullptr; + _udev_monitor_fd = -1; + + /* Clean up the udev context */ + udev_unref( _udev_ctx ); + _udev_ctx = nullptr; +} + + +// Scan devices using udev +bool udev_device_watcher::foreach_device( std::function< bool( struct udev_device * udev_dev ) > callback ) +{ + auto enumerator = udev_enumerate_new( _udev_ctx ); + if( ! enumerator ) + throw runtime_error( "error creating udev enumerator" ); + + udev_enumerate_add_match_subsystem( enumerator, "usb" ); + udev_enumerate_scan_devices( enumerator ); + + auto devices = udev_enumerate_get_list_entry( enumerator ); + struct udev_list_entry * device_entry; + udev_list_entry_foreach( device_entry, devices ) + { + const char * path = udev_list_entry_get_name( device_entry ); + struct udev_device * udev_dev = udev_device_new_from_syspath( _udev_ctx, path ); + + callback( udev_dev ); + + udev_device_unref( udev_dev ); + } + + udev_enumerate_unref( enumerator ); +} + + } // namespace librealsense \ No newline at end of file diff --git a/src/linux/udev-device-watcher.h b/src/linux/udev-device-watcher.h index beeaca482f..f703050934 100644 --- a/src/linux/udev-device-watcher.h +++ b/src/linux/udev-device-watcher.h @@ -1,57 +1,57 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2021 Intel Corporation. All Rights Reserved. - -#pragma once - -#include "../backend.h" -#include "../concurrency.h" -#include "../callback-invocation.h" - -#include - - -namespace librealsense { - - -class udev_device_watcher : public librealsense::platform::device_watcher -{ - active_object<> _active_object; - - callbacks_heap _callback_inflight; - platform::backend const * _backend; - - platform::backend_device_group _devices_data; - platform::device_changed_callback _callback; - - struct udev * _udev_ctx; - struct udev_monitor * _udev_monitor; - int _udev_monitor_fd; - bool _changed = false; - -public: - udev_device_watcher( platform::backend const * ); - ~udev_device_watcher(); - - // device_watcher -public: - void start( platform::device_changed_callback callback ) override - { - stop(); - _callback = std::move( callback ); - _active_object.start(); - } - - void stop() override - { - _active_object.stop(); - _callback_inflight.wait_until_empty(); - } - - bool is_stopped() const override { return ! _active_object.is_active(); } - -private: - bool foreach_device( std::function< bool( struct udev_device* udev_dev ) > ); -}; - - -} // namespace librealsense +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2021 Intel Corporation. All Rights Reserved. + +#pragma once + +#include "../backend.h" +#include "../concurrency.h" +#include "../callback-invocation.h" + +#include + + +namespace librealsense { + + +class udev_device_watcher : public librealsense::platform::device_watcher +{ + active_object<> _active_object; + + callbacks_heap _callback_inflight; + platform::backend const * _backend; + + platform::backend_device_group _devices_data; + platform::device_changed_callback _callback; + + struct udev * _udev_ctx; + struct udev_monitor * _udev_monitor; + int _udev_monitor_fd; + bool _changed = false; + +public: + udev_device_watcher( platform::backend const * ); + ~udev_device_watcher(); + + // device_watcher +public: + void start( platform::device_changed_callback callback ) override + { + stop(); + _callback = std::move( callback ); + _active_object.start(); + } + + void stop() override + { + _active_object.stop(); + _callback_inflight.wait_until_empty(); + } + + bool is_stopped() const override { return ! _active_object.is_active(); } + +private: + bool foreach_device( std::function< bool( struct udev_device* udev_dev ) > ); +}; + + +} // namespace librealsense diff --git a/src/polling-device-watcher.h b/src/polling-device-watcher.h index 8c328e4c7a..7986488694 100644 --- a/src/polling-device-watcher.h +++ b/src/polling-device-watcher.h @@ -1,77 +1,77 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2021 Intel Corporation. All Rights Reserved. - -#pragma once - -#include "backend.h" -#include "concurrency.h" -#include "callback-invocation.h" - - -namespace librealsense { - - -// This device_watcher enumerates all devices every set amount of time (POLLING_DEVICES_INTERVAL_MS) -// -class polling_device_watcher : public librealsense::platform::device_watcher -{ -public: - polling_device_watcher( const platform::backend * backend_ref ) - : _backend( backend_ref ) - , _active_object( [this]( dispatcher::cancellable_timer cancellable_timer ) { polling( cancellable_timer ); } ) - , _devices_data() - { - _devices_data = { _backend->query_uvc_devices(), _backend->query_usb_devices(), _backend->query_hid_devices() }; - } - - ~polling_device_watcher() { stop(); } - - void polling( dispatcher::cancellable_timer cancellable_timer ) - { - if( cancellable_timer.try_sleep( std::chrono::milliseconds( POLLING_DEVICES_INTERVAL_MS ) ) ) - { - platform::backend_device_group curr( _backend->query_uvc_devices(), - _backend->query_usb_devices(), - _backend->query_hid_devices() ); - if( list_changed( _devices_data.uvc_devices, curr.uvc_devices ) - || list_changed( _devices_data.usb_devices, curr.usb_devices ) - || list_changed( _devices_data.hid_devices, curr.hid_devices ) ) - { - callback_invocation_holder callback = { _callback_inflight.allocate(), &_callback_inflight }; - if( callback ) - { - _callback( _devices_data, curr ); - _devices_data = curr; - } - } - } - } - - void start( platform::device_changed_callback callback ) override - { - stop(); - _callback = std::move( callback ); - _active_object.start(); - } - - void stop() override - { - _active_object.stop(); - - _callback_inflight.wait_until_empty(); - } - - bool is_stopped() const override { return ! _active_object.is_active(); } - -private: - active_object<> _active_object; - - callbacks_heap _callback_inflight; - const platform::backend * _backend; - - platform::backend_device_group _devices_data; - platform::device_changed_callback _callback; -}; - - -} // namespace librealsense +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2021 Intel Corporation. All Rights Reserved. + +#pragma once + +#include "backend.h" +#include "concurrency.h" +#include "callback-invocation.h" + + +namespace librealsense { + + +// This device_watcher enumerates all devices every set amount of time (POLLING_DEVICES_INTERVAL_MS) +// +class polling_device_watcher : public librealsense::platform::device_watcher +{ +public: + polling_device_watcher( const platform::backend * backend_ref ) + : _backend( backend_ref ) + , _active_object( [this]( dispatcher::cancellable_timer cancellable_timer ) { polling( cancellable_timer ); } ) + , _devices_data() + { + _devices_data = { _backend->query_uvc_devices(), _backend->query_usb_devices(), _backend->query_hid_devices() }; + } + + ~polling_device_watcher() { stop(); } + + void polling( dispatcher::cancellable_timer cancellable_timer ) + { + if( cancellable_timer.try_sleep( std::chrono::milliseconds( POLLING_DEVICES_INTERVAL_MS ) ) ) + { + platform::backend_device_group curr( _backend->query_uvc_devices(), + _backend->query_usb_devices(), + _backend->query_hid_devices() ); + if( list_changed( _devices_data.uvc_devices, curr.uvc_devices ) + || list_changed( _devices_data.usb_devices, curr.usb_devices ) + || list_changed( _devices_data.hid_devices, curr.hid_devices ) ) + { + callback_invocation_holder callback = { _callback_inflight.allocate(), &_callback_inflight }; + if( callback ) + { + _callback( _devices_data, curr ); + _devices_data = curr; + } + } + } + } + + void start( platform::device_changed_callback callback ) override + { + stop(); + _callback = std::move( callback ); + _active_object.start(); + } + + void stop() override + { + _active_object.stop(); + + _callback_inflight.wait_until_empty(); + } + + bool is_stopped() const override { return ! _active_object.is_active(); } + +private: + active_object<> _active_object; + + callbacks_heap _callback_inflight; + const platform::backend * _backend; + + platform::backend_device_group _devices_data; + platform::device_changed_callback _callback; +}; + + +} // namespace librealsense diff --git a/src/small-heap.h b/src/small-heap.h index 1629acb8cf..5b27367329 100644 --- a/src/small-heap.h +++ b/src/small-heap.h @@ -1,106 +1,106 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2021 Intel Corporation. All Rights Reserved. - -#pragma once - -#include "librealsense-exception.h" - -#include -#include - - -namespace librealsense { - - -template < class T, int C > -class small_heap -{ - T buffer[C]; - bool is_free[C]; - std::mutex mutex; - bool keep_allocating = true; - std::condition_variable cv; - int size = 0; - -public: - static const int CAPACITY = C; - - small_heap() - { - for( auto i = 0; i < C; i++ ) - { - is_free[i] = true; - buffer[i] = std::move( T() ); - } - } - - T * allocate() - { - std::unique_lock< std::mutex > lock( mutex ); - if( ! keep_allocating ) - return nullptr; - - for( auto i = 0; i < C; i++ ) - { - if( is_free[i] ) - { - is_free[i] = false; - size++; - return &buffer[i]; - } - } - return nullptr; - } - - void deallocate( T * item ) - { - if( item < buffer || item >= buffer + C ) - { - throw invalid_value_exception( "Trying to return item to a heap that didn't allocate it!" ); - } - auto i = item - buffer; - auto old_value = std::move( buffer[i] ); - buffer[i] = std::move( T() ); - - { - std::unique_lock< std::mutex > lock( mutex ); - - is_free[i] = true; - size--; - - if( size == 0 ) - { - lock.unlock(); - cv.notify_one(); - } - } - } - - void stop_allocation() - { - std::unique_lock< std::mutex > lock( mutex ); - keep_allocating = false; - } - - void wait_until_empty() - { - std::unique_lock< std::mutex > lock( mutex ); - - const auto ready = [this]() { - return is_empty(); - }; - if( ! ready() - && ! cv.wait_for( lock, - std::chrono::hours( 1000 ), - ready ) ) // for some reason passing std::chrono::duration::max makes it return instantly - { - throw invalid_value_exception( "Could not flush one of the user controlled objects!" ); - } - } - - bool is_empty() const { return size == 0; } - int get_size() const { return size; } -}; - - -} // namespace librealsense +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2021 Intel Corporation. All Rights Reserved. + +#pragma once + +#include "librealsense-exception.h" + +#include +#include + + +namespace librealsense { + + +template < class T, int C > +class small_heap +{ + T buffer[C]; + bool is_free[C]; + std::mutex mutex; + bool keep_allocating = true; + std::condition_variable cv; + int size = 0; + +public: + static const int CAPACITY = C; + + small_heap() + { + for( auto i = 0; i < C; i++ ) + { + is_free[i] = true; + buffer[i] = std::move( T() ); + } + } + + T * allocate() + { + std::unique_lock< std::mutex > lock( mutex ); + if( ! keep_allocating ) + return nullptr; + + for( auto i = 0; i < C; i++ ) + { + if( is_free[i] ) + { + is_free[i] = false; + size++; + return &buffer[i]; + } + } + return nullptr; + } + + void deallocate( T * item ) + { + if( item < buffer || item >= buffer + C ) + { + throw invalid_value_exception( "Trying to return item to a heap that didn't allocate it!" ); + } + auto i = item - buffer; + auto old_value = std::move( buffer[i] ); + buffer[i] = std::move( T() ); + + { + std::unique_lock< std::mutex > lock( mutex ); + + is_free[i] = true; + size--; + + if( size == 0 ) + { + lock.unlock(); + cv.notify_one(); + } + } + } + + void stop_allocation() + { + std::unique_lock< std::mutex > lock( mutex ); + keep_allocating = false; + } + + void wait_until_empty() + { + std::unique_lock< std::mutex > lock( mutex ); + + const auto ready = [this]() { + return is_empty(); + }; + if( ! ready() + && ! cv.wait_for( lock, + std::chrono::hours( 1000 ), + ready ) ) // for some reason passing std::chrono::duration::max makes it return instantly + { + throw invalid_value_exception( "Could not flush one of the user controlled objects!" ); + } + } + + bool is_empty() const { return size == 0; } + int get_size() const { return size; } +}; + + +} // namespace librealsense