1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

UniquePtr: Support SrsUniquePtr to replace SrsAutoFree. v6.0.136 (#4109)

To manage an object:

```cpp
// Before
MyClass* ptr = new MyClass();
SrsAutoFree(MyClass, ptr);
ptr->do_something();

// Now
SrsUniquePtr<MyClass> ptr(new MyClass());
ptr->do_something();
```

To manage an array of objects:

```cpp
// Before
char* ptr = new char[10];
SrsAutoFreeA(char, ptr);
ptr[0] = 0xf;

// Now
SrsUniquePtr<char[]> ptr(new char[10]);
ptr[0] = 0xf;
```

In fact, SrsUniquePtr is a limited subset of SrsAutoFree, mainly
managing pointers and arrays. SrsUniquePtr is better than SrsAutoFree
because it has the same API to standard unique ptr.

```cpp
SrsUniquePtr<MyClass> ptr(new MyClass());
ptr->do_something();
MyClass* p = ptr.get();
```

SrsAutoFree actually uses a pointer to a pointer, so it can be set to
NULL, allowing the pointer's value to be changed later (this usage is
different from SrsUniquePtr).

```cpp
// OK to free ptr correctly.
MyClass* ptr;
SrsAutoFree(MyClass, ptr);
ptr = new MyClass();

// Crash because ptr is an invalid pointer.
MyClass* ptr;
SrsUniquePtr<MyClass> ptr(ptr);
ptr = new MyClass();
```

Additionally, SrsAutoFreeH can use specific release functions, which
SrsUniquePtr does not support.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
This commit is contained in:
Winlin 2024-07-09 10:29:36 +08:00 committed by GitHub
parent baf22d01c1
commit 23d2602c34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
72 changed files with 1720 additions and 1669 deletions

View file

