c++ can not get value from map - c++

I have implemented a serializer to send data over network. And I have implemented a system that can deserialize primitive data, string, map(string, string), map(string, float), but the error happens with map(string, int) when the deserialized map is used to fetch the value from key. In the debugger I can see that map receive correct value but when I'm trying to get data, I get an error "std::out_of_range at memory location".
Here is my code
#include <stdint.h>
#include <memory>
#include <string>
#include <map>
#include <algorithm>
#define STREAM_ENDIANNESS 0
#define PLATFORM_ENDIANNESS 0
using namespace std;
class OutputMemoryStream
{
void ReallocBuffer(uint32_t inNewLength)
{
mBuffer = static_cast<char*>(std::realloc(mBuffer, inNewLength));
mCapacity = inNewLength;
}
char* mBuffer = nullptr;
uint32_t mHead;
uint32_t mCapacity;
public:
OutputMemoryStream() : mHead(0) { ReallocBuffer(32); }
~OutputMemoryStream()
{
if (mBuffer) { mBuffer = nullptr; }
}
char* GetBufferPtr() const { return mBuffer; }
uint32_t GetLength() const { return mHead; }
void Write(const void* inData, size_t inByteCount)
{
//make sure we have space...
uint32_t resultHead = mHead + static_cast<uint32_t>(inByteCount);
if (resultHead > mCapacity)
{
ReallocBuffer(std::max(mCapacity * 2, resultHead));
}
//copy into buffer at head
std::memcpy(mBuffer + mHead, inData, inByteCount);
//increment head for next write
mHead = resultHead;
}
template< typename T > void Write(T inData)
{
static_assert(std::is_arithmetic< T >::value || std::is_enum< T >::value, "Generic Write only supports primitive data types");
if (STREAM_ENDIANNESS == PLATFORM_ENDIANNESS)
{
Write(&inData, sizeof(inData));
}
else { }
}
template< typename T >
void Write(const std::map< string, T >& inMap)
{
uint32_t elementCount = inMap.size();
Write(elementCount);
for (std::pair<string, T> element : inMap)
{
Write(element.first);
Write(element.second);
}
}
void Write(const std::string& inString)
{
size_t elementCount = inString.size();
Write(elementCount + 1);
Write(inString.data(), (elementCount + 1) * sizeof(char));
}
};
class InputMemoryStream
{
private:
char* mBuffer;
uint32_t mHead;
uint32_t mCapacity;
public:
InputMemoryStream() {}
InputMemoryStream(char* inBuffer, uint32_t inByteCount) : mBuffer(inBuffer), mCapacity(inByteCount), mHead(0) { }
~InputMemoryStream()
{
if (mBuffer) { mBuffer = nullptr; }
}
uint32_t GetRemainingDataSize() const
{
return mCapacity - mHead;
}
void Read(void* outData, uint32_t inByteCount)
{
uint32_t resultHead = mHead + inByteCount;
if (resultHead > mCapacity)
{
//handle error, no data to read!
//...
}
std::memcpy(outData, mBuffer + mHead, inByteCount);
mHead = resultHead;
}
template< typename T > void Read(T& outData)
{
static_assert(std::is_arithmetic< T >::value || std::is_enum< T >::value, "Generic Read only supports primitive data types");
Read(&outData, sizeof(outData));
}
template<typename T1>
void Read(std::map<string, T1> &mapP)
{
size_t elemenCount;
Read(elemenCount);
for (int i = 0; i < elemenCount; i++)
{
string key; T1 value;
Read(key);
Read(value);
std::pair<string, T1> pair(key, value);
mapP.insert(pair);
}
}
void Read(string &outString)
{
size_t strSize;
Read(strSize);
outString.resize(strSize);
for (int i = 0; i < strSize; i++)
{
Read(&outString[i], 1);
}
}
};
class ServerObject
{
OutputMemoryStream outStream;
InputMemoryStream inStream;
map<std::string, int> mapInt;
public:
ServerObject() {};
ServerObject(char* byteArray, int byteCount)
{
InputMemoryStream inStream(byteArray, byteCount);
Deserialize(inStream);
}
~ServerObject() {};
void Serialize()
{
outStream.Write(mapInt);
}
void Deserialize(InputMemoryStream inStream)
{
inStream.Read(mapInt);
}
OutputMemoryStream GetOutStream()
{
return outStream;
}
int GetInt(string key)
{
return mapInt.at(key);
}
void PutInt(string key, int value)
{
mapInt.insert(std::pair<string, int>(key, value));
}
};
int main()
{
ServerObject * so = new ServerObject();
so->PutInt("test", 10);
so->Serialize();
ServerObject * so1 = new ServerObject(so->GetOutStream().GetBufferPtr(), so->GetOutStream().GetLength());
int i = so1->GetInt("test");
system("pause>NULL");
return 0;
}

