#pragma once
#ifndef CCONNECT_POOL_H_2021
#define CCONNECT_POOL_H_2021

#include <stdio.h>
#include <stdlib.h>
#include <queue>
#include <set>
#include <pthread.h>
#include <unistd.h>
#include "mysql/mysql.h"

class CConnectPool
{
public:
    struct Connect_Info
    {
        int MinConnectCount;
        int MaxConnectCount;
        const char *Host;
        int Port;
        const char *Account;
        const char *Passwd;
        const char* KName;
    };

    Connect_Info My_Info;

public:
    /**
     * @brief 创建连接池 \n
     * 在主线程中创建连接池，创建后需要调用FreePool予以释放
     * 创建失败程序会打印错误信息并终止运行
     */
    static void
    CreatePool(int MinConnectCount, int MaxConnectCount, const char *Host, int Port, const char *Account, const char *Passwd);

    /**
     * @brief 释放连接池 \n
     * 需要在主线程中调用该接口
     */
    static void FreePool();

    /**
     * @brief 获取连接 \n
     * 支持多线程，使用完成后需调用PutConnect，归还连接，本函数为阻塞函数，直到有可用连接才调用返回
     * @return 返回数据库连接
     *  --NULL表示调用失败
     */
    static MYSQL *GetConnect();

    /**
     * @brief 获取连接 \n
     * 支持多线程，使用完成后需调用PutConnect，归还连接，本函数调用后立刻返回，若没有空闲连接则返回NULL
     * @return 返回数据库连接
     *  --NULL表示调用失败
     * */
    static MYSQL *TryGetConnect();

    /**
     * @brief 向连接池归还连接 \n
     * 支持多线程
     * @param[in] pConn    需要归还的数据库连接
     * */
    static void PutConnect(MYSQL *pConn);

private:
    CConnectPool();
    ~CConnectPool();
    MYSQL *_GetConnect(bool bTry);
    void _PutConnect(MYSQL *pConn);
    // 真正创建连接
    MYSQL *_CreateConnect();

    static CConnectPool *s_pInstance;
    std::queue<MYSQL *> m_queueFree; // 空闲队列
    std::set<MYSQL *> m_setBusy;     // 繁忙队列
    pthread_mutex_t m_mutex;
    pthread_cond_t m_cond;
};

#endif

/*
使用说明
CConnectPool::CreatePool();
MYSQL *sql = CConnectPool::GetConnect();
CConnectPool::PutConnect(sql);
CConnectPool::FreePool();
*/
