CLucene源码剖析(三) 实现跨平台的线程安全

首页 > CLucene, 程序人生 > CLucene源码剖析(三) 实现跨平台的线程安全
CLucene源码剖析(三) 实现跨平台的线程安全
2009年5月29日 小武哥 发表评论 阅读评论
在多线程编程中,程序的线程安全(thread-safe)是十分重要的,要做到这一点,一方面要在程序设计的过程中,尽可能设计多的单线程访问的数据结构,一方面就是合理的使用锁(Mutex)。在CLucene中,实现了如下跨平台的锁相关的宏:
(1) _LUCENE_SLEEP(x) 挂起当前线程 x微秒
(2) _LUCENE_THREADMUTEX 线程锁(mutex)
(3) _LUCENE_CURRTHREADID 获取当前线程的thread ID
(4) _LUCENE_THREADID_TYPE thread ID的类型定义
通过上面几个宏,就可以实现基本的线程安全的相关操作。下面对上述宏的具体实现进行一一详细说明:
1.在windows平台下:
(1) _LUCENE_SLEEP(x)由系统API Sleep()实现

1
#define _LUCENE_SLEEP(x) Sleep(x)

(2) _LUCENE_THREADMUTEX由CRITICAL_SECTION相关的内容实现

1
#define _LUCENE_THREADMUTEX CL_NS(util)::mutex_win32

(3) _LUCENE_CURRTHREADID由系统API GetCurrentThreadId()实现

1
#define _LUCEN colla="E_CURRTHREADID GetCurrentThreadId()

(4) _LUCENE_THREADID_TYPE类型为 DWORD类型

1
#define _LUCENE_THREADID_TYPE DWORD

2.在unix平台下:
(1) _LUCENE_SLEEP(x)由系统函数 usleep()实现

1
#define _LUCENE_SLEEP(x) usleep(x*1000)

(2) _LUCENE_THREADMUTEX由pthread_mutex_t相关的内容实现

1
#define _LUCENE_THREADMUTEX CL_NS(util)::mutex_pthread

(3) _LUCENE_CURRTHREADID由pthread中的pthread_self()的实现

1
#define _LUCENE_CURRTHREADID pthread_self()

(4) _LUCENE_THREADID_TYPE类型为pthread_t类型

1
#define _LUCENE_THREADID_TYPE pthread_t

从上面的讲解过程中,我们可以看出_LUCENE_THREADMUTEX的实现,还是有一层包装的,在windows下是mutex_win32,在unix下是mutex_pthread,所以要想深入理解,还需要更加深入一步。
下面是mutex_win32的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class mutex_win32
{
private:
CRITICAL_SECTION mtx;
public:
mutex_win32(const mutex_win32& clone);
mutex_win32();
~mutex_win32();
void lock();
void unlock();
};
mutex_win32::mutex_win32(const mutex_win32& clone){
InitializeCriticalSection(&mtx);
}
mutex_win32::mutex_win32()
{
InitializeCriticalSection(&mtx);
}

mutex_win32::~mutex_win32()
{
DeleteCriticalSection(&mtx);
}

void mutex_win32::lock()
{
EnterCriticalSection(&mtx);
}

void mutex_win32::unlock()
{
LeaveCriticalSection(&mtx);
}

下面是mutex_pthread的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
class mutex_pthread
{
private:
pthread_mutex_t mtx;

public:
mutex_pthread(const mutex_pthread& clone);
mutex_pthread();
~mutex_pthread();
void lock();
void unlock();

private:
#ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
pthread_t lockOwner;
unsigned int lockCount;
#endif
};
#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
bool mutex_pthread_attr_initd=false;
pthread_mutexattr_t mutex_pthread_attr;
#endif

#ifdef _CL__CND_DEBUG
#define _CLPTHREAD_CHECK(c,m) CND_PRECONDITION(c==0,m)
#else
#define _CLPTHREAD_CHECK(c,m) c;
#endif