Your void Write(const std::string& inString) function of OutputMemoryStream should not store additional byte of buffer for null terminator because std::string will not contain null terminator but if you use c_str(), a null terminator will be included in the return from this method. Don't get confused with the internal structure of the memory. std::string stores the length of the string in its member variable so there is no need of null terminator. The function should be as shown below.
void Write(const std::string& inString)
{
size_t elementCount = inString.size();
Write(elementCount);
Write(inString.data(), elementCount * sizeof(char));
}

Related

how to override base class with template child?

I have the following code.
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <cmath>
class Configuration {
protected:
static std::map<std::string, Configuration*> commands;
static std::vector<Configuration*> commidx;
const std::string name;
const int index;
int (*snippet)(float);
public:
Configuration(std::string name, const int index, int (*snippet)(float))
: name(std::move(name)), index(index), snippet(snippet) {}
virtual ~Configuration() = default;
virtual void set(float val) {} //should we raise an error?
virtual float get() { return NAN; } //should we raise an error?
};
template<typename T>
class Config : public Configuration {
const std::string type;
const std::string def;
T cur, min, max;
public:
explicit Config(const char *name, int index, const char *_type, const char *def, int (*snippet)(float), T min , T max)
: Configuration(name, index, snippet)
, type(_type)
, def(def)
, min(min)
, max(max)
{
if (type == "float") {
cur = std::stof(def);
} else if (type == "integer") {
cur = std::stoi(def);
} else if (type == "bool") {
cur = std::stof(def) != 0;
} else {
SPDLOG_ERROR("unknownt type {}", type);
}
}
void set(T val) override {
if (val < min) val = min;
if (val > max) val = max;
if (val != cur) {
val = cur;
snippet(val);
}
}
T get() override {
return cur;
}
};
std::vector<Configuration*> Configuration::commidx {
new Config<float>("fff", 0, "float", "0.4", nullptr, 0, 1),
new Config<bool>("bbb", 1, "bool", "0", nullptr, 0, 1),
new Config<integer>("iii", 8, "int", "0", nullptr, 0, 3),
};
This bombs in compilation because set() and get() methods don't really override base class.
How can I achieve desired result: put in the same vector of pointers to slightly different template classes?
You can try something like following.
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <cmath>
class Configuration
{
protected:
static std::map<std::string, Configuration *> commands;
static std::vector<Configuration *> commidx;
const std::string name;
const int index;
int (*snippet)(float);
public:
Configuration(std::string name, const int index, int (*snippet)(float))
: name(std::move(name)), index(index), snippet(snippet) {}
virtual ~Configuration() = default;
};
template <typename T>
class ConfigurationBase : public Configuration
{
public:
ConfigurationBase(std::string name, const int index, int (*snippet)(float))
: Configuration(name, index, snippet)
{
}
//virtual void set(T val) {}
//virtual T get() { return NAN; }
virtual void set(T val) = 0;
virtual T get() = 0;
};
template <typename T>
class Config : public ConfigurationBase<T>
{
const std::string type;
const std::string def;
T cur, min, max;
public:
explicit Config(const char *name, int index, const char *_type, const char *def, int (*snippet)(float), T min, T max)
: ConfigurationBase<T>(name, index, snippet), type(_type), def(def), min(min), max(max)
{
if (type == "float")
{
cur = std::stof(def);
}
else if (type == "integer")
{
cur = std::stoi(def);
}
else if (type == "bool")
{
cur = std::stof(def) != 0;
}
else
{
// SPDLOG_ERROR("unknownt type {}", type);
}
}
void set(T val) override
{
if (val < min)
val = min;
if (val > max)
val = max;
if (val != cur)
{
val = cur;
// snippet(val);
}
}
T get() override
{
return cur;
}
};
std::vector<Configuration *> Configuration::commidx{
new Config<float>("fff", 0, "float", "0.4", nullptr, 0, 1),
new Config<bool>("bbb", 1, "bool", "0", nullptr, 0, 1),
new Config<int>("iii", 8, "int", "0", nullptr, 0, 3),
};

How to store class object having string in binary file?

