webrtc 使用scoped_ptr
来源:互联网 发布:品茗网络计划破解版 编辑:程序博客网 时间:2024/06/02 19:28
// Copyright (c) 2012 The Chromium Authors. All rights reserved.// Use of this source code is governed by a BSD-style license that can be// found in the LICENSE file.#ifndef THIRD_PARTY_WEBRTC_FILES_TALK_BASE_MOVE_H_#define THIRD_PARTY_WEBRTC_FILES_TALK_BASE_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 {// TALK_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 {// TALK_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 TALK_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 // THIRD_PARTY_WEBRTC_FILES_TALK_BASE_MOVE_H_
/** 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.*/// Borrowed from Chromium's src/base/basictypes.h.#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_// 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.// TODO(ajm): Hack to avoid multiple definitions until the base/ of webrtc and// libjingle are merged.#if !defined(COMPILE_ASSERT)template <bool>struct CompileAssert {};#define COMPILE_ASSERT(expr, msg) \ typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]#endif // COMPILE_ASSERT#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
#ifndef TALK_BASE_SCOPED_PTR_H__#define TALK_BASE_SCOPED_PTR_H__#include <cstddef>// for std::ptrdiff_t#include <stdlib.h>// for free() decl#include "compile_assert.h"// for COMPILE_ASSERT#include "move.h"// for TALK_MOVE_ONLY_TYPE_FOR_CPP_03#if !defined(WARN_UNUSED_RESULT)#if defined(__GNUC__)#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))#else#define WARN_UNUSED_RESULT#endif#endif // WARN_UNUSED_RESULT#ifndef DISALLOW_ASSIGN#define DISALLOW_ASSIGN(TypeName) \ void operator=(const TypeName&)#endif#ifndef DISALLOW_COPY_AND_ASSIGN// A macro to disallow the evil copy constructor and operator= functions// This should be used in the private: declarations for a class#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ DISALLOW_ASSIGN(TypeName)#endif#ifdef _WIN32namespace std { using ::ptrdiff_t; };#endif // _WIN32namespace talk_base {// 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((talk_base::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#938template <typename U> void operator()(U* array) const;};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);};// 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, talk_base::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 talk_base::subtle::move() and// talk_base::subtle::forward()// functions that are imperfect emulations of their C++11 equivalents,// but until there's a requirement, just assume deleters are copyable.}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();}~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);}}void reset(T* p) {// This is a self-reset, which is no longer allowed: http://crbug.com/162971if (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;}T* get() const { return data_.ptr; }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* release() {T* old_ptr = data_.ptr;data_.ptr = NULL;return old_ptr;}T** accept() {reset(NULL);return &(data_.ptr);}T** use() {return &(data_.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 = talk_base::DefaultDeleter<T> >class scoped_ptr {TALK_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(!talk_base::is_array<U>::value, U_cannot_be_an_array);}// 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(!talk_base::is_array<U>::value, U_cannot_be_an_array);impl_.TakeState(&rhs.impl_);return *this;}// 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 talk_base::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==(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_);}// 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();}// Delete the currently held pointer and return a pointer// to allow overwriting of the current pointer address.element_type** accept() WARN_UNUSED_RESULT{return impl_.accept();}// Return a pointer to the current pointer address.element_type** use() WARN_UNUSED_RESULT{return impl_.use();}// 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;talk_base::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;};}#endif // #ifndef TALK_BASE_SCOPED_PTR_H__
#include "scoped_ptr.h"#include<iostream>#include<string>using namespace std;using namespace talk_base;class VoiceChannelTransport{public:VoiceChannelTransport(string s){name = s;}void Initialize(){cout << "Initialize" << endl;}private:string name;};int main(){{talk_base::scoped_ptr<VoiceChannelTransport> voice_channel_transport(new VoiceChannelTransport("abc"));voice_channel_transport.reset(new VoiceChannelTransport("cde"));voice_channel_transport.get()->Initialize();}cout << "Initialize" << endl;//error //VoiceChannelTransport * p = voice_channel_transport.get();//delete p;return 0;}
0 0
- webrtc 使用scoped_ptr
- webrtc的scoped_ptr
- scoped_ptr
- scoped_ptr
- scoped_ptr
- scoped_ptr
- scoped_ptr
- scoped_ptr
- scoped_ptr
- 智能指针scoped_ptr组件的使用
- webrtc--AudioProcessing的使用
- 使用webRTC通话Demo
- webrtc--AudioProcessing的使用
- webrtc--AudioProcessing的使用
- WEBRTC DataChannel使用
- 智能指针scoped_ptr,shared_ptr,weak_ptr和auto_ptr的使用
- Boost学习笔记(一)----scoped_ptr智能指针的使用
- WebRTC VoiceEngine使用简单Demo
- C++11学习1
- Python中lxml模块的安装
- JavaScript特效之前进,后退(返回上一级)
- 高级模糊查询
- JavaScript中操作对象的属性
- webrtc 使用scoped_ptr
- group by 统计行数
- cocos 打开网页
- 让Win10 win+e显示我的电脑的方法
- BSP RF 相关 安卓底层命令--学习中 未完待续
- mysql 查询优化
- CString 转char *
- Android工程项目没有错却出现红叉—解决办法
- ubuntu虚拟机忘记密码的解决办法