diff --git a/srtcore/cache.cpp b/srtcore/cache.cpp index 4cda9a70f..2c6f624c4 100644 --- a/srtcore/cache.cpp +++ b/srtcore/cache.cpp @@ -38,7 +38,6 @@ written by Yunhong Gu, last updated 05/05/2009 *****************************************************************************/ - #include "platform_sys.h" #include @@ -49,70 +48,70 @@ using namespace std; srt::CInfoBlock& srt::CInfoBlock::copyFrom(const CInfoBlock& obj) { - std::copy(obj.m_piIP, obj.m_piIP + 4, m_piIP); - m_iIPversion = obj.m_iIPversion; - m_ullTimeStamp = obj.m_ullTimeStamp; - m_iSRTT = obj.m_iSRTT; - m_iBandwidth = obj.m_iBandwidth; - m_iLossRate = obj.m_iLossRate; - m_iReorderDistance = obj.m_iReorderDistance; - m_dInterval = obj.m_dInterval; - m_dCWnd = obj.m_dCWnd; - - return *this; + std::copy(obj.m_piIP, obj.m_piIP + 4, m_piIP); + m_iIPversion = obj.m_iIPversion; + m_ullTimeStamp = obj.m_ullTimeStamp; + m_iSRTT = obj.m_iSRTT; + m_iBandwidth = obj.m_iBandwidth; + m_iLossRate = obj.m_iLossRate; + m_iReorderDistance = obj.m_iReorderDistance; + m_dInterval = obj.m_dInterval; + m_dCWnd = obj.m_dCWnd; + + return *this; } bool srt::CInfoBlock::operator==(const CInfoBlock& obj) const { - if (m_iIPversion != obj.m_iIPversion) - return false; + if (m_iIPversion != obj.m_iIPversion) + return false; - else if (m_iIPversion == AF_INET) - return (m_piIP[0] == obj.m_piIP[0]); + else if (m_iIPversion == AF_INET) + return (m_piIP[0] == obj.m_piIP[0]); - for (int i = 0; i < 4; ++ i) - { - if (m_piIP[i] != obj.m_piIP[i]) - return false; - } + for (int i = 0; i < 4; ++i) + { + if (m_piIP[i] != obj.m_piIP[i]) + return false; + } - return true; + return true; } srt::CInfoBlock* srt::CInfoBlock::clone() { - CInfoBlock* obj = new CInfoBlock; - - std::copy(m_piIP, m_piIP + 4, obj->m_piIP); - obj->m_iIPversion = m_iIPversion; - obj->m_ullTimeStamp = m_ullTimeStamp; - obj->m_iSRTT = m_iSRTT; - obj->m_iBandwidth = m_iBandwidth; - obj->m_iLossRate = m_iLossRate; - obj->m_iReorderDistance = m_iReorderDistance; - obj->m_dInterval = m_dInterval; - obj->m_dCWnd = m_dCWnd; - - return obj; + CInfoBlock* obj = new CInfoBlock; + + std::copy(m_piIP, m_piIP + 4, obj->m_piIP); + obj->m_iIPversion = m_iIPversion; + obj->m_ullTimeStamp = m_ullTimeStamp; + obj->m_iSRTT = m_iSRTT; + obj->m_iBandwidth = m_iBandwidth; + obj->m_iLossRate = m_iLossRate; + obj->m_iReorderDistance = m_iReorderDistance; + obj->m_dInterval = m_dInterval; + obj->m_dCWnd = m_dCWnd; + + return obj; } int srt::CInfoBlock::getKey() { - if (m_iIPversion == AF_INET) - return m_piIP[0]; + if (m_iIPversion == AF_INET) + return m_piIP[0]; - return m_piIP[0] + m_piIP[1] + m_piIP[2] + m_piIP[3]; + return m_piIP[0] + m_piIP[1] + m_piIP[2] + m_piIP[3]; } void srt::CInfoBlock::convert(const sockaddr_any& addr, uint32_t aw_ip[4]) { - if (addr.family() == AF_INET) - { - aw_ip[0] = addr.sin.sin_addr.s_addr; - aw_ip[1] = aw_ip[2] = aw_ip[3] = 0; - } - else - { - memcpy((aw_ip), addr.sin6.sin6_addr.s6_addr, sizeof addr.sin6.sin6_addr.s6_addr); - } + if (addr.family() == AF_INET) + { + aw_ip[0] = addr.sin.sin_addr.s_addr; + aw_ip[1] = aw_ip[2] = aw_ip[3] = 0; + } + else + { + memcpy((aw_ip), addr.sin6.sin6_addr.s6_addr, sizeof addr.sin6.sin6_addr.s6_addr); + } } diff --git a/srtcore/cache.h b/srtcore/cache.h index d5a037633..d7f586c20 100644 --- a/srtcore/cache.h +++ b/srtcore/cache.h @@ -54,220 +54,215 @@ namespace srt class CCacheItem { public: - virtual ~CCacheItem() {} + virtual ~CCacheItem() {} public: - virtual CCacheItem& operator=(const CCacheItem&) = 0; + virtual CCacheItem& operator=(const CCacheItem&) = 0; - // The "==" operator SHOULD only compare key values. - virtual bool 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. + /// get a deep copy clone of the current item + /// @return Pointer to the new item, or NULL if failed. - virtual CCacheItem* clone() = 0; + 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. + /// 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; + 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() {} + // 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 class CCache +template +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(); - } + 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) + /// 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) { - last_item_list.erase(i); - break; + // copy the cached info + *data = ***i; + return 0; } - } + } - last_data->release(); - delete last_data; - m_StorageList.pop_back(); - -- m_iCurrSize; - } + return -1; + } - return 0; - } + /// 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. -private: + 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; + } - /// Specify the cache size (i.e., max number of items). - /// Private or else must be protected by a lock. - /// @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. - /// Private or else must be protected by a lock. - void clear() - { - for (typename std::list::iterator i = m_StorageList.begin(); i != m_StorageList.end(); ++ i) - { - (*i)->release(); - delete *i; - } - m_StorageList.clear(); - for (typename std::vector::iterator i = m_vHashPtr.begin(); i != m_vHashPtr.end(); ++ i) - i->clear(); - m_iCurrSize = 0; - } + return 0; + } private: - std::list m_StorageList; - typedef typename std::list::iterator ItemPtr; - typedef std::list ItemPtrList; - std::vector m_vHashPtr; + /// Specify the cache size (i.e., max number of items). + /// Private or else must be protected by a lock. + /// @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. + /// Private or else must be protected by a lock. + void clear() + { + for (typename std::list::iterator i = m_StorageList.begin(); i != m_StorageList.end(); ++i) + { + (*i)->release(); + delete *i; + } + m_StorageList.clear(); + for (typename std::vector::iterator i = m_vHashPtr.begin(); i != m_vHashPtr.end(); ++i) + i->clear(); + m_iCurrSize = 0; + } - int m_iMaxSize; - int m_iHashSize; - int m_iCurrSize; +private: + std::list m_StorageList; + typedef typename std::list::iterator ItemPtr; + typedef std::list ItemPtrList; + std::vector m_vHashPtr; + + int m_iMaxSize; + int m_iHashSize; + int m_iCurrSize; - srt::sync::Mutex m_Lock; + srt::sync::Mutex m_Lock; private: - CCache(const CCache&); - CCache& operator=(const CCache&); + 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). + 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() {} + 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 - /// 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]); + static void convert(const sockaddr_any& addr, uint32_t ip[4]); }; } // namespace srt