mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	fix https://github.com/ossrs/srs/issues/3155 Build srt-1-fit fails with `standard attributes in middle of decl-specifiers` on GCC 12,Arch Linux. See https://github.com/Haivision/srt/releases/tag/v1.5.3
		
			
				
	
	
		
			273 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			273 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*****************************************************************************
 | |
| Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
 | |
| All rights reserved.
 | |
| 
 | |
| Redistribution and use in source and binary forms, with or without
 | |
| modification, are permitted provided that the following conditions are
 | |
| met:
 | |
| 
 | |
| * Redistributions of source code must retain the above
 | |
|   copyright notice, this list of conditions and the
 | |
|   following disclaimer.
 | |
| 
 | |
| * Redistributions in binary form must reproduce the
 | |
|   above copyright notice, this list of conditions
 | |
|   and the following disclaimer in the documentation
 | |
|   and/or other materials provided with the distribution.
 | |
| 
 | |
| * Neither the name of the University of Illinois
 | |
|   nor the names of its contributors may be used to
 | |
|   endorse or promote products derived from this
 | |
|   software without specific prior written permission.
 | |
| 
 | |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 | |
| IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 | |
| THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | |
| PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | |
| CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 | |
| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | |
| PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 | |
| PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | |
| LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | |
| NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | |
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| *****************************************************************************/
 | |
| 
 | |
| /*****************************************************************************
 | |
| written by
 | |
|    Yunhong Gu, last updated 01/27/2011
 | |
| *****************************************************************************/
 | |
| 
 | |
| #ifndef INC_SRT_CACHE_H
 | |
| #define INC_SRT_CACHE_H
 | |
| 
 | |
| #include <list>
 | |
| #include <vector>
 | |
| 
 | |
| #include "sync.h"
 | |
| #include "netinet_any.h"
 | |
| #include "udt.h"
 | |
| 
 | |
| namespace srt
 | |
