STDIO
Tìm kiếm gần đây
    • Nội dung
    • QR Code
    • 0
    • 0
    • Sao chép

    Design Pattern: Reference Counting

    Bài viết giới thiệu một phương pháp quản lý vùng nhớ dùng chung giữa các con trỏ - Reference Counting.
    Rye Nguyen

    Rye Nguyen

    04/08/2015
    26/09/2020
    3 phút đọc
    Design Pattern: Reference Counting

    Ý tưởng

    Xuất phát từ thực tế nhiều biến con trỏ (pointer) có thể dùng chung 1 vùng nhớ, khi hủy 1 pointer bằng từ khóa delete trong C++, các pointer khác dùng chung vùng nhớ đó sẽ rơi vào trạng thái "trỏ đến hư vô" (NULL). Nếu giải phóng vùng nhớ đó 1 lần nữa sẽ gây ra lỗi vì 1 vùng nhớ không thể được giải phóng 2 lần. Do đó, hoặc là phải rất cẩn thận khi giải phóng 1 pointer, hoặc 1 phương pháp đơn giản để tự động quản lý công việc này.

    Reference Counting sử dụng 1 biến đếm số lượng pointer trỏ vào 1 vùng nhớ. Khi có các pointer cùng trỏ đến 1 vùng nhớ, hoặc 1 pointer không còn trỏ đến vùng nhớ đó nữa, biến này sẽ được cập nhật lại tương ứng. Vùng nhớ sẽ thực sự được giải phóng khi biến đếm có giá trị bằng 0, hay nói cách khác là không còn pointer nào trỏ đến nó.

    Vùng nhớ truyền thống
    Vùng nhớ trỏ bởi 4 con trỏ
    Vùng nhớ được thu hồi
    Vùng nhớ không còn được trỏ

    Hiện thực Reference Counting

    class ReferenceCounting
    {
    private:
           int    m_counter;
    public:
           ReferenceCounting() : m_counter(0){}
           virtual ~ReferenceCounting(){}
    
           void   Grab(){ m_counter++; }
           void   Release()
           {
                  m_counter--;
                  if(m_counter == 0)
                         delete (ReferenceCounting*)this;
           }
    };

    Trong hiện thực của lớp có các thành phần với chức năng như sau:

    • Biến m_counter: số lượng các pointer đang cùng trỏ vào vùng nhớ.
    • Hàm Grab: quản lý việc thêm 1 pointer khác trỏ vào vùng nhớ.
    • Hàm Release: giải phóng vùng nhớ khi không còn pointer nào trỏ đến.

    Sử dụng Reference Counting

    Ở khai báo lớp, cho lớp kế thừa từ ReferenceCounting để kích hoạt khả năng quản lý vùng nhớ của ReferenceCounting.

    Với mỗi trường hợp 1 pointer cần trỏ đến 1 biến cùng kiểu đã được khởi tạo, gọi hàm Grab để tăng giá trị của biến đếm.

    Khi 1 pointer hết giá trị sử dụng, gọi hàm Release để kiểm tra và giải phóng vùng nhớ của pointer đó.

     Ví dụ, sử dụng trong Project Sins (STDIO):

    #include <stdio.h>
    
    class ReferenceCounting
    {
    private:
           int           m_counter;
    public:
           ReferenceCounting() : m_counter(0){}
           virtual ~ReferenceCounting(){}
    
           void   Grab(){ m_counter++; }
           void   Release()
           {
                  m_counter--;
                  if(m_counter == 0)
                         delete (ReferenceCounting*)this;
           }
    };
    
    // Singleton
    template <class T> class Singleton
    {
    private:
           static T*     s_instance;
    public:
           Singleton(){}
           virtual ~Singleton(){}
    
           static T*     GetInstance()
           {
                  {
                         if(!s_instance)
                               s_instance = new T();
                         return s_instance;
                  }
           }
    };
    
    template <class T>
    T* Singleton<T>::s_instance = NULL;
    
    // Class derive from ReferenceCounting
    class StdioFacebookPlugin : public ReferenceCounting, public Singleton<StdioFacebookPlugin>
    {
    private:
           // Some necessary variables
           int           m_loginState;
           int           m_shareState;
    public:
           StdioFacebookPlugin(){}
           virtual ~StdioFacebookPlugin(){}
    
           // Some neccesary function
           int           StdioShare(){ return 1; }
           int           StdioLogin(){ return 1; }
    
           void          SetLoginState(int _state){ m_loginState = _state; }
           int           GetLoginState(){ return m_loginState; }
           void          SetShareState(int _state){ m_shareState = _state; }
           int           GetShareState(){ return m_shareState; }
    };
    
    StdioFacebookPlugin * FacebookLogin()
    {
           // ...
    
           StdioFacebookPlugin* plugin = Singleton< StdioFacebookPlugin >::GetInstance();
           plugin->Grab();
           plugin->SetLoginState(plugin->StdioLogin());
    
           // ...
           return plugin;
    }
    
    StdioFacebookPlugin * FacebookSharing()
    {
           // ...
    
           StdioFacebookPlugin* plugin = Singleton<StdioFacebookPlugin>::GetInstance();
           plugin->Grab();
           plugin->SetShareState(plugin->StdioShare());
    
           // ...
           return plugin;
    }
    
    int main()
    {
           // ...
           StdioFacebookPlugin* login = FacebookLogin();
           StdioFacebookPlugin* share = NULL;
    
           if(login)
           {
                  share = FacebookSharing();
           }
           else
           {
                  printf("Can't login.\n");
           }
    
           // ...
    
           login->Release();
           if(share)
                  share->Release();
    
           return 0;
    }
    0 Bình luận

    Đề xuất

      Khi bạn nhấn vào sản phẩm do chúng tôi đề xuất và mua hàng, chúng tôi sẽ nhận được hoa hồng. Điều này hỗ trợ chúng tôi có thêm kinh phí tạo nhiều nội dung hữu ích. Tìm hiểu thêm.
      STDIO

      Trang chính

      Công ty TNHH STDIO

      30, Trịnh Đình Thảo, Hòa Thạnh, Tân Phú, Hồ Chí Minh
      +84 28.36205514 - +84 942.111912
      developer@stdio.vn

      383/1 Quang Trung, Phường 10, Quận Gò Vấp, Hồ Chí Minh
      Số giấy phép ĐKKD: 0311563559 do sở Kế hoạch và Đầu Tư TPHCM cấp ngày 23/02/2012

      Đã thông báo Bộ Công Thương
      ©STDIO, 2013 - 2020