c++的对象计数问题的多线程实现

几个概念:


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)





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值