| {
 | |
| 
 | |
| class CCacheItem
 | |
| {
 | |
| public:
 | |
|    virtual ~CCacheItem() {}
 | |
| 
 | |
| public:
 | |
|    virtual CCacheItem& operator=(const CCacheItem&) = 0;
 | |
| 
 | |
|    // The "==" operator SHOULD only compare key values.
 | |
|    virtual bool operator==(const CCacheItem&) = 0;
 | |
| 
 | |
|       /// get a deep copy clone of the current item
 | |
|       /// @return Pointer to the new item, or NULL if failed.
 | |
| 
 | |
|    virtual CCacheItem* clone() = 0;
 | |
| 
 | |
|       /// get a random key value between 0 and MAX_INT to be used for the hash in cache
 | |
|       /// @return A random hash key.
 | |
| 
 | |
|    virtual int getKey() = 0;
 | |
| 
 | |
|    // If there is any shared resources between the cache item and its clone,
 | |
|    // the shared resource should be released by this function.
 | |
|    virtual void release() {}
 | |
| };
 | |
| 
 | |
| template<typename T> class CCache
 | |
| {
 | |
| public:
 | |
|    CCache(int size = 1024):
 | |
|    m_iMaxSize(size),
 | |
|    m_iHashSize(size * 3),
 | |
|    m_iCurrSize(0)
 | |
|    {
 | |
|       m_vHashPtr.resize(m_iHashSize);
 | |
|       // Exception: -> CUDTUnited ctor
 | |
|       srt::sync::setupMutex(m_Lock, "Cache");
 | |
|    }
 | |
| 
 | |
|    ~CCache()
 | |
|    {
 | |
|       clear();
 | |
|    }
 | |
| 
 | |
| public:
 | |
|       /// find the matching item in the cache.
 | |
|       /// @param [in,out] data storage for the retrieved item; initially it must carry the key information
 | |
|       /// @return 0 if found a match, otherwise -1.
 | |
| 
 | |
|    int lookup(T* data)
 | |
|    {
 | |
|       srt::sync::ScopedLock cacheguard(m_Lock);
 | |
| 
 | |
|       int key = data->getKey();
 | |
|       if (key < 0)
 | |
|          return -1;
 | |
|       if (key >= m_iMaxSize)
 | |
|          key %= m_iHashSize;
 | |
| 
 | |
|       const ItemPtrList& item_list = m_vHashPtr[key];
 | |
|       for (typename ItemPtrList::const_iterator i = item_list.begin(); i != item_list.end(); ++ i)
 | |
|       {
 | |
|          if (*data == ***i)
 | |
|          {
 | |
|             // copy the cached info
 | |
|             *data = ***i;
 | |
|             return 0;
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       return -1;
 | |
|    }
 | |
| 
 | |
|       /// update an item in the cache, or insert one if it doesn't exist; oldest item may be removed
 | |
|       /// @param [in] data the new item to updated/inserted to the cache
 | |
|       /// @return 0 if success, otherwise -1.
 | |
| 
 | |
|    int update(T* data)
 | |
|    {
 | |
|       srt::sync::ScopedLock cacheguard(m_Lock);
 | |
| 
 | |
|       int key = data->getKey();
 | |
|       if (key < 0)
 | |
|          return -1;
 | |
|       if (key >= m_iMaxSize)
 | |
|          key %= m_iHashSize;
 | |
| 
 | |
|       T* curr = NULL;
 | |
| 
 | |
|       ItemPtrList& item_list = m_vHashPtr[key];
 | |
|       for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i)
 | |
|       {
 | |
|          if (*data == ***i)
 | |
|          {
 | |
|             // update the existing entry with the new value
 | |
|             ***i = *data;
 | |
|             curr = **i;
 | |
| 
 | |
|             // remove the current entry
 | |
|             m_StorageList.erase(*i);
 | |
|             item_list.erase(i);
 | |
| 
 | |
|             // re-insert to the front
 | |
|             m_StorageList.push_front(curr);
 | |
|             item_list.push_front(m_StorageList.begin());
 | |
| 
 | |
|             return 0;
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       // create new entry and insert to front
 | |
|       curr = data->clone();
 | |
|       m_StorageList.push_front(curr);
 | |
|       item_list.push_front(m_StorageList.begin());
 | |
| 
 | |
|       ++ m_iCurrSize;
 | |
|       if (m_iCurrSize >= m_iMaxSize)
 | |
|       {
 | |
|          // Cache overflow, remove oldest entry.
 | |
|          T* last_data = m_StorageList.back();
 | |
|          int last_key = last_data->getKey() % m_iHashSize;
 | |
| 
 | |
|          ItemPtrList& last_item_list = m_vHashPtr[last_key];
 | |
|          for (typename ItemPtrList::iterator i = last_item_list.begin(); i != last_item_list.end(); ++ i)
 | |
|          {
 | |
|             if (*last_data == ***i)
 | |
|             {
 | |
|                last_item_list.erase(i);
 | |
|                break;
 | |
|             }
 | |
|          }
 | |
| 
 | |
|          last_data->release();
 | |
|          delete last_data;
 | |
|          m_StorageList.pop_back();
 | |
|          -- m_iCurrSize;
 | |
|       }
 | |
| 
 | |
|       return 0;
 | |
|    }
 | |
| 
 | |
|       /// Specify the cache size (i.e., max number of items).
 | |
|       /// @param [in] size max cache size.
 | |
| 
 | |
|    void setSizeLimit(int size)
 | |
|    {
 | |
|       m_iMaxSize = size;
 | |
|       m_iHashSize = size * 3;
 | |
|       m_vHashPtr.resize(m_iHashSize);
 | |
|    }
 | |
| 
 | |
|       /// Clear all entries in the cache, restore to initialization state.
 | |
| 
 | |
|    void clear()
 | |
|    {
 | |
|       for (typename std::list<T*>::iterator i = m_StorageList.begin(); i != m_StorageList.end(); ++ i)
 | |
|       {
 | |
|          (*i)->release();
 | |
|          delete *i;
 | |
|       }
 | |
|       m_StorageList.clear();
 | |
|       for (typename std::vector<ItemPtrList>::iterator i = m_vHashPtr.begin(); i != m_vHashPtr.end(); ++ i)
 | |
|          i->clear();
 | |
|       m_iCurrSize = 0;
 | |
|    }
 | |
| 
 | |
| private:
 | |
|    std::list<T*> m_StorageList;
 | |
|    typedef typename std::list<T*>::iterator ItemPtr;
 | |
|    typedef std::list<ItemPtr> ItemPtrList;
 | |
|    std::vector<ItemPtrList> m_vHashPtr;
 | |
| 
 | |
|    int m_iMaxSize;
 | |
|    int m_iHashSize;
 | |
|    int m_iCurrSize;
 | |
| 
 | |
|    srt::sync::Mutex m_Lock;
 | |
| 
 | |
| private:
 | |
|    CCache(const CCache&);
 | |
|    CCache& operator=(const CCache&);
 | |
| };
 | |
| 
 | |
| 
 | |
| class CInfoBlock
 | |
| {
 | |
| public:
 | |
|    uint32_t m_piIP[4];        // IP address, machine read only, not human readable format.
 | |
|    int m_iIPversion;          // Address family: AF_INET or AF_INET6.
 | |
|    uint64_t m_ullTimeStamp;   // Last update time.
 | |
|    int m_iSRTT;               // Smoothed RTT.
 | |
|    int m_iBandwidth;          // Estimated link bandwidth.
 | |
|    int m_iLossRate;           // Average loss rate.
 | |
|    int m_iReorderDistance;    // Packet reordering distance.
 | |
|    double m_dInterval;        // Inter-packet time (Congestion Control).
 | |
|    double m_dCWnd;            // Congestion window size (Congestion Control).
 | |
| 
 | |
| public:
 | |
|    CInfoBlock() {} // NOTE: leaves uninitialized
 | |
|    CInfoBlock& copyFrom(const CInfoBlock& obj);
 | |
|    CInfoBlock(const CInfoBlock& src) { copyFrom(src); }
 | |
|    CInfoBlock& operator=(const CInfoBlock& src) { return copyFrom(src); }
 | |
|    bool operator==(const CInfoBlock& obj) const;
 | |
|    CInfoBlock* clone();
 | |
|    int getKey();
 | |
|    void release() {}
 | |
| 
 | |
| public:
 | |
| 
 | |
|       /// convert sockaddr structure to an integer array
 | |
|       /// @param [in] addr network address
 | |
|       /// @param [in] ver IP version
 | |
|       /// @param [out] ip the result machine readable IP address in integer array
 | |
| 
 | |
|    static void convert(const sockaddr_any& addr, uint32_t ip[4]);
 | |
| };
 | |
| 
 | |
| } // namespace srt
 | |
| 
 | |
| #endif
 |