几个概念:
1.锁lock-》mutex_lock或(recursive_mutex_lock)
2.锁的监视类:lock_guard
3.实体计数类counter ,-》具体的实体比如:apple,peal
4线程类thread -》具体实现buy_fruits
1。锁的代码:
mutex.h
#ifndef MUTEX_H_
#define MUTEX_H_
#include<pthread.h>
#include "no_copyable.h"
using namespace std;
namespace ccdtdg {
/*lock interface*/
class lock {
public:
virtual ~lock() {
}
/*acquire lock*/
virtual void acquire() = 0;
/*release lock*/
virtual void release() = 0;
};
/*
* mutex_lock can be used as automatic variable to lock the resource and release
* when destruction
* When the same thread tries to acquire the same lock,EDEADLK will return and the acquire behavior will fail
*/
class mutex_lock: public lock,public no_copyable {
public:
mutex_lock();
~mutex_lock();
void acquire();
void release();
private:
pthread_mutex_t mutex_;
};
/*Recursive mutex
* It allows the same thread to relock the mutex, not causing dead lock.
* Add a counter to record how many times of acquiring and releasing, which should equal to each other
* */
class recursive_mutex_lock: public lock,public no_copyable{
public:
recursive_mutex_lock();
~recursive_mutex_lock();
void acquire();
void release();
private:
pthread_mutex_t mutex_;
int count_;
};
}
#endif /* MUTEX_H_ */
nocopytable。h
/*
* no_copyable.h
*
* Created on: 2011-6-27
* Author: Jackie He
*/
#ifndef NO_COPYABLE_H_
#define NO_COPYABLE_H_
namespace ccdtdg {
/*Class derived from no_copyable is forbidden to be copied*/
class no_copyable {
protected:
no_copyable() {
}
virtual ~no_copyable() {
}
private:
//copyable operator
const no_copyable& operator=(const no_copyable&);
//copyable destruction
no_copyable(const no_copyable&);
};
}
#endif /* NO_COPYABLE_H_ */
mutex。cpp实现
#include<exception>
#include<stdio.h>
#include<stdlib.h>
#include "mutex.h"
using namespace std;
namespace ccdtdg {
mutex_lock::mutex_lock() {
#if defined(__linux) && !defined(__USE_UNIX98)
pthread_mutexattr_t attr = { PTHREAD_MUTEX_ERRORCHECK_NP };
int rc = pthread_mutex_init(&mutex_, &attr);
if (rc) {
throw exception();
}
#else
pthread_mutexattr_t attr;
int rc = pthread_mutexattr_init(&attr);
if (rc) {
throw exception();
}
rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
if (rc) {
throw exception();
}
rc = pthread_mutex_init(&mutex_, &attr);
if (rc) {
throw exception();
}
rc = pthread_mutexattr_destroy(&attr);
if(rc != 0) {
throw exception();
}
#endif
}
mutex_lock::~mutex_lock() {
int rc = pthread_mutex_destroy(&mutex_);
if (rc) {
perror( "Failed to destroy mutex: ");
}
}
void mutex_lock::acquire() {
int rc = pthread_mutex_lock(&mutex_);
if (rc) {
throw exception();
}
}
void mutex_lock::release() {
int rc = pthread_mutex_unlock(&mutex_);
if (rc) {
throw exception();
}
}
/*Recursive mutex
* It allows the same thread to relock the mutex, not causing dead lock.
* Add a counter to record how many times of acquiring and releasing, which should equal to each other
* */
recursive_mutex_lock::recursive_mutex_lock() {
#if defined(__linux) && !defined(__USE_UNIX98)
pthread_mutexattr_t attr = { PTHREAD_MUTEX_RECURSIVE_NP };
int rc = pthread_mutex_init(&mutex_, &attr);
if (rc) {
throw exception();
}
#else
pthread_mutexattr_t attr;
int rc = pthread_mutexattr_init(&attr);
if (rc) {
throw exception();
}
rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
if (rc) {
throw exception();
}
rc = pthread_mutex_init(&mutex_, &attr);
if (rc) {
throw exception();
}
rc = pthread_mutexattr_destroy(&attr);
if(rc != 0) {
throw exception();
}
#endif
count_ = 0;
//pthread_mutex_lock(&mutex_);
}
recursive_mutex_lock::~recursive_mutex_lock() {
int rc = pthread_mutex_destroy(&mutex_);
if (rc) {
perror( "Failed to destroy mutex: ");
}
//pthread_mutex_unlock();
}
void recursive_mutex_lock::acquire() {
int rc = pthread_mutex_lock(&mutex_);
if (rc) {
throw exception();
}
if (++count_ > 1) {
rc = pthread_mutex_unlock(&mutex_);
if (rc) {
throw exception();
}
}
}
void recursive_mutex_lock::release() {
if (--count_ == 0) {
int rc = pthread_mutex_unlock(&mutex_);
if (rc) {
throw exception();
}
}
}
}
2.2.锁的监视类的代码
lock_guard。h
#ifndef LOCK_GUARD_H_
#define LOCK_GUARD_H_
namespace ccdtdg {
/*lock guard
*/
template<class lock_type>
class lock_guard{
public:
lock_guard(lock_type& lock) :
_lock(lock) {
_lock.acquire();
}
~lock_guard() {
_lock.release();
}
private:
lock_type& _lock;
};
}
#endif /* LOCK_GUARD_H_ */
3.线程类的代码
thread.h
#ifndef THREAD_H_
#define THREAD_H_
#include <pthread.h>
#include "no_copyable.h"
#include "thread_exception.h"
namespace ccdtdg {
/*Thread run interface*/
class trun_interace {
public:
virtual ~trun_interace() {
}
virtual void run()=0;
};
class thread: public trun_interace,public no_copyable {
public:
thread();
~thread();
void start();
void join();
void detach();
pthread_t getId();
virtual void run() = 0;
private:
pthread_t id_;
};
}
#endif /* THREAD_H_ */
thread.cpp
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include "thread.h"
using namespace std;
namespace ccdtdg {
extern "C" {
void* runthread(void* target) {
try {
reinterpret_cast<trun_interace*> (target)->run();
} catch (exception& ex) {
perror(" Uncaught exception in runthread");
}
return 0;
}
}
thread::thread()
{
memset(&id_,0,sizeof(pthread_t));
}
thread::~thread() {
}
void thread::start() {
pthread_attr_t attr;
int rc = pthread_attr_init(&attr);
if (rc) {
throw thread_exception(rc,"thread attr init error");
}
rc = pthread_create(&id_, &attr, runthread, this);
if (rc) {
throw thread_exception(rc,"thread create error");
}
rc = pthread_attr_destroy(&attr);
if(rc) {
throw thread_exception(rc,"thread destroy attr error");
}
}
void thread::join() {
int rc = pthread_join(id_, NULL);
if (rc) {
throw thread_exception(rc,"thread join error");
}
}
void thread::detach() {
int rc = pthread_detach(id_);
if (rc) {
throw thread_exception(rc,"thread detach error");
}
}
pthread_t thread::getId() {
return id_;
}
}
4.计数类
objectCounting.cpp
#include<iostream>
#include<string.h>
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
#include"mutex.h"
#include"thread.h"
#include"lock_guard.h"
using namespace std;
namespace ccdtdg {
template<typename T>
class counter {
protected:
counter(int n = 1) {
n_ = n;
lock_guard<recursive_mutex_lock> guard(counter_lock);
cnt_ += n_;
}
counter(counter &cnter) {
lock_guard<recursive_mutex_lock> guard(counter_lock);
cnt_ += counter::n_;
}
~counter() {
lock_guard<recursive_mutex_lock> guard(counter_lock);
cnt_ -= n_;
}
static const size_t getCnt() {
return counter<T>::cnt_;
}
private:
/// thread safe
static recursive_mutex_lock counter_lock;
static size_t cnt_;
static int n_;
};
template<typename T>
size_t counter<T>::cnt_ = 0;
template<typename T>
int counter<T>::n_ = 0;
template<typename T>
recursive_mutex_lock counter<T>::counter_lock;
}
using namespace ccdtdg;
class apple: private counter<apple> {
public:
apple() :
counter<apple> (1) {
}
using counter<apple>::getCnt;
};
class pear: private counter<pear> {
public:
pear() :
counter<pear> (2) {
}
using counter<pear>::getCnt;
};
apple * array_apple[5];
pear * array_pear[8];
class buy_fruits: public ccdtdg::thread {
public:
buy_fruits() :
beg_(0), end_(0) {
}
buy_fruits(int beg, int end) :
beg_(beg), end_(end) {
}
void run() {
for (int i = beg_; i < end_; ++i) {
array_apple[i] = new apple();
array_pear[i] = new pear();
}
return;
}
private:
int beg_;
int end_;
};
int main(int argc, char * argv[]) {
/* // create two pthreads
pthread_t p_id1, p_id2;
int ret;
ret=pthread_create(&p_id1,NULL, BuyFruits,(void *)("0 2"));
if ( ret != 0 )
{
perror("pthread_create error!");
}
ret = pthread_create(&p_id2,NULL, BuyFruits,(void *)("2 3"));
if ( ret != 0 )
{
perror("pthread_create error!");
}
// wait the end of two threads
pthread_join(p_id1,NULL);
pthread_join(p_id2,NULL);*/
buy_fruits buy1(0, 2);
buy_fruits buy2(2, 3);
try{
buy1.start();
buy2.start();
buy1.join();
buy2.join();
}catch(thread_exception& ex){
cout<<"Thread run error!Error code:"<<ex.getErrorCode()<<"-reason:"<<ex.what()<<endl;
return 1;
}
//cout << "the number of apple:" << apple::getCnt()<<endl;
printf("the number of apple:%d \n",apple::getCnt());
//cout << "the number of pear:" << pear::getCnt()<<endl;
printf("the number of pear:%d \n",pear::getCnt());
///< deconstructor and free memory >
return 0;
}
5.异常类代码
hread_exception
#ifndef THREAD_EXCEPTION_H_
#define THREAD_EXCEPTION_H_
#include<exception>
#include<string>
using namespace std;
namespace ccdtdg {
class thread_exception: public exception {
public:
thread_exception() :
errCode_(0) {
}
thread_exception(int errCode, const string& errMsg) :
errCode_(errCode), errMsg_(errMsg) {
}
const char* what() const throw () {
return errMsg_.c_str();
}
int getErrorCode() const throw () {
return errCode_;
}
virtual ~thread_exception() throw () {
}
private:
int errCode_;
string errMsg_;
};
}
#endif /* THREAD_EXCEPTION_H_ */
6.makefile
CXX_Linux = g++
CXX_SunOS = CC
CXX_AIX = xlC_r
CXX_HP-UX = aCC
CXX_WIN = g++
CC_Linux = gcc
CC_SunOS = cc
CC_AIX = xlC_r
CC_HP-UX = xlC_r
CC_WIN = gcc
LIBS_Linux = -lpthread
LIBS_SunOS = -lpthread
LIBS_AIX = -lpthread
LIBS_HP-UX = -lpthread
LIBS_WIN = -lpthread
CXXFLAGS_Linux = -Wall -g
CXXFLAGS_SunOS = -g
CXXFLAGS_AIX = -g
CXXFLAGS_HP-HX = -mt -g
CXXFLAGS_WIN = -g
CXX = $(CXX_$(OS))
CC = $(CC_$(OS))
LIBS = $(LIBS_$(OS))
CXXFLAGS = $(CXXFLAGS_$(OS))
CPP_SRCS = ObjectCounting.cpp mutex.cpp thread.cpp
#OBJS = $(patsubst %.cpp,%.o,$(CPP_SRCS))
OBJS = ObjectCounting.o mutex.o thread.o
TARGET = count
.SUFFIXES: .o .cpp .h
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
all: $(TARGET)
.cpp.o:
$(CXX) $(CXXFLAGS) -c $<
.PHONY:clean
clean:
-rm $(OBJS) $(TARGET)