mutex_pthread::mutex_pthread(const mutex_pthread& clone){
#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, &mutex_pthread_attr), "mutex_pthread(clone) constructor failed")
#else
#if defined(__hpux) && defined(_DECTHREADS_)
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, pthread_mutexattr_default), "mutex_pthread(clone) constructor failed")
#else
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, 0), "mutex_pthread(clone) constructor failed")
#endif
lockCount=0;
lockOwner=0;
#endif
}
mutex_pthread::mutex_pthread()
{
#ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
if ( mutex_pthread_attr_initd == false ){
pthread_mutexattr_init(&mutex_pthread_attr);
pthread_mutexattr_settype(&mutex_pthread_attr, PTHREAD_MUTEX_RECURSIVE);
mutex_pthread_attr_initd = true;
}
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, &mutex_pthread_attr), "mutex_pthread(clone) constructor failed")
#else
#if defined(__hpux) && defined(_DECTHREADS_)
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, pthread_mutexattr_default), "mutex_pthread(clone) constructor failed")
#else
_CLPTHREAD_CHECK(pthread_mutex_init(&mtx, 0), "mutex_pthread(clone) constructor failed")
#endif
lockCount=0;
lockOwner=0;
#endif
}

mutex_pthread::~mutex_pthread()
{
_CLPTHREAD_CHECK(pthread_mutex_destroy(&mtx), "~mutex_pthread destructor failed")
}

void mutex_pthread::lock()
{
#ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
pthread_t currentThread = pthread_self();
if( pthread_equal( lockOwner, currentThread ) ) {
++lockCount;
} else {
_CLPTHREAD_CHECK(pthread_mutex_lock(&mtx), "mutex_pthread::lock")
lockOwner = currentThread;
lockCount = 1;
}
#else
_CLPTHREAD_CHECK(pthread_mutex_lock(&mtx), "mutex_pthread::lock")
#endif
}

void mutex_pthread::unlock()
{
#ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE
--lockCount;
if( lockCount == 0 )
{
lockOwner = 0;
_CLPTHREAD_CHECK(pthread_mutex_unlock(&mtx), "mutex_pthread::unlock")
}
#else
_CLPTHREAD_CHECK(pthread_mutex_unlock(&mtx), "mutex_pthread::unlock")
#endif
}


由上面的实现可以看出,mutex_win32直接就是对CRITICAL_SECTION相关的操作进行了封装,而mutex_pthread是对pthread_mutex_t相关操作的封装。其实在这里,我不知道作者为什么要采用这种宏的方式,我觉得完全可以能过封装一个通用的Thread类和Mutex类,这样用起来更为方便,而且要做扩展也比较容易。
[url]http://www.wuzesheng.com/?p=120[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大名鼎鼎的clucene,是lucene的c++ 版; CLucene README ============== ------------------------------------------------------ CLucene is a C++ port of Lucene. It is a high-performance, full-featured text search engine written in C++. CLucene is faster than lucene as it is written in C++. ------------------------------------------------------ CLucene has contributions from many, see AUTHORS CLucene is distributed under the GNU Lesser General Public License (LGPL) *or* the Apache License, Version 2.0 See the LGPL.license and APACHE.license for the respective license information. Read COPYING for more about the license. Installation ------------ * For Linux, MacOSX, cygwin and MinGW build information, read INSTALL. * Boost.Jam files are provided in the root directory and subdirectories. * Microsoft Visual Studio (6&7) are provided in the win32 folder. Mailing List ------------ Questions and discussion should be directed to the CLucene mailing list at clucene-developers@lists.sourceforge.net Find subscription instructions at http://lists.sourceforge.net/lists/listinfo/clucene-developers Suggestions and bug reports can be made on our bug tracking database (http://sourceforge.net/tracker/?group_id=80013&atid=558446) The latest version ------------------ Details of the latest version can be found on the CLucene sourceforge project web site: http://www.sourceforge.net/projects/clucene Documentation ------------- Documentation is provided at http://clucene.sourceforge.net/doc/doxygen/html/ You can also build your own documentation by running doxygen from the root directory of clucene. CLucene is a very close port of Java Lucene, so you can also try looking at the Java Docs on http://lucene.apache.org/java/ Performance ----------- Very little benchmarking has been done on clucene. Andi Vajda posted some limited statistics on the clucene list a while ago with the following results. There are 250 HTML files under $JAVA_HOME/docs/api/java/util for about 6108kb of HTML
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值