1

我在我的应用程序中使用了两个 mysql 对象。在退出线程之前,我只需要调用mysql_thread_end一次。是否有任何函数/回调以便它在退出线程之前调用?

附上示例程序

using namespace std;
class MySql
{
public:
    MySql()
    {
        mysql = mysql_init(NULL);
    }
    ~MySql()
    {
        if(mysql)
        {
            mysql_close(mysql);
        }
    // Wrong: this will clear thread specific values twice. it may lead to crash the application.   
       // mysql_thread_end();
    }
    int Connect(const char *host,
                       const char *user,
                       const char *passwd,
                       const char *db,
                       unsigned int port,
                       const char *unix_socket,
                       unsigned long clientflag)
    {
        if(!mysql_real_connect(mysql, host,user, 
                            passwd, db, port, unix_socket, clientflag))
        {  
        return 1;
        }
        return 0;
    }
    int Execute(const char *query)
    {     
        int status = mysql_query(mysql, query);
        return status;
    }
private:
    MYSQL * mysql;
};

void createthreads();
static void StartThread(void * Arg);

int main(int argc, _TCHAR* argv[])
{
    int i = mysql_library_init(0, NULL, NULL);
    createthreads();    
    mysql_library_end();
    return 0;
}

void createthreads()
{  
    PRThread *thread;

    thread = PR_CreateThread(PR_USER_THREAD, StartThread, (void *)NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
    //Sleep(2000);
    PR_JoinThread(thread);   
}

void StartThread(void * Arg)
{
    MySql mysqlsrc;
    MySql mysqldest;

    //Production server
    if(!mysqlsrc.Connect("localhost","root", "root", NULL, 3306, NULL, 0))
    {
        cout<<"Connection to Src Failed";
        return;
    }

    //Test Server
    if(!mysqldest.Connect("localhost","root", "root", NULL, 3306, NULL, 0))
    {
        cout<<"Connection to Destn Failed";
        return;
    }

    /// Sync databases.     
}
4

2 回答 2

0

由于mysql_thread_end()应在关闭连接后调用OP 状态,并且文档状态应在线程结束之前调用它,因此我建议修改StartThread(线程函数)如下:

void StartThread(void * Arg)
{
  {
    MySql mysqlsrc;
    MySql mysqldest;

    //Production server
    if(!mysqlsrc.Connect("localhost","root", "root", NULL, 3306, NULL, 0))
    {
        cout<<"Connection to Src Failed";
        return;
    }

    //Test Server
    if(!mysqldest.Connect("localhost","root", "root", NULL, 3306, NULL, 0))
    {
        cout<<"Connection to Destn Failed";
        return;
    }

    /// Sync databases.   
  } /* MySql objects run out of scope, their d`tor will be called, so mysql_close() is called also. */

  mysql_thread_end();
}
于 2013-05-23T06:15:54.673 回答
0

用于线程特定数据的标准 pthread 工具允许注册特定于线程的数据析构函数,因此可用于实现一种“pthread 退出钩子”

那么,该钩子可以调用mysql_thread_end(),而您的其余代码不需要知道这一点:

using namespace std;

// --> XXX WARNING UNTESTED AND ERROR CHECKING OMITTED XXX <----

namespace {
    pthread_key_t    key;
    pthread_key_once key_once = PTHREAD_ONCE_INIT;

    void cleanup(void *dummy)  // called at thread termination
    {
        mysql_thread_end();
    }
    void key_init()            // called pthread_once and only once
    {
        (void)pthread_key_create(&key, mycleanup);
    }
    void workaround_bz66740()  // call after you know mysql_thread_init has been called
    {
        (void)pthread_once(&key_once, key_init);
        (void)pthread_setspecific(key, (const void *)1);
    }
}

class MySql
{
public:
    MySql()
    {
        mysql = mysql_init(NULL);
        workaround_bz66740();
    }
    ....

旁注:您需要显式清理 MySQL 资源这一事实既繁重又令人遗憾,正如MySQL 更改请求 #66740中所阐明的那样。

于 2013-05-23T13:24:40.807 回答