I'm storing my class object in the binary file but I'm getting weird results when I load the data.
Following Code is Loading and Saving Data:
#include <iostream>
#include <fstream>
#include <memory>
#include <string>
#include <sstream>
using namespace std;
template <class C>
void Load(const char fileName[], C& obj)
{
ifstream in;
in.open(fileName, ios::in | ios::binary);
in.read(reinterpret_cast<char*>(addressof(obj)), sizeof(obj));
in.close();
return;
}
template <class T>
void Save(const char fileName[], T obj)
{
ofstream out;
out.open(fileName, ios::out | ios::binary);
out.write(reinterpret_cast<char const*>(addressof(obj)), sizeof(obj));
stringstream ss;
out.close();
return;
}
class Contact {
public:
int CompareTo(Contact obj)
{
return 1;
}
string ss;
int rollNum;
};
class Data {
public:
Data()
{
}
Contact arr[10];
};
int main()
{
const char fileName[] = "ContactMG.dat";
/*
Data *T = new Data();
for(int i=0;i<10;i++)
T->arr[i].ss = "fahad";
Save(fileName , *T);
*/
Data* d = new Data();
Load(fileName, *d);
for (int i = 0; i < 10; i++)
cout << d->arr[i].ss << endl;
}
/*
Console outPut:
ⁿx
p²x
σß╥Z∙
░▒▓│┤
>
☺Y╩
░‼╩
*/
/* Binary File
#® ® ®
*/
I want to ask how I can store this object in the binary file and load it?
I'm pretty sure the problem is with string but I don't know how to fix it!
I have already known to store strings in binary files but don't know how to store class objects which have string in it
I would introduce a new level of indirection, i.e. functions from_binary and to_binary, and implement your Load and Store in terms of those:
template <class C>
bool Load(const char fileName[], C& obj) {
if (ifstream in{fileName, ios::in | ios::binary}) {
from_binary(in, obj);
return true;
}
return false;
}
template <class T>
bool Save(const char fileName[], T obj) {
if (ofstream out{fileName, ios::out | ios::binary}) {
to_binary(out, obj);
return true;
}
return false;
}
For POD data types, from_binary and to_binary will just do what you already did in Load/Store (beware, however: pointers are PODs but saving an address is pretty much meaningless):
template <class T, typename = enable_if_t<is_pod_v<T>>>
void from_binary(ifstream& in, T& obj) {
in.read(reinterpret_cast<char*>(addressof(obj)), sizeof(obj));
}
template <class T, typename = enable_if_t<is_pod_v<T>>>
void to_binary(ofstream& out, T const& obj) {
out.write(reinterpret_cast<char const*>(addressof(obj)), sizeof(obj));
}
As pointed out in the comments, std::string is not a POD type. I'm going to serialize it by saving the character count and then the actual characters:
void from_binary(ifstream& in, string& str) {
std::size_t stringSize{0};
from_binary(in, stringSize);
str.reserve(stringSize);
for (size_t i = 0; i != stringSize; ++i) {
char ch{};
in.read(&ch, 1);
str.push_back(ch);
}
}
void to_binary(ofstream& out, string const& str) {
auto const stringSize = str.size();
to_binary(out, stringSize);
auto const* cStr = str.c_str();
out.write(cStr, stringSize);
}
Also, I'm going to serialize/deserialize an array by calling to_binary/from_binary on each element of the array:
template <class T, size_t N>
void from_binary(ifstream& in, T (&obj)[N]) {
for (auto& elem : obj) from_binary(in, elem);
}
template <class T, size_t N>
void to_binary(ofstream& out, T const (&obj)[N]) {
for (auto const& elem : obj) to_binary(out, elem);
}
The above functions are enough to implement from_binary and to_binary for your Contact and Data classes:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
template <class T, typename = enable_if_t<is_pod_v<T>>>
void from_binary(ifstream& in, T& obj) {
in.read(reinterpret_cast<char*>(addressof(obj)), sizeof(obj));
}
template <class T, typename = enable_if_t<is_pod_v<T>>>
void to_binary(ofstream& out, T const& obj) {
out.write(reinterpret_cast<char const*>(addressof(obj)), sizeof(obj));
}
void from_binary(ifstream& in, string& str) {
std::size_t stringSize{0};
from_binary(in, stringSize);
str.reserve(stringSize);
for (size_t i = 0; i != stringSize; ++i) {
char ch{};
in.read(&ch, 1);
str.push_back(ch);
}
}
void to_binary(ofstream& out, string const& str) {
auto const stringSize = str.size();
to_binary(out, stringSize);
auto const* cStr = str.c_str();
out.write(cStr, stringSize);
}
template <class T, size_t N>
void from_binary(ifstream& in, T (&obj)[N]) {
for (auto& elem : obj) from_binary(in, elem);
}
template <class T, size_t N>
void to_binary(ofstream& out, T const (&obj)[N]) {
for (auto const& elem : obj) to_binary(out, elem);
}
template <class C>
bool Load(const char fileName[], C& obj) {
if (ifstream in{fileName, ios::in | ios::binary}) {
from_binary(in, obj);
return true;
}
return false;
}
template <class T>
bool Save(const char fileName[], T obj) {
if (ofstream out{fileName, ios::out | ios::binary}) {
to_binary(out, obj);
return true;
}
return false;
}
class Contact {
public:
int CompareTo(Contact obj) { return 1; }
string ss;
int rollNum;
};
void from_binary(ifstream& in, Contact& obj) {
from_binary(in, obj.ss);
from_binary(in, obj.rollNum);
}
void to_binary(ofstream& out, Contact const& obj) {
to_binary(out, obj.ss);
to_binary(out, obj.rollNum);
}
class Data {
public:
Data() {}
Contact arr[10];
};
void from_binary(ifstream& in, Data& obj) { from_binary(in, obj.arr); }
void to_binary(ofstream& out, Data const& obj) { to_binary(out, obj.arr); }
int main() {
const char fileName[] = "ContactMG.dat";
{
Data data;
auto const contactCount = sizeof(data.arr) / sizeof(data.arr[0]);
for (size_t c = 0; c != contactCount; ++c) {
data.arr[c].ss = "some name " + to_string(c);
data.arr[c].rollNum = c;
}
Save(fileName, data);
}
{
Data data;
Load(fileName, data);
for (auto const& contact : data.arr)
cout << "Contact: rollNum=" << contact.rollNum
<< ", ss=" << contact.ss << '\n';
}
}
Output:
Contact: rollNum=0, ss=some name 0
Contact: rollNum=1, ss=some name 1
Contact: rollNum=2, ss=some name 2
Contact: rollNum=3, ss=some name 3
Contact: rollNum=4, ss=some name 4
Contact: rollNum=5, ss=some name 5
Contact: rollNum=6, ss=some name 6
Contact: rollNum=7, ss=some name 7
Contact: rollNum=8, ss=some name 8
Contact: rollNum=9, ss=some name 9
Although this may solve your particular issue, the number of overloads you'll need for from_binary and to_binary will grow very rapidly as your project grows. So I'd definetely check if there's a more comprehensive (and well tested) library solution out there.

