基于C++写一个mysql连接池

3 篇文章 0 订阅

思想:封装mysql基本操作API,以stl中的list容器包装连接对象,采用单例模式创建连接池类对象,采取RAII机制进行实现。其中,涉及到对连接队列的操作的,全部都加上互斥锁,保证原子操作。

具体的,Pool类成员变量包括:

主机名或IP地址m_url,如果NULL或"localhost",连接将被视为与本地主机的连接。
数据库名称m_dbName、
登录用户名m_dbUser、
用户密码m_dbPswd、
连接端口m_port,
当前连接数m_curconn、
空闲连接数m_freeconn以及一个封装了互斥量的locker类对象Lock,封装了信号量的sem类对象rest。

主要接口有:

初始化接口init,
获取空闲连接数接口getFreeconn,
释放一个连接接口releaseConn,
销毁连接池接口Destroy以及
单例模式获取唯一实例接口getInstance。

最后,RAIIPool类实现RAII机制,在构造函数中获取唯一实例,析构函数销毁连接池。

代码如下

#pragma once

class Pool{
public:
    ~Pool();
    int getFreeconn();
    bool init(string url, string dbName, string dbPswd, string User, int port);
    void Destroy();  //销毁连接池
    void releaseConn(MYSQL* conn);   //释放一个连接
    MYSQL* GetConn();     //获取一个空闲连接
    Pool* getInstance();  //单例连接
    
private:
    Pool();
    list<MYSQL*> pool_;
    string m_dbName;
    string m_dbPswd;
    string m_dbUser;
    string m_port;
    string m_url;

    constexpr static int maxconn = 10; //最大连接
    int m_curconn;
    int m_freeconn;    //空闲连接
    
    locker Lock;     //原子操作
    sem rest;   //信号量类检测剩余空闲连接数
};


//真正实现RAII - 创建对象即获得一个连接, 析构函数则释放资源
class RAIIPool{
public:
    RAIIPool(MYSQL** conn, Pool* pool_);
    ~RAIIPool();
private:
    MYSQL* RAIIconn;
    Pool* RAIIpool;
};

具体实现:

Pool::Pool(){
    this->m_freeconn = 0;
    this->m_curconn = 0;
}

Pool::~Pool(){
    Destroy();
}

int Pool::getFreeconn(){
    return m_freeconn;
}

bool Pool::init(string url, string dbName, string dbPswd, string dbUser, int port){
    m_url = url;
    m_dbName = dbName;
    m_port = port;
    m_dbPswd = dbPswd;
    m_dbUser = dbUser;
    for(int i = 0; i < maxconn; ++i){
        MYSQL* conn = NULL;
        conn = mysql_init(conn);
        if(conn == NULL){
            perror("mysql_init");
            exit(1);
        }
        conn = mysql_real_connect(conn, url.c_str(), dbUser.c_str(), dbPswd.c_str(), dbName.c_str(), port, NULL, 0);
        if(conn == NULL){
            perror("mysql_real_connect");
            exit(1);
        }          
        pool_.push_back(conn);
        ++m_freeconn;
    }
    rest = sem(m_freeconn);
    return true;
}

void Pool::Destroy(){
    Lock.lock();
    for(auto it = pool_.begin(); it != pool_.end(); ++it){
        MYSQL* item = *it;
        mysql_close(item);
    }
    m_curconn = 0;
    m_freeconn = 0;
    pool_.clear();  //清空list
    list<MYSQL*>().swap(pool_); //释放资源
    Lock.unlock();
}

MYSQL* Pool::GetConn(){
    if(pool_.size() == 0){
        return nullptr;
    }
    Lock.lock();

    rest.wait();  //信号量-1
    MYSQL* conn = pool_.front(); //取出一个连接
    pool_.pop_front();
    --m_freeconn;
    ++m_curconn;
    
    Lock.unlock();
    return conn;
}

void Pool::releaseConn(MYSQL* conn){
    if(conn == NULL){
        return;
    }
    Lock.lock();

    pool_.push_back(conn); //放进空闲链接队列
    ++m_freeconn;
    --m_curconn;
    rest.post();  //信号量+1
    
    Lock.unlock();
}

Pool* Pool::getInstance(){
    static Pool conn;  //全类共享
    return &conn;
}


RAIIPool::RAIIPool(MYSQL** conn ,Pool* pool_){
    *conn = pool_->GetConn();

    RAIIconn = *conn;
    RAIIpool = pool_;
}

RAIIPool::~RAIIPool(){
    RAIIpool->Destroy();
}

locker类实现:

class locker
{
public:
    locker(){
        if(pthread_mutex_init(&mtx, nullptr) != 0){
            throw std::exception();
        }
    }
    ~locker(){
        pthread_mutex_destroy(&mtx);
    }
    bool lock(){
        return pthread_mutex_lock(&mtx) == 0;
    }
    bool unlock(){
        return pthread_mutex_unlock(&mtx) == 0;
    }
    pthread_mutex_t* GetMtx(){ //获取一把锁
        return &mtx;
    }
private:
    pthread_mutex_t mtx;
};

class sem
{
public:
    sem(int num){
        if(sem_init(&id, 0, num) != 0){  //线程共享
            throw std::exception();  
        }
    }
    sem(){
        if(sem_init(&id, 0, 0) != 0){
            throw std::exception();
        }
    }
    ~sem(){
        sem_destroy(&id);
    }
    bool wait(){
        return sem_wait(&id) == 0;
    }
    bool post(){
        return sem_post(&id) == 0;
    }
private:
    sem_t id;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值