包装了一个多线程安全的hash_map(好用),欢迎指点

Oversense 2003-09-20 02:17:10
class __buddy; // not implement
template<class Key,class Type,class Buddy = __buddy>
class simp_hash_map{
private:
typedef bool (Buddy::*Function)(Type& _val);
simp_hash_map(const simp_hash_map &);
simp_hash_map& operator=(const simp_hash_map &);
stdext::hash_map<Key,Type> _map;

// 因为可能出现在apply函数中erase某个元素的情况,
// 这样,如果_ite作为apply函数的变量,就可能指向一
// 个未知的地方,所以把_ite作为类变量,方便处理
typename stdext::hash_map<Key,Type>::iterator _ite;
CriticalSection _cs;
public:
simp_hash_map(){
_ite = _map.begin();
}
~simp_hash_map(){
}
bool insert(const Key& _key,const Type& _val){
CriticalSectionLock lock(_cs);
return _map.insert(std::pair<Key,Type>(_key,_val)).second;
}
int erase(const Key& _key){
CriticalSectionLock lock(_cs);
if(_ite != _map.end() && _ite->first == _key ){
_ite = _map.erase(_ite);
return 1;
}else{
return _map.erase(_key);
}
}
void clear(){
CriticalSectionLock lock(_cs);
_map.clear();
_ite = _map.begin();
}
bool find(const Key& _key,Type& _val){
CriticalSectionLock lock(_cs);
stdext::hash_map<Key,Type>::const_iterator _ite = _map.find(_key);
if( _ite == _map.end() )return false;
_val = _ite->second;
return true;
}
bool apply(Function _fun,Buddy * const _buddy){
CriticalSectionLock lock(_cs);
_ite = _map.begin();
while( _ite != _map.end()){
Type& _tval = _ite->second;
++_ite;

// 如果先_fun, 然后++_ite, 如果_fun
// erase掉当前的_ite,就漏掉当前_ite
// 的后一个元素,没有在上面执行_fun
if( (_buddy->*_fun)(_tval) )return true;
}
return false;
}
int size(){
CriticalSectionLock lock(_cs);
return _map.size();
}
};


下面是测试程序
class a{
public:
a(){
_map.insert(0,0);
_map.insert(1,1);
_map.insert(2,2);
_map.insert(3,3);
j = 5;
}
int j;
simp_hash_map<int,int,a> _map;
bool foo(int& _i){
_map.erase(_i + 1);
return false;
}
bool fox(int& _i){
printf("%d\n",_i);
return false;
}
void bar(){
_map.apply(foo,this);
_map.apply(fox,this);
}
};
int main(){
a _a;
_a.bar();
return 0;
}
...全文
671 37 打赏 收藏 转发到动态 举报
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
Oliver2002 2003-11-08
  • 打赏
  • 举报
回复
学习 !!
TH 2003-11-06
  • 打赏
  • 举报
回复
good
sevencat 2003-10-29
  • 打赏
  • 举报
回复
boost的thread基本上是对poisx线程的一个封装,我自己有一个自己的跨平台的线程和线程池封装。我觉得一般要在应用类上进行封装这类的多线程和内存封装,而不是在基础类上进行封装。因为基础类并不知道什么时候用多线程什么时候不用。会造成额外的开销。

就像SGI的那个OPERATOR NEW的内存封装,我也认为没什么必要。
xkak2 2003-10-28
  • 打赏
  • 举报
回复
缺乏iterator的容器,就不再符合STL的标准了。
另外,你直接使用Windows的API,我认为不是一个很好的办法。如果使用你的容器的代码需要夸平台(软件的核心部分常常会有此要求),那将是个灾难。STL本身是跨平台的,你更改过的容器也应该力争如此。
建议:boost的Thread库有跨平台的同步类,封装的很巧妙,考虑一下吧。
liuty2006 2003-10-28
  • 打赏
  • 举报
回复
mk
Oversense 2003-10-14
  • 打赏
  • 举报