Can BOOST_FOREACH be customized for a pointer type?

I'm writing C++98 (sorry), but working with a C library, which has many objects stored in data structures of the form:
struct c_container
{
size_t len;
int data[1];
};
struct c_container *make_container(size_t n)
{
if (n == 0)
return NULL;
struct c_container *rv = (struct c_container *)malloc(sizeof(rv->len) + n*sizeof(rv->data));
rv->len = n;
return rv;
}
I'd like to do C++-style iteration using BOOST_FOREACH, but this doesn't work. (The "old style" of manually calling the range_begin and range_end functions does work).
inline int *range_begin(c_container *c)
{
return c ? &c->data[0] : NULL;
}
inline int *range_end(c_container *c)
{
return c ? &c->data[c->len] : NULL;
}
inline const int *range_begin(const c_container *c)
{
return c ? &c->data[0] : NULL;
}
inline const int *range_end(const c_container *c)
{
return c ? &c->data[c->len] : NULL;
}
namespace boost
{
template<>
struct range_mutable_iterator<c_container *>
{
typedef int *type;
};
template<>
struct range_const_iterator<c_container *>
{
typedef const int *type;
};
}
int main()
{
c_container *coll = make_container(3);
coll->data[0] = 1;
coll->data[1] = 42;
coll->data[2] = -1;
BOOST_FOREACH(int i, coll)
{
std::cout << i << std::endl;
}
}
This is all that should be necessary, according to http://www.boost.org/doc/libs/1_65_1/doc/html/foreach/extensibility.html (and I've tested it with classes)
However, that example uses a class, whereas I'm using a pointer to a class. Based on my investigation, it appears to be using the codepath that is only intended for const char * and const wchar_t *:
In file included from boost-foreach.cpp:6:0:
/usr/include/boost/foreach.hpp: In function ‘bool boost::foreach_detail_::done(const boost::foreach_detail_::auto_any_base&, const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<T*, C>*) [with T = c_container, C = mpl_::bool_<false>, const boost::foreach_detail_::auto_any_base& = const boost::foreach_detail_::auto_any_base&]’:
boost-foreach.cpp:65:5: instantiated from here
/usr/include/boost/foreach.hpp:749:57: error: no match for ‘operator!’ in ‘!* boost::foreach_detail_::auto_any_cast [with T = c_container*, C = mpl_::bool_<false>, typename boost::mpl::if_<C, const T, T>::type = c_container*, const boost::foreach_detail_::auto_any_base& = const boost::foreach_detail_::auto_any_base&](((const boost::foreach_detail_::auto_any_base&)((const boost::foreach_detail_::auto_any_base*)cur)))’
/usr/include/boost/foreach.hpp:749:57: note: candidate is: operator!(bool) <built-in>
Is there some additional boost trait to specialize or something?
It seems to be difficult to define the range functions for pointer types. But you can define them for c_container directly. The code looks like this:
#include <cstdlib>
#include <iostream>
#include <boost/foreach.hpp>
struct c_container
{
size_t len;
int data[1];
};
struct c_container *make_container(size_t n)
{
if (n == 0)
return NULL;
struct c_container *rv = (struct c_container *)malloc(sizeof(rv->len) + n * sizeof(rv->data));
rv->len = n;
return rv;
}
inline int *range_begin(c_container &c)
{
return c.len > 0 ? &c.data[0] : NULL;
}
inline int *range_end(c_container &c)
{
return c.len > 0 ? &c.data[c.len] : NULL;
}
inline const int *range_begin(const c_container &c)
{
return c.len > 0 ? &c.data[0] : NULL;
}
inline const int *range_end(const c_container &c)
{
return c.len > 0 ? &c.data[c.len] : NULL;
}
namespace boost
{
template<>
struct range_mutable_iterator<c_container>
{
typedef int *type;
};
template<>
struct range_const_iterator<c_container>
{
typedef const int *type;
};
}
#define MY_FOREACH(x, y) BOOST_FOREACH(x, *y)
int main()
{
c_container *coll = make_container(3);
coll->data[0] = 1;
coll->data[1] = 42;
coll->data[2] = -1;
//BOOST_FOREACH(int i, *coll)
MY_FOREACH(int i, coll)
{
std::cout << i << std::endl;
}
}
Note that the BOOST_FOREACH loop does not iterate over a pointer type. As a workaround you may define your own FOREACH that does so as shown in the code above.

