boost :: lock_guard永远等待

时间:2012-06-01 07:18:49

标签: c++ boost locking deadlock boost-mutex

我正在C ++中开发一个LRU-cache,在多线程环境中使用boost互斥锁和锁。 该架构基于boost :: unordered_map + a lock-free-queue 插入以非阻塞模式(try_lock)工作,但删除应锁定地图并继续。 问题是很少,缓存访问死锁在删除。

·H

typedef boost::function<std::string ( const std::string &key )> LoaderFunction;

class ListNode;

struct CacheEntry {
    CacheEntry(std::string key="", std::string value="");
    ListNode * createLruListNode() const;
    ListNode * getLruListNode() const;
    virtual ~CacheEntry();
    const std::string key;
    const std::string value;
private:
    ListNode ** listNodePP;
};

struct ListNode {
    ListNode(const CacheEntry* entry = NULL);
    ~ListNode();
    void setCacheEntry(const CacheEntry* entry);
    const CacheEntry * getCacheEntry();
    void setDirty();

private:
    const CacheEntry * cacheEntry;
    bool dirty;
};

typedef LockFreeQueue<ListNode*> List;


typedef boost::unordered_map
        < const string               , const CacheEntry * >
Cache;

typedef Cache::iterator CacheIter;

的.cpp

#include "LockFreeQueue.h"
#include <unistd.h>

using namespace std;

/* ... */

ListNode::ListNode(const CacheEntry* e2) : cacheEntry(e2) {
    dirty=false;
}

void ListNode::setCacheEntry(const CacheEntry* entry) {
    cacheEntry=entry;
}

const CacheEntry* ListNode::getCacheEntry() {
    if(dirty) {
        return NULL;
    }
    return cacheEntry;
}

void ListNode::setDirty() {
    dirty=true;
}

std::string PeachCachePartition::get(const string key) {
    CacheIter iter=cache->find(key);
    string value;
    if(iter!=cache->end()) { 
        __sync_fetch_and_add(_hits,1);
        const CacheEntry* entry=iter->second;
        value=(entry->value);

        lruList->enqueue(entry->getLruListNode());
        if(size() > max) { // removes some
            int howMany = (int) ceil((*_misses)/(*_hits))+1;
            int k=0;
            ListNode removedListNode=ListNode();
            ListNode * p=&removedListNode;
            ListNode ** pp=&p;
            while(size() > max && k<howMany) {

                if(lruList->dequeue(pp)) {
                    const CacheEntry * toBeRemoved=p->getCacheEntry();
                    if(toBeRemoved) {
                        remove(toBeRemoved->key);
                        k++;
                    }
                }


            }
        }
    } else { 
        __sync_fetch_and_add(_misses,1);
        value=loader(key);
        if(value.size()>0) {
            put(key,value);
        }
    }
    return value;
}

void PeachCachePartition::remove(const std::string &key) {
    try {
        boost::lock_guard<boost::mutex> mapLockGuard(mapMutex);
        CacheIter iter = cache->find(key);
        if(iter!=cache->end()) {
            const CacheEntry * toBeRemoved=iter->second;
            if(toBeRemoved->getLruListNode()) {
                toBeRemoved->getLruListNode()->setDirty();
            }

            delete(toBeRemoved);
            cache->erase(iter);
            __sync_sub_and_fetch(_size,1);
        }
    } catch (std::exception &e) {
        Logger::err(e.what());
    }
}


void PeachCachePartition::put(const std::string &key, std::string &value) {
    try {
        boost::unique_lock<boost::mutex> mapLockGuard(mapMutex,boost::try_to_lock);
        if(mapLockGuard.owns_lock()) {
            CacheIter iter=cache->find(key);
            const CacheEntry * entry;
            if(iter!=cache->end()) {
                entry=iter->second;
                entry->getLruListNode()->setDirty();
            } else {
                entry = new CacheEntry(key,value);
                __sync_add_and_fetch(_size,1);
                (*cache)[key] = entry;
            }

            entry->createLruListNode()->setCacheEntry(entry);

            lruList->enqueue(entry->getLruListNode());
        }
    } catch (std::exception &e) {
        Logger::err(e.what());
    }
}

你能解释一下我的错吗?我几乎可以肯定它在移除中是死锁,因为它是必须获取的唯一锁。

谢谢大家

编辑:我在运行mpm_prefork_module的apache模块中使用此缓存:这可能是问题吗?我应该使用boost :: interprocess而不是boost :: thread吗?

0 个答案:

没有答案