回复
to sevencat(七猫) ( ):
标准库里面应该可以#define一下,或者怎么一下,就变成线程安全的也不错啊
Oversense 2003-10-14
  • 打赏
  • 举报
回复
to xkak2(c++狂热者) ( ):
你说的问题我仔细考虑过了,我觉得没什么问题啊
我暴露的接口里面根本就没有迭代器,而且对于遍历的时候也考虑了改变其中元素的啊
如果有代码把我的simp_hash_map弄出问题,我会好好改进啊
t0mychen 2003-10-14
  • 打赏
  • 举报
回复
顶一下
vcforever 2003-10-10
  • 打赏
  • 举报
回复
高手啊!
来看看!
MARK!
xkak2 2003-10-09
  • 打赏
  • 举报
回复
你的容器成员函数可以被自己封装的锁锁起来,但是迭代子却不受你的容器成员函数影响。所以,你的方法还是有问题的。
而且,多线程的程序出错根本没有重现性。你在一台电脑上运行正常(单cpu),在另外一台电脑上(多cpu)就可能频频死机。
xkak2 2003-10-09
  • 打赏
  • 举报
回复
我曾经用类似的方法封装过vector,让新的vector的每个函数都只能单线程访问。但是在多线程应用中还是有出错的可能。
考虑如下代码:
for (p = v.begin(); p != v.end(); ++p)
{
......
}
如果有另外一个线程改变了v,那么++p就有可能出现错误。
所以,合适的做法是:在访问一个容器时,整个用线程锁锁住该容器。
类似如下的java代码:
synchronized(v) {
.....
}
sevencat 2003-10-09
  • 打赏
  • 举报
回复
for (p = v.begin(); p != v.end(); ++p)
{
......
}
这种做法在其他的容器类很常见,但在HASH中最好少用,你用之前最好先看一下原代码,因为SGI的迭代器里面没有保存“桶”的数值,因此每次执行++操作的时候,假如到了LIST的最后的话就会先算自己的HASH值然后再+1,然后再到下一个列表。这是最没有效率的东西。
sevencat 2003-10-09
  • 打赏
  • 举报
回复
我觉得在这种基础类上封装线程安全可能不是很划算,

还是具体类具体用的地方再封装也不迟。
leyt 2003-10-09
  • 打赏
  • 举报
回复
仔细研究一下
sevencat 2003-09-26
  • 打赏
  • 举报
回复
我的HASH类是用的SGI的跟VC的其他类相搭配的,感觉还可以,我直接用HASHTABLE,自己加些接口,问题也不是很大。呵呵,HASH真是好东西。
Oversense 2003-09-26
  • 打赏
  • 举报
回复
to sevencat(七猫):
谢谢~~
我也想过从底层开始封装,但是太繁复了
我这个hash_map只能单独用了,因为简单一点,所以叫simp_hash_map
但是hash_map的几乎所有常用功能,都可以用了,我的很多程序里面都在用这个东西,呵呵
sevencat 2003-09-25
  • 打赏
  • 举报
回复
因为有很多功能是在HASHTABLE中完成的,像什么查找啦之类的东西。
都是在HASHTABLE上面的。
HASHMAP只是对HASHTABLE的一个封装,
VC用的是traits,而sgi用的模板直接传入的。
sevencat 2003-09-25
  • 打赏
  • 举报
回复
晕,就是用的VC7.1自带的HASHMAP进行封装的吧(STDEXT),老兄。难怪怎么行数这么少。
Critical Section
在LInux下面则是mute_x
我也封装过的,同时在WIN和LINXU下面的,

不过我觉得这样还不是很够的。因为你这样的话跟STD的其他函数不能一起用,只能是一个普通的HASHMAP而已了。

我觉得可以直接从HASH——TABLE开始做线程安全的HASHMAP类。
fancyhsq 2003-09-25
  • 打赏
  • 举报
回复
菜鸟一定好好学习
go_my_sky 2003-09-22
  • 打赏
  • 举报
回复
不错不错
加载更多回复(17)

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