Pure virtual function error

I receive this error:
In function 'bool detect_feedback(AudioEffect*)':
54:30: error: cannot convert 'std::shared_ptr<AudioEffect>' to 'AudioEffect*' in assignment
55:16: error: cannot convert 'std::shared_ptr<AudioEffect>' to 'AudioEffect*' in assignment
55:40: error: cannot convert 'std::shared_ptr<AudioEffect>' to 'AudioEffect*' in assignment
The code is as follows:
#include<stdlib.h>
#include<iostream>
#include<memory>`
//BASE CLASS
// audio and have a subsequent effect (next).
struct AudioEffect
{
virtual ~AudioEffect() = default;
virtual void process(float* buf, size_t num) = 0;
std::shared_ptr<AudioEffect> next;
};
//DERIVING MULTIPLE AUDIO-EFFECTS
//Noise Gate
struct NoiseGate: public AudioEffect
{
float threshold;
void process(float *buf, size_t num)
{
if (*buf > threshold)
*buf = threshold;
}
};
//Gain Boost
struct GainBoost: public AudioEffect
{
float signal;
void process(float *buf, size_t num)
{
*buf = *buf + signal;
}
};
//Compressor
struct Compressor: public AudioEffect
{
float offset;
void process(float *buf, size_t num)
{
*buf = *buf - offset;
}
};
//Function
// Implement a function that checks if there is a feedback loop
// in the effects chain.
//... detect_feedback(...)
//{
//}
bool detect_feedback (AudioEffect *ae)
{
AudioEffect *p, *q;
for (p = ae;p != NULL; p = p->next)
for (q = p->next; q != NULL; q = q->next)
if (typeid(*p) == typeid(*q))
return true;
return false;
}
//MAIN
int main(int argc, char *argv[])
{
return 0;
}
You can not assign a shared_ptr to a raw pointer. You need to use the .get() method to obtain a raw pointer.
(p->next).get()

boost::lock_guard waits forever

I'm developing a LRU-cache in C++, using boost mutexes and locks, in a multi-threaded environment.
The architecture is based on a boost::unordered_map + a lock-free-queue
Insertions work in non-blocking mode (try_lock), but removals should lock the map and proceed.
The problem is that very rarely, the cache-access deadlocks in the removal.
.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());
}
}
Can you explain me what's wrong? I'm almost sure it deadlocks in the removal as it is the only lock it must acquire.
Thanks everybody
edit: I'm using this cache in an apache module which runs mpm_prefork_module: could this be the problem? Should I use boost::interprocess instead of boost::thread?