2010-06-03 13 views
5

क्या वे मौजूद हैं?सी ++ लॉक-फ्री टेम्पलेटेड ऑब्जेक्टपूल

* स्पष्ट करने के लिए कहा:

वहाँ किसी भी प्रयोग करने योग्य पुस्तकालय है कि लागू ताला मुक्त (जो threadsafe है और spinlock या अन्य हल्के तुल्यकालन लागू हो सकता है) ObjectPool (http://en.wikipedia.org/wiki/Object_pool_pattern) सी में लिखे ++ भाषा है टेम्पलेट का उपयोग कर?

+2

सवाल किस तरह मैं यहाँ पूछ सकता हूँ? निश्चित रूप से प्रोग्रामिंग प्रश्न! जब तक आपके सवाल यह है कि के रूप में: विस्तृत और विशिष्ट अन्य प्रोग्रामर को स्पष्ट रूप से और ब्याज की बस लिखा - ताकि हम वास्तव में यह जवाब देने में सक्षम हो सकता है आपके प्रश्न पर एक थोड़ा और अधिक समय बिताने की कोशिश करें। –

+0

क्यों यह स्पष्ट नहीं है? क्या कोई उपयोगी लाइब्रेरी है जो लॉक-फ्री लागू करती है (जो थ्रेडसेफ है और स्पिनलॉक या अन्य हल्के सिंक्रनाइज़ेशन को कार्यान्वित कर सकती है) ऑब्जेक्टपूल (http://en.wikipedia.org/wiki/Object_pool_pattern) टेम्पलेट का उपयोग कर सी ++ भाषा में लिखी गई है? – uray

+0

मेरा मुद्दा यह है कि आपने अपने प्रश्न में आपके टिप्पणी में लगभग तीन गुना अधिक जानकारी शामिल की है, और मुझे लगता है कि यह दूसरी तरफ होना चाहिए। –

उत्तर

3

मैं अपने ही वस्तु पूल लेखन समाप्त हो गया है, इसके धागे की सुरक्षित, ताला मुक्त और मल्टी कोर स्केलेबल, बेंचमार्क:

यह इंटेल कोर पर 16.6 लाख प्रति सेकंड उधार-रिटर्न संचालन कर सकता है 2 Quad 2.4 गीगा Win7-64 4 धागे

का उपयोग कर

`

#define CACHE_LINE_SIZE 64 
#define alignCache __declspec(align(CACHE_LINE_SIZE)) 
#ifdef _WIN64 
# define alignArch __declspec(align(8)) 
#else 
# define alignArch __declspec(align(4)) 
#endif 

class InterlockedFlag { 
    protected: 
     alignArch volatile unsigned int value; 
    public: 
     inline void set(unsigned int val) { 
      this->value = val; 
     } 
     inline unsigned int exchange(unsigned int val) { 
      return InterlockedExchange(&this->value,val); 
     } 
}; 

#pragma pack(push,1) 
template <typename T> struct ObjectPoolNode { 
    ObjectPoolNode<T>* next; 
    T data; 
    ObjectPoolNode() : next(nullptr) { }; 
}; 
#pragma pack(pop,1) 

template <typename T> struct alignCache ObjectPoolList { 
    ObjectPoolList<T>* nextList; 
    char pad1[CACHE_LINE_SIZE - sizeof(ObjectPoolList<T>*)]; 
    ObjectPoolNode<T>* first; 
    char pad2[CACHE_LINE_SIZE - sizeof(ObjectPoolNode<T>*)]; 
    InterlockedFlag consumerLock; 
    char pad3[CACHE_LINE_SIZE - sizeof(InterlockedFlag)]; 
    ObjectPoolNode<T>* last; 
    char pad4[CACHE_LINE_SIZE - sizeof(ObjectPoolNode<T>*)]; 
    InterlockedFlag producerLock; 
    char pad5[CACHE_LINE_SIZE - sizeof(InterlockedFlag)]; 
    ObjectPoolNode<T>** storage;     
    char pad6[CACHE_LINE_SIZE - sizeof(ObjectPoolNode<T>**)]; 
    size_t available; 
    size_t count; 

    ObjectPoolList(size_t count) 
     : producerLock(false), consumerLock(false) 
    { 
     this->available = this->count = count; 
     this->storage = new ObjectPoolNode<T>*[count+1]; 
     for(size_t i=0 ; i<count+1 ; i++) { 
      this->storage[i] = new ObjectPoolNode<T>; 
     } 
     for(size_t i=0 ; i<count ; i++) { 
      this->storage[i]->next = this->storage[i+1]; 
     } 
     this->first = this->storage[0]; 
     this->last = this->storage[count];   
    } 

    ~ObjectPoolList() { 
     this->count = 0; 
     this->available = 0; 
     if(this->storage) { 
      for(size_t i=0 ; i<count+1 ; i++) { 
       delete this->storage[i]; 
      } 
      delete[] this->storage; 
      this->storage = NULL; 
     } 
    } 
}; 

template <typename T> class alignCache ObjectPool { 
private: 
    ObjectPoolList<T>** lists; 
    char pad1[CACHE_LINE_SIZE - sizeof(ObjectPoolList<T>**)]; 
    size_t available; 
    size_t listCount; 
public: 
    ObjectPool(size_t count,size_t parallelCount = 0) { 
     this->available = count; 
     this->listCount = parallelCount; 
     if(this->listCount == 0) { 
      this->listCount = getSystemLogicalProcessor(); //default 
     }  
     this->lists = new ObjectPoolList<T>*[this->listCount]; 
     for(size_t i=0 ; i<this->listCount ; i++) { 
      this->lists[i] = new ObjectPoolList<T>(count/this->listCount); 
     } 
     for(size_t i=0 ; i<this->listCount-1 ; i++) { 
      this->lists[i]->nextList = this->lists[i+1]; 
     } 
     this->lists[this->listCount-1]->nextList = this->lists[0]; 
    } 

    ~ObjectPool() { 
     if(this->lists) { 
      for(size_t i=0 ; i<this->listCount ; i++) { 
       delete this->lists[i]; 
      } 
      delete[] this->lists; 
      this->lists = NULL; 
     } 
     this->available = 0; 
     this->listCount = 0; 
    } 

    T* borrowObj() { 
     ObjectPoolList<T>* list = this->lists[0]; 
     while(!list->available || list->consumerLock.exchange(true)) { 
      if(!this->available) { 
       return NULL; 
      } 
      list = list->nextList; 
     } 
     if(list->first->next) { 
      ObjectPoolNode<T>* usedNode = list->first; 
      list->first = list->first->next; 
      list->available--; 
      this->available--; 
      list->consumerLock.set(false); 
      usedNode->next = nullptr; 
      return &usedNode->data;      
     }   
     list->consumerLock.set(false); 
     return NULL; 
    } 

    void returnObj(T* object) { 
     ObjectPoolNode<T>* node = (ObjectPoolNode<T>*)(((char*)object) - sizeof(ObjectPoolNode<T>*)); 
     ObjectPoolList<T>* list = this->lists[0]; 
     while(list->producerLock.exchange(true)) { 
      list = list->nextList; 
     } 
     list->last->next = node; 
     list->last  = node; 
     list->producerLock.set(false); 
     list->available++; 
     this->available++; 
    } 
}; 

`

+0

विंडोज विशिष्ट दिखता है ('इंटरलॉक एक्सचेंज' कह रहा है), क्या यह मामला है? –

+0

स्टोरेज तत्वों को गलत तरीके से हटाने से पहले ऑब्जेक्टपूललिस्ट() में 0 पर गिनती रीसेट नहीं कर रहा है? – vavan

+0

"यह-> उपलब्ध नहीं होना चाहिए" और "यह-> उपलब्ध ++" परमाणु (इंटरलाक्ड) होना चाहिए? – vavan

1

आपकी सर्वश्रेष्ठ शर्त Boost.Pool देखें, और इसके लिए लॉक फ्री आवंटक/म्यूटेक्स इंटरफ़ेस लिखें।

+1

अगर मैं बूस्ट :: पूल का उपयोग करता हूं और बस अपने आवंटक को लॉक-फ्री आवंटक के साथ प्रतिस्थापित करता हूं, तो मुझे लगता है कि यह पूल लॉक-फ्री या इवेंट थ्रेड सुरक्षित नहीं है, क्योंकि बूस्ट :: पूल कार्यान्वित किया जा सकता है लिंक किए गए सूची या कुछ ऐसा जो थ्रेड-सुरक्षित नहीं है और आवंटन में सिंक्रनाइज़ेशन की आवश्यकता नहीं है, लेकिन उधार लेने की विधि में उपयोग करने योग्य() और वापसीReusable(), तो यह लॉक-फ्री पूल नहीं होगा मैं सही हूँ? – uray

0

यह देखते हुए कि लॉक-फ्री कतार हैं, मैं कहूंगा कि यदि पूल मौजूद नहीं है, तो निश्चित रूप से आप एक (लगभग) लॉक-फ्री पूल बना सकते हैं।

क्लासिक tmalloc आवंटक के साथ संयुक्त (जो लॉक हो सकता है लेकिन जितना संभव हो इसे से बचाता है), मुझे लगता है कि आप अपने लक्ष्य के करीब होंगे।

+1

मेरी चिंता यह है कि, यदि यह उच्च प्रदर्शन के साथ वास्तव में आसान या लॉक-फ्री के करीब है, तो मल्टीकोर के इन वर्षों के बाद, किसी ने इसे पहले ही लागू नहीं किया है? मेरे मामले में से एक, पहले ही यहां पूछताछ की गई है: http: //stackoverflow.com/questions/2953554/recycle-freed-objects। मैं लॉक-फ्री कतार को कार्यान्वित कर रहा हूं, लेकिन मैं ऑब्जेक्टपूल का उपयोग करके ढेर आवंटन को कम करके इसे थोड़ा सा अनुकूलित करना चाहता हूं। लेकिन यदि कोई कतार का "कतार नोड पूल" कतार – uray

+0

हम का उपयोग करके लागू किया गया है, तो यह कोई प्रदर्शन लाभ होगा, यह बहुत अनावश्यक लगता है: मुझे डर है कि यह तब काम नहीं करेगा। –

संबंधित मुद्दे