From 28652a53d7318f72c9c473b9a092cb3adbff5846 Mon Sep 17 00:00:00 2001 From: Raphael Dumusc Date: Fri, 23 Sep 2016 09:42:05 +0200 Subject: [PATCH] Replace boost with C++11 where applicable [DISCL-391] Notes: - FramePtr must remain a boost::shared_ptr as long as Tide is serializing it and does not mandate boost >= 1.56. - boost::signals2 for Stream::disconnected is hard to replace, however it is only used internally by QmlStreamerImpl.cpp. - program_options and unit_test could be optional. --- CMakeLists.txt | 7 ++- apps/DesktopStreamer/MainWindow.cpp | 2 + apps/SimpleStreamer/main.cpp | 3 +- deflect/FrameDispatcher.cpp | 2 + deflect/ImageSegmenter.cpp | 2 +- deflect/ImageSegmenter.h | 6 +-- deflect/ReceiveBuffer.cpp | 12 ++--- deflect/Server.cpp | 4 +- deflect/Stream.h | 12 ++--- deflect/StreamPrivate.cpp | 4 +- deflect/StreamSendWorker.cpp | 10 ++-- deflect/StreamSendWorker.h | 22 ++++----- deflect/qt/QmlStreamerImpl.cpp | 3 +- doc/Changelog.md | 3 ++ tests/cpp/ImageSegmenterTests.cpp | 17 ++++--- tests/cpp/SegmentDecoderTests.cpp | 6 +-- tests/cpp/perf/benchmarkStreamer.cpp | 46 ++++--------------- tests/cpp/perf/streamTests.cpp | 31 ++----------- tests/mock/CMakeLists.txt | 1 + tests/mock/Timer.h | 69 ++++++++++++++++++++++++++++ 20 files changed, 137 insertions(+), 125 deletions(-) create mode 100644 tests/mock/Timer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d264d5c..daf2cdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,15 +17,14 @@ set(DEFLECT_LICENSE BSD) set(DEFLECT_DEPENDENT_LIBRARIES Boost) set(DEFLECT_DEB_DEPENDS freeglut3-dev libxi-dev libxmu-dev libjpeg-turbo8-dev libturbojpeg - libboost-date-time-dev libboost-program-options-dev libboost-system-dev - libboost-test-dev libboost-thread-dev + libboost-program-options-dev libboost-test-dev qtbase5-dev qtdeclarative5-dev) set(DEFLECT_PORT_DEPENDS boost freeglut qt5) include(Common) -common_find_package(Boost REQUIRED COMPONENTS date_time program_options system - thread unit_test_framework) +common_find_package(Boost REQUIRED COMPONENTS program_options + unit_test_framework) common_find_package(GLUT) common_find_package(LibJpegTurbo REQUIRED) common_find_package(OpenGL) diff --git a/apps/DesktopStreamer/MainWindow.cpp b/apps/DesktopStreamer/MainWindow.cpp index 9f246a1..b70eb61 100644 --- a/apps/DesktopStreamer/MainWindow.cpp +++ b/apps/DesktopStreamer/MainWindow.cpp @@ -49,7 +49,9 @@ #include #include +#include #include +#include #ifdef _WIN32 typedef __int32 int32_t; diff --git a/apps/SimpleStreamer/main.cpp b/apps/SimpleStreamer/main.cpp index 78daa5a..c8ea07b 100644 --- a/apps/SimpleStreamer/main.cpp +++ b/apps/SimpleStreamer/main.cpp @@ -41,8 +41,9 @@ #include -#include +#include #include +#include #ifdef __APPLE__ # include diff --git a/deflect/FrameDispatcher.cpp b/deflect/FrameDispatcher.cpp index e8a4c7e..381369a 100644 --- a/deflect/FrameDispatcher.cpp +++ b/deflect/FrameDispatcher.cpp @@ -42,6 +42,8 @@ #include "Frame.h" #include "ReceiveBuffer.h" +#include + namespace deflect { diff --git a/deflect/ImageSegmenter.cpp b/deflect/ImageSegmenter.cpp index 5ddf731..71ed160 100644 --- a/deflect/ImageSegmenter.cpp +++ b/deflect/ImageSegmenter.cpp @@ -1,5 +1,5 @@ /*********************************************************************/ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project */ +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project */ /* Raphael Dumusc */ /* Stefan.Eilemann@epfl.ch */ /* All rights reserved. */ diff --git a/deflect/ImageSegmenter.h b/deflect/ImageSegmenter.h index c5d8c51..0755093 100644 --- a/deflect/ImageSegmenter.h +++ b/deflect/ImageSegmenter.h @@ -1,5 +1,5 @@ /*********************************************************************/ -/* Copyright (c) 2013-2015, EPFL/Blue Brain Project */ +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project */ /* Raphael Dumusc */ /* Stefan.Eilemann@epfl.ch */ /* All rights reserved. */ @@ -47,7 +47,7 @@ #include #include -#include +#include #include namespace deflect @@ -63,7 +63,7 @@ class ImageSegmenter DEFLECT_API ImageSegmenter(); /** Function called on each segment. */ - typedef boost::function< bool( const Segment& ) > Handler; + using Handler = std::function< bool( const Segment& ) >; /** * Generate segments. diff --git a/deflect/ReceiveBuffer.cpp b/deflect/ReceiveBuffer.cpp index 35fbc0e..d8934dc 100644 --- a/deflect/ReceiveBuffer.cpp +++ b/deflect/ReceiveBuffer.cpp @@ -39,6 +39,8 @@ #include "ReceiveBuffer.h" +#include + namespace deflect { @@ -91,10 +93,9 @@ bool ReceiveBuffer::hasCompleteFrame() const assert( !_sourceBuffers.empty( )); // Check if all sources for Stream have reached the same index - for( SourceBufferMap::const_iterator it = _sourceBuffers.begin(); - it != _sourceBuffers.end(); ++it ) + for( const auto& kv : _sourceBuffers ) { - const SourceBuffer& buffer = it->second; + const auto& buffer = kv.second; if( buffer.backFrameIndex <= _lastFrameComplete ) return false; } @@ -104,10 +105,9 @@ bool ReceiveBuffer::hasCompleteFrame() const Segments ReceiveBuffer::popFrame() { Segments frame; - for( SourceBufferMap::iterator it = _sourceBuffers.begin(); - it != _sourceBuffers.end(); ++it ) + for( auto& kv : _sourceBuffers ) { - SourceBuffer& buffer = it->second; + auto& buffer = kv.second; frame.insert( frame.end(), buffer.segments.front().begin(), buffer.segments.front().end( )); buffer.pop(); diff --git a/deflect/Server.cpp b/deflect/Server.cpp index f6d0b9f..4ad9085 100644 --- a/deflect/Server.cpp +++ b/deflect/Server.cpp @@ -46,7 +46,6 @@ #ifdef DEFLECT_USE_SERVUS # include -# include #endif #include @@ -77,8 +76,7 @@ Server::Server( const int port ) { if( !listen( QHostAddress::Any, port )) { - const QString err = - QString( "could not listen on port: %1" ).arg( port ); + const auto err = QString( "could not listen on port: %1" ).arg( port ); throw std::runtime_error( err.toStdString( )); } #ifdef DEFLECT_USE_SERVUS diff --git a/deflect/Stream.h b/deflect/Stream.h index 54c260a..84be494 100644 --- a/deflect/Stream.h +++ b/deflect/Stream.h @@ -47,17 +47,11 @@ #include #include +#include #include #include -#ifndef Q_MOC_RUN // See: https://bugreports.qt-project.org/browse/QTBUG-22829 -// needed for future.hpp with Boost 1.41 -# include -# include - -# include -# include -#endif +#include class Application; @@ -132,7 +126,7 @@ class Stream /** @name Asynchronous send API */ //@{ /** Future signaling success of asyncSend(). @version 1.1 */ - typedef boost::unique_future< bool > Future; + using Future = std::future< bool >; /** * Send an image and finish the frame asynchronously. diff --git a/deflect/StreamPrivate.cpp b/deflect/StreamPrivate.cpp index 641c3d4..892d33c 100644 --- a/deflect/StreamPrivate.cpp +++ b/deflect/StreamPrivate.cpp @@ -128,8 +128,8 @@ bool StreamPrivate::send( const ImageWrapper& image ) return false; } - const ImageSegmenter::Handler sendFunc = - boost::bind( &StreamPrivate::sendPixelStreamSegment, this, _1 ); + const auto sendFunc = std::bind( &StreamPrivate::sendPixelStreamSegment, + this, std::placeholders::_1 ); return imageSegmenter.generate( image, sendFunc ); } diff --git a/deflect/StreamSendWorker.cpp b/deflect/StreamSendWorker.cpp index 144caac..42d2b6a 100644 --- a/deflect/StreamSendWorker.cpp +++ b/deflect/StreamSendWorker.cpp @@ -1,5 +1,5 @@ /*********************************************************************/ -/* Copyright (c) 2013-2014, EPFL/Blue Brain Project */ +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project */ /* Daniel.Nachbaur@epfl.ch */ /* All rights reserved. */ /* */ @@ -47,7 +47,7 @@ namespace deflect StreamSendWorker::StreamSendWorker( StreamPrivate& stream ) : _stream( stream ) , _running( true ) - , _thread( boost::bind( &StreamSendWorker::_run, this )) + , _thread( std::bind( &StreamSendWorker::_run, this )) {} StreamSendWorker::~StreamSendWorker() @@ -57,7 +57,7 @@ StreamSendWorker::~StreamSendWorker() void StreamSendWorker::_run() { - boost::mutex::scoped_lock lock( _mutex ); + std::unique_lock lock( _mutex ); while( true ) { while( _requests.empty() && _running ) @@ -75,7 +75,7 @@ void StreamSendWorker::_run() void StreamSendWorker::_stop() { { - boost::mutex::scoped_lock lock( _mutex ); + std::lock_guard lock( _mutex ); _running = false; _condition.notify_all(); } @@ -90,7 +90,7 @@ void StreamSendWorker::_stop() Stream::Future StreamSendWorker::enqueueImage( const ImageWrapper& image ) { - boost::mutex::scoped_lock lock( _mutex ); + std::lock_guard lock( _mutex ); PromisePtr promise( new Promise ); _requests.push_back( Request( promise, image )); _condition.notify_all(); diff --git a/deflect/StreamSendWorker.h b/deflect/StreamSendWorker.h index b6847c5..abc8cbe 100644 --- a/deflect/StreamSendWorker.h +++ b/deflect/StreamSendWorker.h @@ -1,5 +1,5 @@ /*********************************************************************/ -/* Copyright (c) 2013-2014, EPFL/Blue Brain Project */ +/* Copyright (c) 2013-2016, EPFL/Blue Brain Project */ /* Daniel.Nachbaur@epfl.ch */ /* All rights reserved. */ /* */ @@ -40,12 +40,8 @@ #ifndef DEFLECT_STREAMSENDWORKER_H #define DEFLECT_STREAMSENDWORKER_H -// needed for future.hpp with Boost 1.41 -#include -#include - -#include -#include +#include +#include #include #include "Stream.h" // Stream::Future @@ -76,16 +72,16 @@ class StreamSendWorker /** Stop the worker and clear any pending image send requests. */ void _stop(); - typedef boost::promise< bool > Promise; - typedef boost::shared_ptr< Promise > PromisePtr; - typedef std::pair< PromisePtr, ImageWrapper > Request; + using Promise = std::promise< bool >; + using PromisePtr = std::shared_ptr< Promise >; + using Request = std::pair< PromisePtr, ImageWrapper >; StreamPrivate& _stream; std::deque< Request > _requests; - boost::mutex _mutex; - boost::condition _condition; + std::mutex _mutex; + std::condition_variable _condition; bool _running; - boost::thread _thread; + std::thread _thread; }; } diff --git a/deflect/qt/QmlStreamerImpl.cpp b/deflect/qt/QmlStreamerImpl.cpp index 2ac712a..91884a6 100644 --- a/deflect/qt/QmlStreamerImpl.cpp +++ b/deflect/qt/QmlStreamerImpl.cpp @@ -436,8 +436,7 @@ bool QmlStreamer::Impl::_setupDeflectStream() if( !_stream->isConnected( )) return false; - _stream->disconnected.connect( - boost::bind( &QmlStreamer::Impl::streamClosed, this )); + _stream->disconnected.connect( [this](){ emit streamClosed(); } ); if( !_stream->registerForEvents( )) return false; diff --git a/doc/Changelog.md b/doc/Changelog.md index 8c6be9b..8463fc8 100644 --- a/doc/Changelog.md +++ b/doc/Changelog.md @@ -5,6 +5,9 @@ Changelog {#Changelog} ### 0.12.0 (git master) +* [130](https://github.com/BlueBrain/Deflect/pull/130) + Replaced boost by C++11 where applicable. It is still required in two places: + Stream::disconnected signal, FramePtr (for serialization with boost in Tide). * [129](https://github.com/BlueBrain/Deflect/pull/129) Cleared Deflect from boost::serialization that was used exclusively by Tide. * [128](https://github.com/BlueBrain/Deflect/pull/128) diff --git a/tests/cpp/ImageSegmenterTests.cpp b/tests/cpp/ImageSegmenterTests.cpp index 9bcb6c4..c982052 100644 --- a/tests/cpp/ImageSegmenterTests.cpp +++ b/tests/cpp/ImageSegmenterTests.cpp @@ -46,7 +46,6 @@ namespace ut = boost::unit_test; #include #include -#include static bool append( deflect::Segments& segments, const deflect::Segment& segment ) @@ -74,8 +73,8 @@ BOOST_AUTO_TEST_CASE( testImageSegmenterSegmentParameters ) deflect::ImageWrapper imageWrapper( data, 4, 8, deflect::RGB ); deflect::Segments segments; - const deflect::ImageSegmenter::Handler appendFunc = - boost::bind( &append, boost::ref( segments ), _1 ); + const auto appendFunc = std::bind( &append, std::ref( segments ), + std::placeholders::_1 ); { deflect::ImageSegmenter segmenter; @@ -164,8 +163,8 @@ BOOST_AUTO_TEST_CASE( testImageSegmenterSingleSegmentData ) deflect::ImageSegmenter segmenter; deflect::Segments segments; - const deflect::ImageSegmenter::Handler appendFunc = - boost::bind( &append, boost::ref( segments ), _1 ); + const auto appendFunc = std::bind( &append, std::ref( segments ), + std::placeholders::_1 ); segmenter.generate( imageWrapper, appendFunc ); BOOST_REQUIRE_EQUAL( segments.size(), 1 ); @@ -226,8 +225,8 @@ BOOST_AUTO_TEST_CASE( testImageSegmenterUniformSegmentationData ) deflect::ImageSegmenter segmenter; deflect::Segments segments; - const deflect::ImageSegmenter::Handler appendFunc = - boost::bind( &append, boost::ref( segments ), _1 ); + const auto appendFunc = std::bind( &append, std::ref( segments ), + std::placeholders::_1 ); segmenter.setNominalSegmentDimensions( 2, 4 ); segmenter.generate( imageWrapper, appendFunc ); @@ -301,8 +300,8 @@ BOOST_AUTO_TEST_CASE( testImageSegmenterNonUniformSegmentationData ) deflect::ImageSegmenter segmenter; deflect::Segments segments; - const deflect::ImageSegmenter::Handler appendFunc = - boost::bind( &append, boost::ref( segments ), _1 ); + const auto appendFunc = std::bind( &append, std::ref( segments ), + std::placeholders::_1 ); segmenter.setNominalSegmentDimensions( 3, 5 ); segmenter.generate( imageWrapper, appendFunc ); diff --git a/tests/cpp/SegmentDecoderTests.cpp b/tests/cpp/SegmentDecoderTests.cpp index cc9e2d1..0ef932f 100644 --- a/tests/cpp/SegmentDecoderTests.cpp +++ b/tests/cpp/SegmentDecoderTests.cpp @@ -48,8 +48,6 @@ namespace ut = boost::unit_test; #include #include -#include - #include void fillTestImage( std::vector& data ) @@ -114,8 +112,8 @@ BOOST_AUTO_TEST_CASE( testImageSegmentationWithCompressionAndDecompression ) deflect::Segments segments; deflect::ImageSegmenter segmenter; - const deflect::ImageSegmenter::Handler appendFunc = - boost::bind( &append, boost::ref( segments ), _1 ); + const auto appendFunc = std::bind( &append, std::ref( segments ), + std::placeholders::_1 ); segmenter.generate( imageWrapper, appendFunc ); BOOST_REQUIRE_EQUAL( segments.size(), 1 ); diff --git a/tests/cpp/perf/benchmarkStreamer.cpp b/tests/cpp/perf/benchmarkStreamer.cpp index 67ff5e7..fa8c3b1 100644 --- a/tests/cpp/perf/benchmarkStreamer.cpp +++ b/tests/cpp/perf/benchmarkStreamer.cpp @@ -37,51 +37,25 @@ /* or implied, of The University of Texas at Austin. */ /*********************************************************************/ +#include "Timer.h" + #include #include #include #include -#include #include +#include +#include + #include #include -#include #include -#include -#include #define MEGABYTE 1000000 #define MICROSEC 1000000 -namespace -{ -class Timer -{ -public: - void start() - { - _lastTime = boost::posix_time::microsec_clock::universal_time(); - } - - void restart() - { - start(); - } - - float elapsed() - { - const boost::posix_time::ptime now = - boost::posix_time::microsec_clock::universal_time(); - return (float)(now - _lastTime).total_milliseconds(); - } - -private: - boost::posix_time::ptime _lastTime; -}; -} - struct BenchmarkOptions { BenchmarkOptions( int& argc, char** argv ) @@ -242,8 +216,8 @@ class Application deflectImage.compressionPolicy = deflect::COMPRESSION_ON; deflectImage.compressionQuality = _options.quality; - const deflect::ImageSegmenter::Handler appendHandler = - boost::bind( &append, boost::ref( _jpegSegments ), _1 ); + const auto appendHandler = std::bind( &append, std::ref( _jpegSegments ), + std::placeholders::_1 ); return _stream->_impl->imageSegmenter.generate( deflectImage, appendHandler ); @@ -300,7 +274,7 @@ class Application private: const BenchmarkOptions& _options; QImage _noiseImage; - boost::scoped_ptr _stream; + std::unique_ptr _stream; deflect::Segments _jpegSegments; }; @@ -325,8 +299,8 @@ int main( int argc, char** argv ) while( streamOpen && ( options.nframes == 0 || counter < options.nframes )) { if( options.framerate ) - boost::this_thread::sleep( - boost::posix_time::microseconds( MICROSEC / options.framerate )); + std::this_thread::sleep_for( + std::chrono::microseconds( MICROSEC / options.framerate )); streamOpen = benchmarkStreamer.send(); ++counter; } diff --git a/tests/cpp/perf/streamTests.cpp b/tests/cpp/perf/streamTests.cpp index 931f755..3c3da70 100644 --- a/tests/cpp/perf/streamTests.cpp +++ b/tests/cpp/perf/streamTests.cpp @@ -39,13 +39,16 @@ #define BOOST_TEST_MODULE Stream #include -#include namespace ut = boost::unit_test; #include "MinimalGlobalQtApp.h" +#include "Timer.h" + #include #include +#include + #include // Tests local throughput of the streaming library by sending raw as well as @@ -67,32 +70,6 @@ namespace ut = boost::unit_test; BOOST_GLOBAL_FIXTURE( MinimalGlobalQtApp ); -namespace -{ -class Timer -{ -public: - void start() - { - _lastTime = boost::posix_time::microsec_clock::universal_time(); - } - - void restart() - { - start(); - } - - float elapsed() - { - const boost::posix_time::ptime now = - boost::posix_time::microsec_clock::universal_time(); - return (float)(now - _lastTime).total_milliseconds(); - } -private: - boost::posix_time::ptime _lastTime; -}; -} - class DCThread : public QThread { void run() diff --git a/tests/mock/CMakeLists.txt b/tests/mock/CMakeLists.txt index 83e176a..c4d773e 100644 --- a/tests/mock/CMakeLists.txt +++ b/tests/mock/CMakeLists.txt @@ -8,6 +8,7 @@ set(DEFLECTMOCK_HEADERS MinimalGlobalQtApp.h MockServer.h + Timer.h ) set(DEFLECTMOCK_SOURCES diff --git a/tests/mock/Timer.h b/tests/mock/Timer.h new file mode 100644 index 0000000..2fe0367 --- /dev/null +++ b/tests/mock/Timer.h @@ -0,0 +1,69 @@ +/*********************************************************************/ +/* Copyright (c) 2016, EPFL/Blue Brain Project */ +/* Raphael Dumusc */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or */ +/* without modification, are permitted provided that the following */ +/* conditions are met: */ +/* */ +/* 1. Redistributions of source code must retain the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer. */ +/* */ +/* 2. Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials */ +/* provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF TEXAS AT */ +/* AUSTIN ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, */ +/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ +/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT */ +/* AUSTIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */ +/* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR */ +/* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT */ +/* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/* POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* The views and conclusions contained in the software and */ +/* documentation are those of the authors and should not be */ +/* interpreted as representing official policies, either expressed */ +/* or implied, of Ecole polytechnique federale de Lausanne. */ +/*********************************************************************/ + +#ifndef TIMER_H +#define TIMER_H + +#include + +class Timer +{ +public: + void start() + { + _startTime = std::chrono::high_resolution_clock::now(); + } + + void restart() + { + start(); + } + + float elapsed() + { + const auto now = std::chrono::high_resolution_clock::now(); + std::chrono::duration fp_ms = now - _startTime; + return fp_ms.count(); + } + +private: + std::chrono::high_resolution_clock::time_point _startTime; +}; + +#endif