mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	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>
		
			
				
	
	
		
			127 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* SPDX-License-Identifier: MIT */
 | 
						|
/* Copyright (c) 2013-2024 The SRS Authors */
 | 
						|
 | 
						|
#ifndef ST_UTEST_PUBLIC_HPP
 | 
						|
#define ST_UTEST_PUBLIC_HPP
 | 
						|
 | 
						|
// Before define the private/protected, we must include some system header files.
 | 
						|
// Or it may fail with:
 | 
						|
//      redeclared with different access struct __xfer_bufptrs
 | 
						|
// @see https://stackoverflow.com/questions/47839718/sstream-redeclared-with-public-access-compiler-error
 | 
						|
#include <gtest/gtest.h>
 | 
						|
 | 
						|
#include <st.h>
 | 
						|
#include <string>
 | 
						|
 | 
						|
#define VOID
 | 
						|
 | 
						|
// Close the fd automatically.
 | 
						|
#define StFdCleanup(fd, stfd) impl__StFdCleanup _ST_free_##fd(&fd, &stfd)
 | 
						|
#define StStfdCleanup(stfd) impl__StFdCleanup _ST_free_##stfd(NULL, &stfd)
 | 
						|
class impl__StFdCleanup {
 | 
						|
    int* fd_;
 | 
						|
    st_netfd_t* stfd_;
 | 
						|
public:
 | 
						|
    impl__StFdCleanup(int* fd, st_netfd_t* stfd) : fd_(fd), stfd_(stfd) {
 | 
						|
    }
 | 
						|
    virtual ~impl__StFdCleanup() {
 | 
						|
        if (stfd_ && *stfd_) {
 | 
						|
            st_netfd_close(*stfd_);
 | 
						|
        } else if (fd_ && *fd_ > 0) {
 | 
						|
            ::close(*fd_);
 | 
						|
        }
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
// For coroutine function to return with error object.
 | 
						|
struct ErrorObject {
 | 
						|
    int r0_;
 | 
						|
    int errno_;
 | 
						|
    std::string message_;
 | 
						|
 | 
						|
    ErrorObject(int r0, std::string message) : r0_(r0), errno_(errno), message_(message) {
 | 
						|
    }
 | 
						|
};
 | 
						|
extern std::ostream& operator<<(std::ostream& out, const ErrorObject* err);
 | 
						|
#define ST_ASSERT_ERROR(error, r0, message) if (error) return new ErrorObject(r0, message)
 | 
						|
#define ST_COROUTINE_JOIN(trd, r0) ErrorObject* r0 = NULL; if (trd) st_thread_join(trd, (void**)&r0); SrsUniquePtr<ErrorObject> r0_uptr(r0)
 | 
						|
#define ST_EXPECT_SUCCESS(r0) EXPECT_TRUE(!r0) << r0
 | 
						|
#define ST_EXPECT_FAILED(r0) EXPECT_TRUE(r0) << r0
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
// 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;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
// The time unit in ms, for example 100 * SRS_UTIME_MILLISECONDS means 100ms.
 | 
						|
#define SRS_UTIME_MILLISECONDS 1000
 | 
						|
 | 
						|
#endif
 | 
						|
 |