diff options
27 files changed, 1009 insertions, 179 deletions
diff --git a/common_audio/resampler/push_resampler.cc b/common_audio/resampler/push_resampler.cc index 92775afb..29944187 100644 --- a/common_audio/resampler/push_resampler.cc +++ b/common_audio/resampler/push_resampler.cc @@ -19,9 +19,7 @@ namespace webrtc { PushResampler::PushResampler() - : sinc_resampler_(NULL), - sinc_resampler_right_(NULL), - src_sample_rate_hz_(0), + : src_sample_rate_hz_(0), dst_sample_rate_hz_(0), num_channels_(0), src_left_(NULL), diff --git a/common_audio/resampler/push_sinc_resampler.cc b/common_audio/resampler/push_sinc_resampler.cc index 886d7633..1fb72dc7 100644 --- a/common_audio/resampler/push_sinc_resampler.cc +++ b/common_audio/resampler/push_sinc_resampler.cc @@ -17,14 +17,13 @@ namespace webrtc { PushSincResampler::PushSincResampler(int source_frames, int destination_frames) - : resampler_(NULL), + : resampler_(new SincResampler(source_frames * 1.0 / destination_frames, + source_frames, this)), float_buffer_(new float[destination_frames]), source_ptr_(NULL), destination_frames_(destination_frames), first_pass_(true), source_available_(0) { - resampler_.reset(new SincResampler(source_frames * 1.0 / destination_frames, - source_frames, this)); } PushSincResampler::~PushSincResampler() { diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c b/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c index a1dced98..9c4e5875 100644 --- a/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c +++ b/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c @@ -8,20 +8,14 @@ * be found in the AUTHORS file in the root of the source tree. */ -/* - * pitch_estimator.c - * - * Pitch filter functions - * - */ +#include "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h" #ifdef WEBRTC_ARCH_ARM_NEON #include <arm_neon.h> #endif -#include "pitch_estimator.h" -#include "signal_processing_library.h" -#include "system_wrappers/interface/compile_assert.h" +#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" +#include "webrtc/system_wrappers/interface/compile_assert_c.h" /* log2[0.2, 0.5, 0.98] in Q8 */ static const int16_t kLogLagWinQ8[3] = { diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c b/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c index df961a7a..c3db01c6 100644 --- a/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c +++ b/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c @@ -8,18 +8,12 @@ * be found in the AUTHORS file in the root of the source tree. */ -/* - * pitch_filter.c - * - * Pitch filter functions - * - */ +#include "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h" -#include "common_audio/signal_processing/include/signal_processing_library.h" -#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h" -#include "modules/audio_coding/codecs/isac/fix/source/settings.h" -#include "modules/audio_coding/codecs/isac/fix/source/structs.h" -#include "system_wrappers/interface/compile_assert.h" +#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" +#include "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h" +#include "webrtc/modules/audio_coding/codecs/isac/fix/source/structs.h" +#include "webrtc/system_wrappers/interface/compile_assert_c.h" // Number of segments in a pitch subframe. static const int kSegments = 5; diff --git a/modules/audio_coding/main/acm2/audio_coding_module_impl.cc b/modules/audio_coding/main/acm2/audio_coding_module_impl.cc index 911605e8..59d5727a 100644 --- a/modules/audio_coding/main/acm2/audio_coding_module_impl.cc +++ b/modules/audio_coding/main/acm2/audio_coding_module_impl.cc @@ -140,7 +140,6 @@ AudioCodingModuleImpl::AudioCodingModuleImpl(int id) receiver_initialized_(false), callback_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), secondary_send_codec_inst_(), - secondary_encoder_(NULL), codec_timestamp_(expected_codec_ts_), first_10ms_data_(false) { diff --git a/modules/audio_coding/main/source/audio_coding_module_impl.cc b/modules/audio_coding/main/source/audio_coding_module_impl.cc index 62a13c57..38027338 100644 --- a/modules/audio_coding/main/source/audio_coding_module_impl.cc +++ b/modules/audio_coding/main/source/audio_coding_module_impl.cc @@ -154,7 +154,6 @@ AudioCodingModuleImpl::AudioCodingModuleImpl(const int32_t id, Clock* clock) last_detected_tone_(kACMToneEnd), callback_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), secondary_send_codec_inst_(), - secondary_encoder_(NULL), initial_delay_ms_(0), num_packets_accumulated_(0), num_bytes_accumulated_(0), diff --git a/modules/audio_coding/neteq4/neteq_impl.cc b/modules/audio_coding/neteq4/neteq_impl.cc index 4ed39764..a5c45ff7 100644 --- a/modules/audio_coding/neteq4/neteq_impl.cc +++ b/modules/audio_coding/neteq4/neteq_impl.cc @@ -59,8 +59,7 @@ NetEqImpl::NetEqImpl(int fs, PacketBuffer* packet_buffer, PayloadSplitter* payload_splitter, TimestampScaler* timestamp_scaler) - : background_noise_(NULL), - buffer_level_filter_(buffer_level_filter), + : buffer_level_filter_(buffer_level_filter), decoder_database_(decoder_database), delay_manager_(delay_manager), delay_peak_detector_(delay_peak_detector), @@ -70,14 +69,6 @@ NetEqImpl::NetEqImpl(int fs, payload_splitter_(payload_splitter), timestamp_scaler_(timestamp_scaler), vad_(new PostDecodeVad()), - algorithm_buffer_(NULL), - sync_buffer_(NULL), - expand_(NULL), - normal_(NULL), - merge_(NULL), - accelerate_(NULL), - preemptive_expand_(NULL), - comfort_noise_(NULL), last_mode_(kModeNormal), mute_factor_array_(NULL), decoded_buffer_length_(kMaxFrameSize), diff --git a/modules/audio_conference_mixer/source/audio_conference_mixer_impl.cc b/modules/audio_conference_mixer/source/audio_conference_mixer_impl.cc index da16814d..c5cf137f 100644 --- a/modules/audio_conference_mixer/source/audio_conference_mixer_impl.cc +++ b/modules/audio_conference_mixer/source/audio_conference_mixer_impl.cc @@ -124,8 +124,6 @@ AudioConferenceMixerImpl::AudioConferenceMixerImpl(int id) _scratchMixedParticipants(), _scratchVadPositiveParticipantsAmount(0), _scratchVadPositiveParticipants(), - _crit(NULL), - _cbCrit(NULL), _id(id), _minimumMixingFreq(kLowestPossible), _mixReceiver(NULL), @@ -142,8 +140,7 @@ AudioConferenceMixerImpl::AudioConferenceMixerImpl(int id) _timeStamp(0), _timeScheduler(kProcessPeriodicityInMs), _mixedAudioLevel(), - _processCalls(0), - _limiter(NULL) + _processCalls(0) {} bool AudioConferenceMixerImpl::Init() diff --git a/modules/audio_processing/aecm/aecm_core.c b/modules/audio_processing/aecm/aecm_core.c index a44ce08d..2c0a40f0 100644 --- a/modules/audio_processing/aecm/aecm_core.c +++ b/modules/audio_processing/aecm/aecm_core.c @@ -18,7 +18,7 @@ #include "webrtc/modules/audio_processing/aecm/include/echo_control_mobile.h" #include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" #include "webrtc/modules/audio_processing/utility/ring_buffer.h" -#include "webrtc/system_wrappers/interface/compile_assert.h" +#include "webrtc/system_wrappers/interface/compile_assert_c.h" #include "webrtc/system_wrappers/interface/cpu_features_wrapper.h" #include "webrtc/typedefs.h" diff --git a/modules/audio_processing/utility/delay_estimator_wrapper.c b/modules/audio_processing/utility/delay_estimator_wrapper.c index c358f138..b72b8ffa 100644 --- a/modules/audio_processing/utility/delay_estimator_wrapper.c +++ b/modules/audio_processing/utility/delay_estimator_wrapper.c @@ -16,7 +16,7 @@ #include "webrtc/modules/audio_processing/utility/delay_estimator.h" #include "webrtc/modules/audio_processing/utility/delay_estimator_internal.h" -#include "webrtc/system_wrappers/interface/compile_assert.h" +#include "webrtc/system_wrappers/interface/compile_assert_c.h" // Only bit |kBandFirst| through bit |kBandLast| are processed and // |kBandFirst| - |kBandLast| must be < 32. diff --git a/modules/desktop_capture/win/cursor.cc b/modules/desktop_capture/win/cursor.cc index 6e0fd4eb..11bb2dbb 100644 --- a/modules/desktop_capture/win/cursor.cc +++ b/modules/desktop_capture/win/cursor.cc @@ -78,7 +78,8 @@ void AddCursorOutline(int width, int height, uint32_t* data) { // Premultiplies RGB components of the pixel data in the given image by // the corresponding alpha components. void AlphaMul(uint32_t* data, int width, int height) { - COMPILE_ASSERT(sizeof(uint32_t) == kBytesPerPixel); + COMPILE_ASSERT(sizeof(uint32_t) == kBytesPerPixel, + size_of_uint32_should_be_the_bytes_per_pixel); for (uint32_t* data_end = data + width * height; data != data_end; ++data) { RGBQUAD* from = reinterpret_cast<RGBQUAD*>(data); diff --git a/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc b/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc index bcd1d10c..1d8b2be3 100644 --- a/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc @@ -8,19 +8,20 @@ * be found in the AUTHORS file in the root of the source tree. */ - /* * This file includes unit tests for the VP8 packetizer. */ #include "testing/gtest/include/gtest/gtest.h" - -#include "webrtc/system_wrappers/interface/compile_assert.h" - #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h" +#include "webrtc/system_wrappers/interface/compile_assert.h" #include "webrtc/typedefs.h" +#define CHECK_ARRAY_SIZE(expected_size, array) \ + COMPILE_ASSERT(expected_size == sizeof(array) / sizeof(array[0]), \ + check_array_size); + namespace webrtc { class RtpFormatVp8Test : public ::testing::Test { @@ -63,10 +64,8 @@ TEST_F(RtpFormatVp8Test, TestStrictMode) { const bool kExpectedFragStart[] = {true, false, true, true, false, false, false}; const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedPart) / sizeof(kExpectedPart[0])); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0])); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart); helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, kExpectedFragStart, kExpectedNum); @@ -91,10 +90,8 @@ TEST_F(RtpFormatVp8Test, TestAggregateMode) { const int kExpectedPart[] = {0, 0, 0, 1}; const bool kExpectedFragStart[] = {true, false, false, true}; const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedPart) / sizeof(kExpectedPart[0])); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0])); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart); helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, kExpectedFragStart, kExpectedNum); @@ -119,10 +116,8 @@ TEST_F(RtpFormatVp8Test, TestAggregateModeManyPartitions1) { const int kExpectedPart[] = {0, 0, 1, 5}; const bool kExpectedFragStart[] = {true, false, true, true}; const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedPart) / sizeof(kExpectedPart[0])); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0])); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart); helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, kExpectedFragStart, kExpectedNum); @@ -147,10 +142,8 @@ TEST_F(RtpFormatVp8Test, TestAggregateModeManyPartitions2) { const int kExpectedPart[] = {0, 0, 1, 4, 4, 5}; const bool kExpectedFragStart[] = {true, false, true, true, false, true}; const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedPart) / sizeof(kExpectedPart[0])); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0])); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart); helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, kExpectedFragStart, kExpectedNum); @@ -175,10 +168,8 @@ TEST_F(RtpFormatVp8Test, TestAggregateModeTwoLargePartitions) { const int kExpectedPart[] = {0, 0, 1, 1}; const bool kExpectedFragStart[] = {true, false, true, false}; const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedPart) / sizeof(kExpectedPart[0])); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0])); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart); helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, kExpectedFragStart, kExpectedNum); @@ -203,10 +194,8 @@ TEST_F(RtpFormatVp8Test, TestEqualSizeModeFallback) { // Frag start only true for first packet in equal size mode. const bool kExpectedFragStart[] = {true, false, false, false}; const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedPart) / sizeof(kExpectedPart[0])); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0])); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart); helper_->set_sloppy_partitioning(true); helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, @@ -232,10 +221,8 @@ TEST_F(RtpFormatVp8Test, TestNonReferenceBit) { // Frag start only true for first packet in equal size mode. const bool kExpectedFragStart[] = {true, false}; const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedPart) / sizeof(kExpectedPart[0])); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0])); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart); helper_->set_sloppy_partitioning(true); helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, @@ -265,10 +252,8 @@ TEST_F(RtpFormatVp8Test, TestTl0PicIdxAndTID) { const int kExpectedPart[1] = {0}; // Packet starts with partition 0. const bool kExpectedFragStart[1] = {true}; const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedPart) / sizeof(kExpectedPart[0])); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0])); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart); helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, kExpectedFragStart, kExpectedNum); @@ -295,10 +280,8 @@ TEST_F(RtpFormatVp8Test, TestKeyIdx) { const int kExpectedPart[1] = {0}; // Packet starts with partition 0. const bool kExpectedFragStart[1] = {true}; const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedPart) / sizeof(kExpectedPart[0])); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0])); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart); helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, kExpectedFragStart, kExpectedNum); @@ -326,10 +309,8 @@ TEST_F(RtpFormatVp8Test, TestTIDAndKeyIdx) { const int kExpectedPart[1] = {0}; // Packet starts with partition 0. const bool kExpectedFragStart[1] = {true}; const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedPart) / sizeof(kExpectedPart[0])); - COMPILE_ASSERT(kExpectedNum == - sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0])); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart); + CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart); helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, kExpectedFragStart, kExpectedNum); diff --git a/modules/video_coding/main/test/rtp_player.cc b/modules/video_coding/main/test/rtp_player.cc index 6af43893..99651431 100644 --- a/modules/video_coding/main/test/rtp_player.cc +++ b/modules/video_coding/main/test/rtp_player.cc @@ -326,7 +326,6 @@ class RtpPlayerImpl : public RtpPlayerInterface { float loss_rate, uint32_t rtt_ms, bool reordering) : ssrc_handlers_(payload_sink_factory, payload_types), clock_(clock), - packet_source_(NULL), next_rtp_time_(0), first_packet_(true), first_packet_rtp_time_(0), diff --git a/system_wrappers/interface/asm_defines.h b/system_wrappers/interface/asm_defines.h index c432ec0e..4b839a95 100644 --- a/system_wrappers/interface/asm_defines.h +++ b/system_wrappers/interface/asm_defines.h @@ -56,4 +56,4 @@ strheq \reg1, \reg2, \num .text -#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_ +#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ASM_DEFINES_H_ diff --git a/system_wrappers/interface/compile_assert.h b/system_wrappers/interface/compile_assert.h index 4feda86c..0c8776d2 100644 --- a/system_wrappers/interface/compile_assert.h +++ b/system_wrappers/interface/compile_assert.h @@ -8,14 +8,73 @@ * be found in the AUTHORS file in the root of the source tree. */ +// Borrowed from Chromium's src/base/basictypes.h. + #ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_ #define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_ -/* Use this macro to verify at compile time that certain restrictions are met. - * The argument is the boolean expression to evaluate. - * Example: - * COMPILE_ASSERT(sizeof(foo) < 128); -*/ -#define COMPILE_ASSERT(expression) switch(0){case 0: case expression:;} +// The COMPILE_ASSERT macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. + +template <bool> +struct CompileAssert { +}; + +#undef COMPILE_ASSERT +#define COMPILE_ASSERT(expr, msg) \ + typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] + +// Implementation details of COMPILE_ASSERT: +// +// - COMPILE_ASSERT works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outer parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert<bool(expr)> +// +// instead, these compilers will refuse to compile +// +// COMPILE_ASSERT(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_ diff --git a/system_wrappers/interface/compile_assert_c.h b/system_wrappers/interface/compile_assert_c.h new file mode 100644 index 00000000..d9ba8660 --- /dev/null +++ b/system_wrappers/interface/compile_assert_c.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_ +#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_ + +// Only use this for C files. For C++, use compile_assert.h. +// +// Use this macro to verify at compile time that certain restrictions are met. +// The argument is the boolean expression to evaluate. +// Example: +// COMPILE_ASSERT(sizeof(foo) < 128); +#define COMPILE_ASSERT(expression) switch (0) {case 0: case expression:;} + +#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_ diff --git a/system_wrappers/interface/move.h b/system_wrappers/interface/move.h new file mode 100644 index 00000000..d828c32a --- /dev/null +++ b/system_wrappers/interface/move.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Borrowed from Chromium's src/base/move.h. + +#ifndef WEBRTC_SYSTEM_WRAPPERS_INTEFACE_MOVE_H_ +#define WEBRTC_SYSTEM_WRAPPERS_INTEFACE_MOVE_H_ + +// Macro with the boilerplate that makes a type move-only in C++03. +// +// USAGE +// +// This macro should be used instead of DISALLOW_COPY_AND_ASSIGN to create +// a "move-only" type. Unlike DISALLOW_COPY_AND_ASSIGN, this macro should be +// the first line in a class declaration. +// +// A class using this macro must call .Pass() (or somehow be an r-value already) +// before it can be: +// +// * Passed as a function argument +// * Used as the right-hand side of an assignment +// * Returned from a function +// +// Each class will still need to define their own "move constructor" and "move +// operator=" to make this useful. Here's an example of the macro, the move +// constructor, and the move operator= from the scoped_ptr class: +// +// template <typename T> +// class scoped_ptr { +// MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) +// public: +// scoped_ptr(RValue& other) : ptr_(other.release()) { } +// scoped_ptr& operator=(RValue& other) { +// swap(other); +// return *this; +// } +// }; +// +// Note that the constructor must NOT be marked explicit. +// +// For consistency, the second parameter to the macro should always be RValue +// unless you have a strong reason to do otherwise. It is only exposed as a +// macro parameter so that the move constructor and move operator= don't look +// like they're using a phantom type. +// +// +// HOW THIS WORKS +// +// For a thorough explanation of this technique, see: +// +// http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor +// +// The summary is that we take advantage of 2 properties: +// +// 1) non-const references will not bind to r-values. +// 2) C++ can apply one user-defined conversion when initializing a +// variable. +// +// The first lets us disable the copy constructor and assignment operator +// by declaring private version of them with a non-const reference parameter. +// +// For l-values, direct initialization still fails like in +// DISALLOW_COPY_AND_ASSIGN because the copy constructor and assignment +// operators are private. +// +// For r-values, the situation is different. The copy constructor and +// assignment operator are not viable due to (1), so we are trying to call +// a non-existent constructor and non-existing operator= rather than a private +// one. Since we have not committed an error quite yet, we can provide an +// alternate conversion sequence and a constructor. We add +// +// * a private struct named "RValue" +// * a user-defined conversion "operator RValue()" +// * a "move constructor" and "move operator=" that take the RValue& as +// their sole parameter. +// +// Only r-values will trigger this sequence and execute our "move constructor" +// or "move operator=." L-values will match the private copy constructor and +// operator= first giving a "private in this context" error. This combination +// gives us a move-only type. +// +// For signaling a destructive transfer of data from an l-value, we provide a +// method named Pass() which creates an r-value for the current instance +// triggering the move constructor or move operator=. +// +// Other ways to get r-values is to use the result of an expression like a +// function call. +// +// Here's an example with comments explaining what gets triggered where: +// +// class Foo { +// MOVE_ONLY_TYPE_FOR_CPP_03(Foo, RValue); +// +// public: +// ... API ... +// Foo(RValue other); // Move constructor. +// Foo& operator=(RValue rhs); // Move operator= +// }; +// +// Foo MakeFoo(); // Function that returns a Foo. +// +// Foo f; +// Foo f_copy(f); // ERROR: Foo(Foo&) is private in this context. +// Foo f_assign; +// f_assign = f; // ERROR: operator=(Foo&) is private in this context. +// +// +// Foo f(MakeFoo()); // R-value so alternate conversion executed. +// Foo f_copy(f.Pass()); // R-value so alternate conversion executed. +// f = f_copy.Pass(); // R-value so alternate conversion executed. +// +// +// IMPLEMENTATION SUBTLETIES WITH RValue +// +// The RValue struct is just a container for a pointer back to the original +// object. It should only ever be created as a temporary, and no external +// class should ever declare it or use it in a parameter. +// +// It is tempting to want to use the RValue type in function parameters, but +// excluding the limited usage here for the move constructor and move +// operator=, doing so would mean that the function could take both r-values +// and l-values equially which is unexpected. See COMPARED To Boost.Move for +// more details. +// +// An alternate, and incorrect, implementation of the RValue class used by +// Boost.Move makes RValue a fieldless child of the move-only type. RValue& +// is then used in place of RValue in the various operators. The RValue& is +// "created" by doing *reinterpret_cast<RValue*>(this). This has the appeal +// of never creating a temporary RValue struct even with optimizations +// disabled. Also, by virtue of inheritance you can treat the RValue +// reference as if it were the move-only type itself. Unfortunately, +// using the result of this reinterpret_cast<> is actually undefined behavior +// due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer +// will generate non-working code. +// +// In optimized builds, both implementations generate the same assembly so we +// choose the one that adheres to the standard. +// +// +// COMPARED TO C++11 +// +// In C++11, you would implement this functionality using an r-value reference +// and our .Pass() method would be replaced with a call to std::move(). +// +// This emulation also has a deficiency where it uses up the single +// user-defined conversion allowed by C++ during initialization. This can +// cause problems in some API edge cases. For instance, in scoped_ptr, it is +// impossible to make a function "void Foo(scoped_ptr<Parent> p)" accept a +// value of type scoped_ptr<Child> even if you add a constructor to +// scoped_ptr<> that would make it look like it should work. C++11 does not +// have this deficiency. +// +// +// COMPARED TO Boost.Move +// +// Our implementation similar to Boost.Move, but we keep the RValue struct +// private to the move-only type, and we don't use the reinterpret_cast<> hack. +// +// In Boost.Move, RValue is the boost::rv<> template. This type can be used +// when writing APIs like: +// +// void MyFunc(boost::rv<Foo>& f) +// +// that can take advantage of rv<> to avoid extra copies of a type. However you +// would still be able to call this version of MyFunc with an l-value: +// +// Foo f; +// MyFunc(f); // Uh oh, we probably just destroyed |f| w/o calling Pass(). +// +// unless someone is very careful to also declare a parallel override like: +// +// void MyFunc(const Foo& f) +// +// that would catch the l-values first. This was declared unsafe in C++11 and +// a C++11 compiler will explicitly fail MyFunc(f). Unfortunately, we cannot +// ensure this in C++03. +// +// Since we have no need for writing such APIs yet, our implementation keeps +// RValue private and uses a .Pass() method to do the conversion instead of +// trying to write a version of "std::move()." Writing an API like std::move() +// would require the RValue struct to be public. +// +// +// CAVEATS +// +// If you include a move-only type as a field inside a class that does not +// explicitly declare a copy constructor, the containing class's implicit +// copy constructor will change from Containing(const Containing&) to +// Containing(Containing&). This can cause some unexpected errors. +// +// http://llvm.org/bugs/show_bug.cgi?id=11528 +// +// The workaround is to explicitly declare your copy constructor. +// +#define MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \ + private: \ + struct rvalue_type { \ + explicit rvalue_type(type* object) : object(object) {} \ + type* object; \ + }; \ + type(type&); \ + void operator=(type&); \ + public: \ + operator rvalue_type() { return rvalue_type(this); } \ + type Pass() { return type(rvalue_type(this)); } \ + private: + +#endif // WEBRTC_SYSTEM_WRAPPERS_INTEFACE_MOVE_H_ diff --git a/system_wrappers/interface/scoped_ptr.h b/system_wrappers/interface/scoped_ptr.h index cfaf5cbe..a2a1b44e 100644 --- a/system_wrappers/interface/scoped_ptr.h +++ b/system_wrappers/interface/scoped_ptr.h @@ -1,118 +1,581 @@ -// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001, 2002 Peter Dimov +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Borrowed from Chromium's src/base/memory/scoped_ptr.h. + +// Scopers help you manage ownership of a pointer, helping you easily manage the +// a pointer within a scope, and automatically destroying the pointer at the +// end of a scope. There are two main classes you will use, which correspond +// to the operators new/delete and new[]/delete[]. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Example usage (scoped_ptr<T>): +// { +// scoped_ptr<Foo> foo(new Foo("wee")); +// } // foo goes out of scope, releasing the pointer with it. // -// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. +// { +// scoped_ptr<Foo> foo; // No pointer managed. +// foo.reset(new Foo("wee")); // Now a pointer is managed. +// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. +// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. +// foo->Method(); // Foo::Method() called. +// foo.get()->Method(); // Foo::Method() called. +// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer +// // manages a pointer. +// foo.reset(new Foo("wee4")); // foo manages a pointer again. +// foo.reset(); // Foo("wee4") destroyed, foo no longer +// // manages a pointer. +// } // foo wasn't managing a pointer, so nothing was destroyed. // +// Example usage (scoped_ptr<T[]>): +// { +// scoped_ptr<Foo[]> foo(new Foo[100]); +// foo.get()->Method(); // Foo::Method on the 0th element. +// foo[10].Method(); // Foo::Method on the 10th element. +// } +// +// These scopers also implement part of the functionality of C++11 unique_ptr +// in that they are "movable but not copyable." You can use the scopers in +// the parameter and return types of functions to signify ownership transfer +// in to and out of a function. When calling a function that has a scoper +// as the argument type, it must be called with the result of an analogous +// scoper's Pass() function or another function that generates a temporary; +// passing by copy will NOT work. Here is an example using scoped_ptr: +// +// void TakesOwnership(scoped_ptr<Foo> arg) { +// // Do something with arg +// } +// scoped_ptr<Foo> CreateFoo() { +// // No need for calling Pass() because we are constructing a temporary +// // for the return value. +// return scoped_ptr<Foo>(new Foo("new")); +// } +// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) { +// return arg.Pass(); +// } +// +// { +// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay"). +// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay"). +// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo. +// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2. +// PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL. +// } +// +// Notice that if you do not call Pass() when returning from PassThru(), or +// when invoking TakesOwnership(), the code will not compile because scopers +// are not copyable; they only implement move semantics which require calling +// the Pass() function to signify a destructive transfer of state. CreateFoo() +// is different though because we are constructing a temporary on the return +// line and thus can avoid needing to call Pass(). +// +// Pass() properly handles upcast in initialization, i.e. you can use a +// scoped_ptr<Child> to initialize a scoped_ptr<Parent>: +// +// scoped_ptr<Foo> foo(new Foo()); +// scoped_ptr<FooParent> parent(foo.Pass()); +// +// PassAs<>() should be used to upcast return value in return statement: +// +// scoped_ptr<Foo> CreateFoo() { +// scoped_ptr<FooChild> result(new FooChild()); +// return result.PassAs<Foo>(); +// } +// +// Note that PassAs<>() is implemented only for scoped_ptr<T>, but not for +// scoped_ptr<T[]>. This is because casting array pointers may not be safe. -// scoped_ptr mimics a built-in pointer except that it guarantees deletion -// of the object pointed to, either on destruction of the scoped_ptr or via -// an explicit reset(). scoped_ptr is a simple solution for simple needs; -// use shared_ptr or std::auto_ptr if your needs are more complex. - -// scoped_ptr_malloc added in by Google. When one of -// these goes out of scope, instead of doing a delete or delete[], it -// calls free(). scoped_ptr_malloc<char> is likely to see much more -// use than any other specializations. - -// release() added in by Google. Use this to conditionally -// transfer ownership of a heap-allocated object to the caller, usually on -// method success. #ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_ #define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_ -#include <assert.h> // for assert -#include <stddef.h> // for ptrdiff_t -#include <stdlib.h> // for free() decl +// This is an implementation designed to match the anticipated future TR2 +// implementation of the scoped_ptr class and scoped_ptr_malloc (deprecated). + +#include <assert.h> +#include <stddef.h> +#include <stdlib.h> -#ifdef _WIN32 -namespace std { using ::ptrdiff_t; }; -#endif // _WIN32 +#include <algorithm> // For std::swap(). + +#include "webrtc/system_wrappers/interface/compile_assert.h" +#include "webrtc/system_wrappers/interface/constructor_magic.h" +#include "webrtc/system_wrappers/interface/move.h" +#include "webrtc/system_wrappers/interface/template_util.h" +#include "webrtc/typedefs.h" namespace webrtc { -template <typename T> -class scoped_ptr { +// Function object which deletes its parameter, which must be a pointer. +// If C is an array type, invokes 'delete[]' on the parameter; otherwise, +// invokes 'delete'. The default deleter for scoped_ptr<T>. +template <class T> +struct DefaultDeleter { + DefaultDeleter() {} + template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) { + // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor + // if U* is implicitly convertible to T* and U is not an array type. + // + // Correct implementation should use SFINAE to disable this + // constructor. However, since there are no other 1-argument constructors, + // using a COMPILE_ASSERT() based on is_convertible<> and requiring + // complete types is simpler and will cause compile failures for equivalent + // misuses. + // + // Note, the is_convertible<U*, T*> check also ensures that U is not an + // array. T is guaranteed to be a non-array, so any U* where U is an array + // cannot convert to T*. + enum { T_must_be_complete = sizeof(T) }; + enum { U_must_be_complete = sizeof(U) }; + COMPILE_ASSERT((webrtc::is_convertible<U*, T*>::value), + U_ptr_must_implicitly_convert_to_T_ptr); + } + inline void operator()(T* ptr) const { + enum { type_must_be_complete = sizeof(T) }; + delete ptr; + } +}; + +// Specialization of DefaultDeleter for array types. +template <class T> +struct DefaultDeleter<T[]> { + inline void operator()(T* ptr) const { + enum { type_must_be_complete = sizeof(T) }; + delete[] ptr; + } + private: + // Disable this operator for any U != T because it is undefined to execute + // an array delete when the static type of the array mismatches the dynamic + // type. + // + // References: + // C++98 [expr.delete]p3 + // http://cplusplus.github.com/LWG/lwg-defects.html#938 + template <typename U> void operator()(U* array) const; +}; - T* ptr; +template <class T, int n> +struct DefaultDeleter<T[n]> { + // Never allow someone to declare something like scoped_ptr<int[10]>. + COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type); +}; - scoped_ptr(scoped_ptr const &); - scoped_ptr & operator=(scoped_ptr const &); +// Function object which invokes 'free' on its parameter, which must be +// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: +// +// scoped_ptr<int, webrtc::FreeDeleter> foo_ptr( +// static_cast<int*>(malloc(sizeof(int)))); +struct FreeDeleter { + inline void operator()(void* ptr) const { + free(ptr); + } +}; +namespace internal { + +// Minimal implementation of the core logic of scoped_ptr, suitable for +// reuse in both scoped_ptr and its specializations. +template <class T, class D> +class scoped_ptr_impl { public: + explicit scoped_ptr_impl(T* p) : data_(p) { } + + // Initializer for deleters that have data parameters. + scoped_ptr_impl(T* p, const D& d) : data_(p, d) {} + + // Templated constructor that destructively takes the value from another + // scoped_ptr_impl. + template <typename U, typename V> + scoped_ptr_impl(scoped_ptr_impl<U, V>* other) + : data_(other->release(), other->get_deleter()) { + // We do not support move-only deleters. We could modify our move + // emulation to have webrtc::subtle::move() and webrtc::subtle::forward() + // functions that are imperfect emulations of their C++11 equivalents, + // but until there's a requirement, just assume deleters are copyable. + } - typedef T element_type; + template <typename U, typename V> + void TakeState(scoped_ptr_impl<U, V>* other) { + // See comment in templated constructor above regarding lack of support + // for move-only deleters. + reset(other->release()); + get_deleter() = other->get_deleter(); + } - explicit scoped_ptr(T* p = NULL): ptr(p) {} + ~scoped_ptr_impl() { + if (data_.ptr != NULL) { + // Not using get_deleter() saves one function call in non-optimized + // builds. + static_cast<D&>(data_)(data_.ptr); + } + } - ~scoped_ptr() { - typedef char type_must_be_complete[sizeof(T)]; - delete ptr; + void reset(T* p) { + // This is a self-reset, which is no longer allowed: http://crbug.com/162971 + if (p != NULL && p == data_.ptr) + abort(); + + // Note that running data_.ptr = p can lead to undefined behavior if + // get_deleter()(get()) deletes this. In order to pevent this, reset() + // should update the stored pointer before deleting its old value. + // + // However, changing reset() to use that behavior may cause current code to + // break in unexpected ways. If the destruction of the owned object + // dereferences the scoped_ptr when it is destroyed by a call to reset(), + // then it will incorrectly dispatch calls to |p| rather than the original + // value of |data_.ptr|. + // + // During the transition period, set the stored pointer to NULL while + // deleting the object. Eventually, this safety check will be removed to + // prevent the scenario initially described from occuring and + // http://crbug.com/176091 can be closed. + T* old = data_.ptr; + data_.ptr = NULL; + if (old != NULL) + static_cast<D&>(data_)(old); + data_.ptr = p; } - void reset(T* p = NULL) { - typedef char type_must_be_complete[sizeof(T)]; + T* get() const { return data_.ptr; } - if (ptr != p) { - T* obj = ptr; - ptr = p; - // Delete last, in case obj destructor indirectly results in ~scoped_ptr - delete obj; - } + D& get_deleter() { return data_; } + const D& get_deleter() const { return data_; } + + void swap(scoped_ptr_impl& p2) { + // Standard swap idiom: 'using std::swap' ensures that std::swap is + // present in the overload set, but we call swap unqualified so that + // any more-specific overloads can be used, if available. + using std::swap; + swap(static_cast<D&>(data_), static_cast<D&>(p2.data_)); + swap(data_.ptr, p2.data_.ptr); } - T& operator*() const { - assert(ptr != NULL); - return *ptr; + T* release() { + T* old_ptr = data_.ptr; + data_.ptr = NULL; + return old_ptr; } - T* operator->() const { - assert(ptr != NULL); - return ptr; + private: + // Needed to allow type-converting constructor. + template <typename U, typename V> friend class scoped_ptr_impl; + + // Use the empty base class optimization to allow us to have a D + // member, while avoiding any space overhead for it when D is an + // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good + // discussion of this technique. + struct Data : public D { + explicit Data(T* ptr_in) : ptr(ptr_in) {} + Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {} + T* ptr; + }; + + Data data_; + + DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl); +}; + +} // namespace internal + +// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> +// automatically deletes the pointer it holds (if any). +// That is, scoped_ptr<T> owns the T object that it points to. +// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. +// Also like T*, scoped_ptr<T> is thread-compatible, and once you +// dereference it, you get the thread safety guarantees of T. +// +// The size of scoped_ptr is small. On most compilers, when using the +// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will +// increase the size proportional to whatever state they need to have. See +// comments inside scoped_ptr_impl<> for details. +// +// Current implementation targets having a strict subset of C++11's +// unique_ptr<> features. Known deficiencies include not supporting move-only +// deleteres, function pointers as deleters, and deleters with reference +// types. +template <class T, class D = webrtc::DefaultDeleter<T> > +class scoped_ptr { + MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) + + public: + // The element and deleter types. + typedef T element_type; + typedef D deleter_type; + + // Constructor. Defaults to initializing with NULL. + scoped_ptr() : impl_(NULL) { } + + // Constructor. Takes ownership of p. + explicit scoped_ptr(element_type* p) : impl_(p) { } + + // Constructor. Allows initialization of a stateful deleter. + scoped_ptr(element_type* p, const D& d) : impl_(p, d) { } + + // Constructor. Allows construction from a scoped_ptr rvalue for a + // convertible type and deleter. + // + // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct + // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor + // has different post-conditions if D is a reference type. Since this + // implementation does not support deleters with reference type, + // we do not need a separate move constructor allowing us to avoid one + // use of SFINAE. You only need to care about this if you modify the + // implementation of scoped_ptr. + template <typename U, typename V> + scoped_ptr(scoped_ptr<U, V> other) : impl_(&other.impl_) { + COMPILE_ASSERT(!webrtc::is_array<U>::value, U_cannot_be_an_array); } - T* get() const { - return ptr; + // Constructor. Move constructor for C++03 move emulation of this type. + scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { } + + // operator=. Allows assignment from a scoped_ptr rvalue for a convertible + // type and deleter. + // + // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from + // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated + // form has different requirements on for move-only Deleters. Since this + // implementation does not support move-only Deleters, we do not need a + // separate move assignment operator allowing us to avoid one use of SFINAE. + // You only need to care about this if you modify the implementation of + // scoped_ptr. + template <typename U, typename V> + scoped_ptr& operator=(scoped_ptr<U, V> rhs) { + COMPILE_ASSERT(!webrtc::is_array<U>::value, U_cannot_be_an_array); + impl_.TakeState(&rhs.impl_); + return *this; } - void swap(scoped_ptr & b) { - T* tmp = b.ptr; - b.ptr = ptr; - ptr = tmp; + // Reset. Deletes the currently owned object, if any. + // Then takes ownership of a new object, if given. + void reset(element_type* p = NULL) { impl_.reset(p); } + + // Accessors to get the owned object. + // operator* and operator-> will assert() if there is no current object. + element_type& operator*() const { + assert(impl_.get() != NULL); + return *impl_.get(); } + element_type* operator->() const { + assert(impl_.get() != NULL); + return impl_.get(); + } + element_type* get() const { return impl_.get(); } + + // Access to the deleter. + deleter_type& get_deleter() { return impl_.get_deleter(); } + const deleter_type& get_deleter() const { return impl_.get_deleter(); } + + // Allow scoped_ptr<element_type> to be used in boolean expressions, but not + // implicitly convertible to a real bool (which is dangerous). + // + // Note that this trick is only safe when the == and != operators + // are declared explicitly, as otherwise "scoped_ptr1 == + // scoped_ptr2" will compile but do the wrong thing (i.e., convert + // to Testable and then do the comparison). + private: + typedef webrtc::internal::scoped_ptr_impl<element_type, deleter_type> + scoped_ptr::*Testable; - T* release() { - T* tmp = ptr; - ptr = NULL; - return tmp; + public: + operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; } + + // Comparison operators. + // These return whether two scoped_ptr refer to the same object, not just to + // two different but equal objects. + bool operator==(const element_type* p) const { return impl_.get() == p; } + bool operator!=(const element_type* p) const { return impl_.get() != p; } + + // Swap two scoped pointers. + void swap(scoped_ptr& p2) { + impl_.swap(p2.impl_); } - T** accept() { - if (ptr) { - delete ptr; - ptr = NULL; - } - return &ptr; + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + element_type* release() WARN_UNUSED_RESULT { + return impl_.release(); } - T** use() { - return &ptr; + // C++98 doesn't support functions templates with default parameters which + // makes it hard to write a PassAs() that understands converting the deleter + // while preserving simple calling semantics. + // + // Until there is a use case for PassAs() with custom deleters, just ignore + // the custom deleter. + template <typename PassAsType> + scoped_ptr<PassAsType> PassAs() { + return scoped_ptr<PassAsType>(Pass()); } + + private: + // Needed to reach into |impl_| in the constructor. + template <typename U, typename V> friend class scoped_ptr; + webrtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_; + + // Forbidden for API compatibility with std::unique_ptr. + explicit scoped_ptr(int disallow_construction_from_null); + + // Forbid comparison of scoped_ptr types. If U != T, it totally + // doesn't make sense, and if U == T, it still doesn't make sense + // because you should never have the same object owned by two different + // scoped_ptrs. + template <class U> bool operator==(scoped_ptr<U> const& p2) const; + template <class U> bool operator!=(scoped_ptr<U> const& p2) const; }; -template<typename T> inline -void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) { - a.swap(b); +template <class T, class D> +class scoped_ptr<T[], D> { + MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) + + public: + // The element and deleter types. + typedef T element_type; + typedef D deleter_type; + + // Constructor. Defaults to initializing with NULL. + scoped_ptr() : impl_(NULL) { } + + // Constructor. Stores the given array. Note that the argument's type + // must exactly match T*. In particular: + // - it cannot be a pointer to a type derived from T, because it is + // inherently unsafe in the general case to access an array through a + // pointer whose dynamic type does not match its static type (eg., if + // T and the derived types had different sizes access would be + // incorrectly calculated). Deletion is also always undefined + // (C++98 [expr.delete]p3). If you're doing this, fix your code. + // - it cannot be NULL, because NULL is an integral expression, not a + // pointer to T. Use the no-argument version instead of explicitly + // passing NULL. + // - it cannot be const-qualified differently from T per unique_ptr spec + // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting + // to work around this may use implicit_cast<const T*>(). + // However, because of the first bullet in this comment, users MUST + // NOT use implicit_cast<Base*>() to upcast the static type of the array. + explicit scoped_ptr(element_type* array) : impl_(array) { } + + // Constructor. Move constructor for C++03 move emulation of this type. + scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { } + + // operator=. Move operator= for C++03 move emulation of this type. + scoped_ptr& operator=(RValue rhs) { + impl_.TakeState(&rhs.object->impl_); + return *this; + } + + // Reset. Deletes the currently owned array, if any. + // Then takes ownership of a new object, if given. + void reset(element_type* array = NULL) { impl_.reset(array); } + + // Accessors to get the owned array. + element_type& operator[](size_t i) const { + assert(impl_.get() != NULL); + return impl_.get()[i]; + } + element_type* get() const { return impl_.get(); } + + // Access to the deleter. + deleter_type& get_deleter() { return impl_.get_deleter(); } + const deleter_type& get_deleter() const { return impl_.get_deleter(); } + + // Allow scoped_ptr<element_type> to be used in boolean expressions, but not + // implicitly convertible to a real bool (which is dangerous). + private: + typedef webrtc::internal::scoped_ptr_impl<element_type, deleter_type> + scoped_ptr::*Testable; + + public: + operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; } + + // Comparison operators. + // These return whether two scoped_ptr refer to the same object, not just to + // two different but equal objects. + bool operator==(element_type* array) const { return impl_.get() == array; } + bool operator!=(element_type* array) const { return impl_.get() != array; } + + // Swap two scoped pointers. + void swap(scoped_ptr& p2) { + impl_.swap(p2.impl_); + } + + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + element_type* release() WARN_UNUSED_RESULT { + return impl_.release(); + } + + private: + // Force element_type to be a complete type. + enum { type_must_be_complete = sizeof(element_type) }; + + // Actually hold the data. + webrtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_; + + // Disable initialization from any type other than element_type*, by + // providing a constructor that matches such an initialization, but is + // private and has no definition. This is disabled because it is not safe to + // call delete[] on an array whose static type does not match its dynamic + // type. + template <typename U> explicit scoped_ptr(U* array); + explicit scoped_ptr(int disallow_construction_from_null); + + // Disable reset() from any type other than element_type*, for the same + // reasons as the constructor above. + template <typename U> void reset(U* array); + void reset(int disallow_reset_from_null); + + // Forbid comparison of scoped_ptr types. If U != T, it totally + // doesn't make sense, and if U == T, it still doesn't make sense + // because you should never have the same object owned by two different + // scoped_ptrs. + template <class U> bool operator==(scoped_ptr<U> const& p2) const; + template <class U> bool operator!=(scoped_ptr<U> const& p2) const; +}; + +} // namespace webrtc + +// Free functions +template <class T, class D> +void swap(webrtc::scoped_ptr<T, D>& p1, webrtc::scoped_ptr<T, D>& p2) { + p1.swap(p2); +} + +template <class T, class D> +bool operator==(T* p1, const webrtc::scoped_ptr<T, D>& p2) { + return p1 == p2.get(); } +template <class T, class D> +bool operator!=(T* p1, const webrtc::scoped_ptr<T, D>& p2) { + return p1 != p2.get(); +} +// A function to convert T* into webrtc::scoped_ptr<T> +// Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation +// for webrtc::scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) +template <typename T> +webrtc::scoped_ptr<T> make_scoped_ptr(T* ptr) { + return webrtc::scoped_ptr<T>(ptr); +} +namespace webrtc { +// DEPRECATED: Use scoped_ptr<T[]> instead. +// TODO(ajm): Remove scoped_array. +// // scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to // is guaranteed, either on destruction of the scoped_array or via an explicit // reset(). Use shared_array or std::vector if your needs are more complex. @@ -184,6 +647,9 @@ void swap(scoped_array<T>& a, scoped_array<T>& b) { a.swap(b); } +// DEPRECATED: Use scoped_ptr<C, webrtc::FreeDeleter> instead. +// TODO(ajm): Remove scoped_ptr_malloc. +// // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a // second template argument, the function used to free the object. @@ -254,4 +720,4 @@ void swap(scoped_ptr_malloc<T,FF>& a, scoped_ptr_malloc<T,FF>& b) { } // namespace webrtc -#endif // #ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_ +#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_ diff --git a/system_wrappers/interface/template_util.h b/system_wrappers/interface/template_util.h new file mode 100644 index 00000000..5ae415b5 --- /dev/null +++ b/system_wrappers/interface/template_util.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Borrowed from Chromium's src/base/template_util.h. + +#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TEMPLATE_UTIL_H_ +#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TEMPLATE_UTIL_H_ + +#include <cstddef> // For size_t. + +namespace webrtc { + +// Template definitions from tr1. + +template<class T, T v> +struct integral_constant { + static const T value = v; + typedef T value_type; + typedef integral_constant<T, v> type; +}; + +template <class T, T v> const T integral_constant<T, v>::value; + +typedef integral_constant<bool, true> true_type; +typedef integral_constant<bool, false> false_type; + +template <class T> struct is_pointer : false_type {}; +template <class T> struct is_pointer<T*> : true_type {}; + +template <class T, class U> struct is_same : public false_type {}; +template <class T> struct is_same<T, T> : true_type {}; + +template<class> struct is_array : public false_type {}; +template<class T, size_t n> struct is_array<T[n]> : public true_type {}; +template<class T> struct is_array<T[]> : public true_type {}; + +template <class T> struct is_non_const_reference : false_type {}; +template <class T> struct is_non_const_reference<T&> : true_type {}; +template <class T> struct is_non_const_reference<const T&> : false_type {}; + +template <class T> struct is_void : false_type {}; +template <> struct is_void<void> : true_type {}; + +namespace internal { + +// Types YesType and NoType are guaranteed such that sizeof(YesType) < +// sizeof(NoType). +typedef char YesType; + +struct NoType { + YesType dummy[2]; +}; + +// This class is an implementation detail for is_convertible, and you +// don't need to know how it works to use is_convertible. For those +// who care: we declare two different functions, one whose argument is +// of type To and one with a variadic argument list. We give them +// return types of different size, so we can use sizeof to trick the +// compiler into telling us which function it would have chosen if we +// had called it with an argument of type From. See Alexandrescu's +// _Modern C++ Design_ for more details on this sort of trick. + +struct ConvertHelper { + template <typename To> + static YesType Test(To); + + template <typename To> + static NoType Test(...); + + template <typename From> + static From& Create(); +}; + +// Used to determine if a type is a struct/union/class. Inspired by Boost's +// is_class type_trait implementation. +struct IsClassHelper { + template <typename C> + static YesType Test(void(C::*)(void)); + + template <typename C> + static NoType Test(...); +}; + +} // namespace internal + +// Inherits from true_type if From is convertible to To, false_type otherwise. +// +// Note that if the type is convertible, this will be a true_type REGARDLESS +// of whether or not the conversion would emit a warning. +template <typename From, typename To> +struct is_convertible + : integral_constant<bool, + sizeof(internal::ConvertHelper::Test<To>( + internal::ConvertHelper::Create<From>())) == + sizeof(internal::YesType)> { +}; + +template <typename T> +struct is_class + : integral_constant<bool, + sizeof(internal::IsClassHelper::Test<T>(0)) == + sizeof(internal::YesType)> { +}; + +} // namespace webrtc + +#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TEMPLATE_UTIL_H_ diff --git a/system_wrappers/source/atomic32_win.cc b/system_wrappers/source/atomic32_win.cc index 5dd07092..7c70376f 100644 --- a/system_wrappers/source/atomic32_win.cc +++ b/system_wrappers/source/atomic32_win.cc @@ -20,9 +20,8 @@ namespace webrtc { Atomic32::Atomic32(int32_t initial_value) : value_(initial_value) { - // Make sure that the counter variable we're using is of the same size - // as what the API expects. - COMPILE_ASSERT(sizeof(value_) == sizeof(LONG)); + COMPILE_ASSERT(sizeof(value_) == sizeof(LONG), + counter_variable_is_the_expected_size); assert(Is32bitAligned()); } diff --git a/test/test_suite.cc b/test/test_suite.cc index c8ff742c..7cfb856f 100644 --- a/test/test_suite.cc +++ b/test/test_suite.cc @@ -21,8 +21,7 @@ DEFINE_bool(logs, false, "print logs to stderr"); namespace webrtc { namespace test { -TestSuite::TestSuite(int argc, char** argv) - : trace_to_stderr_(NULL) { +TestSuite::TestSuite(int argc, char** argv) { SetExecutablePath(argv[0]); testing::InitGoogleMock(&argc, argv); // Runs InitGoogleTest() internally. // AllowCommandLineParsing allows us to ignore flags passed on to us by @@ -92,4 +92,13 @@ typedef unsigned __int64 uint64_t; #define OVERRIDE #endif +// Annotate a function indicating the caller must examine the return value. +// Use like: +// int foo() WARN_UNUSED_RESULT; +#if defined(__GNUC__) +#define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +#define WARN_UNUSED_RESULT +#endif + #endif // WEBRTC_TYPEDEFS_H_ diff --git a/video_engine/test/common/frame_generator_capturer.cc b/video_engine/test/common/frame_generator_capturer.cc index 02b4a31d..08b3d298 100644 --- a/video_engine/test/common/frame_generator_capturer.cc +++ b/video_engine/test/common/frame_generator_capturer.cc @@ -66,7 +66,6 @@ FrameGeneratorCapturer::FrameGeneratorCapturer(Clock* clock, sending_(false), tick_(EventWrapper::Create()), lock_(CriticalSectionWrapper::CreateCriticalSection()), - thread_(NULL), frame_generator_(frame_generator), target_fps_(target_fps) { assert(input != NULL); diff --git a/video_engine/vie_channel.cc b/video_engine/vie_channel.cc index 10f46eb2..dabccefa 100644 --- a/video_engine/vie_channel.cc +++ b/video_engine/vie_channel.cc @@ -74,7 +74,6 @@ ViEChannel::ViEChannel(int32_t channel_id, callback_cs_(CriticalSectionWrapper::CreateCriticalSection()), rtp_rtcp_cs_(CriticalSectionWrapper::CreateCriticalSection()), default_rtp_rtcp_(default_rtp_rtcp), - rtp_rtcp_(NULL), vcm_(*VideoCodingModule::Create(ViEModuleId(engine_id, channel_id))), vie_receiver_(channel_id, &vcm_, remote_bitrate_estimator, this), vie_sender_(channel_id), diff --git a/video_engine/vie_encoder.cc b/video_engine/vie_encoder.cc index a3023f9a..6295920a 100644 --- a/video_engine/vie_encoder.cc +++ b/video_engine/vie_encoder.cc @@ -141,7 +141,6 @@ ViEEncoder::ViEEncoder(int32_t engine_id, channel_id))), vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(engine_id, channel_id))), - default_rtp_rtcp_(NULL), callback_cs_(CriticalSectionWrapper::CreateCriticalSection()), data_cs_(CriticalSectionWrapper::CreateCriticalSection()), bitrate_controller_(bitrate_controller), diff --git a/voice_engine/channel.cc b/voice_engine/channel.cc index af89d5cd..9e616a35 100644 --- a/voice_engine/channel.cc +++ b/voice_engine/channel.cc @@ -919,7 +919,6 @@ Channel::Channel(int32_t channelId, _callbackCritSectPtr(NULL), _transportPtr(NULL), _encryptionPtr(NULL), - rtp_audioproc_(NULL), rx_audioproc_(AudioProcessing::Create(VoEModuleId(instanceId, channelId))), _rxVadObserverPtr(NULL), _oldVadDecision(-1), diff --git a/voice_engine/shared_data.cc b/voice_engine/shared_data.cc index 712bb66a..21878447 100644 --- a/voice_engine/shared_data.cc +++ b/voice_engine/shared_data.cc @@ -29,7 +29,6 @@ SharedData::SharedData(const Config& config) : _channelManager(_gInstanceCounter, config), _engineStatistics(_gInstanceCounter), _audioDevicePtr(NULL), - audioproc_(NULL), _moduleProcessThreadPtr(ProcessThread::CreateProcessThread()), _externalRecording(false), _externalPlayout(false) |