@ -9,79 +9,106 @@
#include <srs_core.hpp>
#include <stdlib.h>
// The auto free helper, which is actually the unique ptr, without the move feature,
// Unique ptr smart pointer, only support unique ptr, with limited APIs and features,
// see https://github.com/ossrs/srs/discussions/3667#discussioncomment-8969107
//
// To free the instance in the current scope, for instance, MyClass* ptr,
// which is a ptr and this class will:
// 1. free the ptr.
// 2. set ptr to NULL.
//
// Usage:
// MyClass* po = new MyClass();
// // ...... use po
// SrsAutoFree(MyClass, po);
// SrsUniquePtr<MyClass> ptr(new MyClass());
// ptr->do_something();
//
// Usage for array:
// MyClass** pa = new MyClass*[size];
// // ....... use pa
// SrsAutoFreeA(MyClass*, pa);
// Note that the ptr should be initialized before use it, or it will crash if not set, for example:
// Myclass* p;
// SrsUniquePtr<MyClass> ptr(p); // crash because p is an invalid pointer.
//
// @remark the MyClass can be basic type, for instance, SrsAutoFreeA(char, pstr),
// where the char* pstr = new char[size].
// To delete object.
#define SrsAutoFree(className, instance) \
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, NULL)
// To delete array.
#define SrsAutoFreeA(className, instance) \
impl_SrsAutoFree<className> _auto_free_array_##instance(&instance, true, false, NULL)
// Use free instead of delete.
#define SrsAutoFreeF(className, instance) \
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, true, NULL)
// Use hook instead of delete.
#define SrsAutoFreeH(className, instance, hook) \
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, hook)
// The template implementation.
// Note that do not support array or object created by malloc, because we only use delete to dispose
// the resource.
template<class T>
class impl_SrsAutoFree
class SrsUniquePtr
{
private:
T** ptr;
bool is_array;
bool _use_free;
void (*_hook)(T*);
T* ptr_;
public:
// If use_free, use free(void*) to release the p.
// If specified hook, use hook(p) to release it.
// Use delete to release p, or delete[] if p is an array.
impl_SrsAutoFree(T** p, bool array, bool use_free, void (*hook)(T*)) {
ptr = p;
is_array = array;
_use_free = use_free;
_hook = hook;
SrsUniquePtr(T* ptr = NULL) {
ptr_ = ptr;
}
virtual ~impl_SrsAutoFree() {
if (ptr == NULL || *ptr == NULL) {
return;
}
virtual ~SrsUniquePtr() {
delete ptr_;
}
public:
// Get the object.
T* get() {
return ptr_;
}
// Overload the -> operator.
T* operator->() {
return ptr_;
}
private:
// Copy the unique ptr.
SrsUniquePtr(const SrsUniquePtr<T>&) = delete;
// The assign operator.
SrsUniquePtr<T>& operator=(const SrsUniquePtr<T>&) = delete;
private:
// Overload the * operator.
T& operator*() = delete;
// Overload the bool operator.
operator bool() const = delete;
#if __cplusplus >= 201103L // C++11
private:
// The move constructor.
SrsUniquePtr(SrsUniquePtr<T>&&) = delete;
// The move assign operator.
SrsUniquePtr<T>& operator=(SrsUniquePtr<T>&&) = delete;
#endif
};
if (_use_free) {
free(*ptr);
} else if (_hook) {
_hook(*ptr);
} else {
if (is_array) {
delete[] *ptr;
} else {
delete *ptr;
}
}
*ptr = NULL;
// The unique ptr for array objects, only support unique ptr, with limited APIs and features,
// see https://github.com/ossrs/srs/discussions/3667#discussioncomment-8969107
//
// Usage:
// SrsUniquePtr<MyClass[]> ptr(new MyClass[10]);
// ptr[0]->do_something();
template<class T>
class SrsUniquePtr<T[]>
{
private:
T* ptr_;
public:
SrsUniquePtr(T* ptr = NULL) {
ptr_ = ptr;
}
virtual ~SrsUniquePtr() {
delete[] ptr_;
}
public:
// Get the object.
T* get() {
return ptr_;
}
// Overload the [] operator.
T& operator[](std::size_t index) {
return ptr_[index];
}
const T& operator[](std::size_t index) const {
return ptr_[index];
}
private:
// Copy the unique ptr.
SrsUniquePtr(const SrsUniquePtr<T>&) = delete;
// The assign operator.
SrsUniquePtr<T>& operator=(const SrsUniquePtr<T>&) = delete;
private:
// Overload the * operator.
T& operator*() = delete;
// Overload the bool operator.
operator bool() const = delete;
#if __cplusplus >= 201103L // C++11
private:
// The move constructor.
SrsUniquePtr(SrsUniquePtr<T>&&) = delete;
// The move assign operator.
SrsUniquePtr<T>& operator=(SrsUniquePtr<T>&&) = delete;
#endif
};
// Shared ptr smart pointer, only support shared ptr, no weak ptr, no shared from this, no inheritance,

View file

@ -0,0 +1,8 @@
//
// Copyright (c) 2013-2024 The SRS Authors
//
// SPDX-License-Identifier: MIT
//
#include <srs_core_deprecated.hpp>

View file

@ -0,0 +1,95 @@
//
// Copyright (c) 2013-2024 The SRS Authors
//
// SPDX-License-Identifier: MIT
//
#ifndef SRS_CORE_DEPRECATED_HPP
#define SRS_CORE_DEPRECATED_HPP
#include <srs_core.hpp>
#include <stdlib.h>
// Note that the SrsAutoFree is deprecated, please use SrsUniquePtr instead.
//
// Note: Please use SrsUniquePtr if possible. Please aware that there is a slight difference between SrsAutoFree
// and SrsUniquePtr. SrsAutoFree will track the address of pointer, while SrsUniquePtr will not.
// MyClass* p;
// SrsAutoFree(MyClass, p); // p will be freed even p is changed later.
// SrsUniquePtr ptr(p); // crash because p is an invalid pointer.
//
// The auto free helper, which is actually the unique ptr, without the move feature,
// see https://github.com/ossrs/srs/discussions/3667#discussioncomment-8969107
//
// To free the instance in the current scope, for instance, MyClass* ptr,
// which is a ptr and this class will:
// 1. free the ptr.
// 2. set ptr to NULL.
//
// Usage:
// MyClass* po = new MyClass();
// // ...... use po
// SrsAutoFree(MyClass, po);
//
// Usage for array:
// MyClass** pa = new MyClass*[size];
// // ....... use pa
// SrsAutoFreeA(MyClass*, pa);
//
// @remark the MyClass can be basic type, for instance, SrsAutoFreeA(char, pstr),
// where the char* pstr = new char[size].
// To delete object.
#define SrsAutoFree(className, instance) \
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, NULL)
// To delete array.
#define SrsAutoFreeA(className, instance) \
impl_SrsAutoFree<className> _auto_free_array_##instance(&instance, true, false, NULL)
// Use free instead of delete.
#define SrsAutoFreeF(className, instance) \
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, true, NULL)
// Use hook instead of delete.
#define SrsAutoFreeH(className, instance, hook) \
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, hook)
// The template implementation.
template<class T>
class impl_SrsAutoFree
{
private:
T** ptr;
bool is_array;
bool _use_free;
void (*_hook)(T*);
public:
// If use_free, use free(void*) to release the p.
// If specified hook, use hook(p) to release it.
// Use delete to release p, or delete[] if p is an array.
impl_SrsAutoFree(T** p, bool array, bool use_free, void (*hook)(T*)) {
ptr = p;
is_array = array;
_use_free = use_free;
_hook = hook;
}
virtual ~impl_SrsAutoFree() {
if (ptr == NULL || *ptr == NULL) {
return;
}
if (_use_free) {
free(*ptr);
} else if (_hook) {
_hook(*ptr);
} else {
if (is_array) {
delete[] *ptr;
} else {
delete *ptr;
}
}
*ptr = NULL;
}
};
#endif

View file

@ -9,6 +9,6 @@
#define VERSION_MAJOR 6
#define VERSION_MINOR 0
#define VERSION_REVISION 135
#define VERSION_REVISION 136
#endif