找回密码
 立即注册
收起左侧

如何利用读写锁的dll库对SQLite加读锁

0
回复
10061
查看
[复制链接]
累计签到:6 天
连续签到:1 天
来源: 2018-5-2 10:50:29 显示全部楼层 |阅读模式
5Qter豆
本帖最后由 星星星 于 2018-5-2 11:33 编辑

参考 https://blog.csdn.net/chexlong/article/details/7110060 这篇博客

我找到了一个多线程读写锁的头文件以及对应的dll,已经在项目中可以加载dll并且执行里面的方法。

但是不知道怎么在访问SQLite数据库时加上读锁,我的项目要和其他程序共同访问一个数据库,因此要加锁。

目前的思路是:用一个专门的类来处理SQLite连接和关闭,但是我编程的无法编译通过。

请求大家能否教我一下怎么用dll里面的方法来给数据库加读锁,或者看看我写的程序问题出在哪里。。谢谢!!

头文件RWLockImpl.h 内容如下所示,是现成的不需要更改。DLL见附件:

  1. #ifdef LOCKDLL_EXPORTS
  2. #define LOCKDLL_API __declspec(dllexport)
  3. #else
  4. #define LOCKDLL_API __declspec(dllimport)
  5. #endif



  6. #ifndef _RWLockImpl_Header
  7. #define _RWLockImpl_Header

  8. #include <assert.h>
  9. #include <iostream>
  10. using namespace std;

  11. #include <Windows.h>
  12. #include <process.h>


  13. /*
  14. 读写锁允许当前的多个读用户访问保护资源,但只允许一个写读者访问保护资源
  15. */

  16. //#define LOCKNAME_MAX_LEN 32
  17. #define SQLITE_LOCK_NAME "vis_socket_lock"

  18. //-----------------------------------------------------------------
  19. class CRWLockImpl
  20. {
  21. protected:
  22.         CRWLockImpl(); //无名锁,适用于某进程内部
  23.         CRWLockImpl(const char* lock_name);
  24.         ~CRWLockImpl();
  25.         void ReadLockImpl();
  26.         bool TryReadLockImpl();
  27.         void UnReadlockImpl();        

  28.         void WriteLockImpl();
  29.         bool TryWriteLockImpl();
  30.         void UnWritelockImpl();        

  31.         void UnlockImpl();        

  32. private:
  33.         void AddWriter();
  34.         void RemoveWriter();
  35.         DWORD TryReadLockOnce();

  36.         HANDLE   m_mutex; //互斥锁,保护信号量或事件
  37.         HANDLE   m_readSemaphore; //读信号量,用于标记读锁数量
  38.         HANDLE   m_readEvent;        //读事件,用于标记是否有进程正在读取
  39.         HANDLE   m_writeWaitSemaphore; //写等待信号量,用于标记写等待数量
  40.         HANDLE   m_writeWaitEvent; //写等待事件,用于标记是否有进程正在写等待
  41.         HANDLE         m_writeMutex; //写互斥锁,用于写保护
  42. };

  43. //-----------------------------------------------------------------

  44. class rwLock: private CRWLockImpl
  45. {
  46. public:

  47.         //创建读/写锁
  48.         LOCKDLL_API rwLock(){};
  49.         LOCKDLL_API rwLock(const char* lock_name);

  50.         //销毁读/写锁
  51.         LOCKDLL_API ~rwLock(){};

  52.         //获取读锁
  53.         //如果其它一个线程占有写锁,则当前线程必须等待写锁被释放,才能对保护资源进行访问
  54.         void LOCKDLL_API ReadLock();

  55.         //尝试获取一个读锁
  56.         //如果获取成功,则立即返回true,否则当另一个线程占有写锁,则返回false
  57.         //bool LOCKDLL_API TryReadLock();

  58.         //获取写锁
  59.         //如果一个或更多线程占有读锁,则必须等待所有锁被释放
  60.         //如果相同的一个线程已经占有一个读锁或写锁,则返回结果不确定
  61.         void LOCKDLL_API WriteLock();

  62.         //尝试获取一个写锁
  63.         //如果获取成功,则立即返回true,否则当一个或更多其它线程占有读锁,返回false
  64.         //如果相同的一个线程已经占有一个读锁或写锁,则返回结果不确定
  65.         //bool LOCKDLL_API TryWriteLock();


  66.         //释放一个读锁
  67.         void LOCKDLL_API UnReadlock();

  68.         //释放一个写锁
  69.         void LOCKDLL_API UnWritelock();

  70. private:
  71.         LOCKDLL_API rwLock(const rwLock&);
  72.         LOCKDLL_API rwLock& operator = (const rwLock&);
  73. };

  74. inline void rwLock::ReadLock()
  75. {
  76.         ReadLockImpl();
  77. }

  78. /*
  79. inline bool rwLock::TryReadLock()
  80. {
  81.         return TryReadLockImpl();
  82. }*/

  83. inline void rwLock::WriteLock()
  84. {
  85.         WriteLockImpl();
  86. }

  87. /*
  88. inline bool rwLock::TryWriteLock()
  89. {
  90.         return TryWriteLockImpl();
  91. }*/

  92. inline void rwLock::UnReadlock()
  93. {
  94.         UnReadlockImpl();
  95. }

  96. inline void rwLock::UnWritelock()
  97. {
  98.         UnWritelockImpl();
  99. }


  100. extern "C"
  101. {
  102. void LOCKDLL_API sql_read_lock(void);
  103. void LOCKDLL_API sql_read_unlock(void);
  104. void LOCKDLL_API sql_write_lock(void);
  105. void LOCKDLL_API sql_write_unlock(void);


  106. int LOCKDLL_API test_int(void);
  107. };



  108. #endif
复制代码


我写的Util如下:
  1. #ifndef DBUTIL_H
  2. #define DBUTIL_H

  3. #include "RWLockImpl.h"
  4. #include <QtSql>
  5. #include <QLibrary>
  6. #include <QMessageBox>
  7. #include <QDebug>

  8. class DBUtil
  9. {
  10. public:
  11.     DBUtil();
  12.     static QSqlDatabase openConnection();                 // 获取数据库连接
  13.     static void closeConnection(QSqlDatabase connection); // 释放数据库连接回连接池

  14.     static QLibrary *mylib;

  15. private:
  16.     static QSqlDatabase myDB;
  17.     static QString dbName;
  18. };

  19. #endif // DBUTIL_H
复制代码



  1. #include "dbutil.h"

  2. //函数指针: 获取读锁
  3. typedef void (*p_sql_read_lock)(void);
  4. //函数指针: 释放读锁
  5. typedef void (*p_sql_read_unlock)(void);

  6. DBUtil::DBUtil()
  7. {
  8.     dbName = "vis_information.db";          //初始化数据库名称
  9.     mylib = new QLibrary("lockDll.dll");    //声明所用到的dll文件
  10.     if (mylib->load())                      //判断是否正确加载
  11.     {
  12.         qDebug()<<"SQLite LockDLL load is OK!";
  13.     }
  14.     else
  15.         QMessageBox::information(NULL,"ERROR","数据库读写DLL加载失败!");
  16. }


  17. //获取数据库连接
  18. QSqlDatabase DBUtil::openConnection() {

  19.     //援引 ReadLock() 函数
  20.     p_sql_read_lock readLock=(p_sql_read_lock)mylib->resolve("ReadLock");
  21.     if (readLock)                   //是否成功连接上 ReadLock() 函数
  22.     {
  23.         qDebug()<<"read lock";
  24.         readLock();                 //这里函数指针调用dll中的 ReadLock() 函数


  25.         if(QSqlDatabase::contains("qt_sql_default_connection"))
  26.             myDB = QSqlDatabase::database("qt_sql_default_connection");
  27.         else
  28.         {
  29.             myDB = QSqlDatabase::addDatabase("QSQLITE");
  30.             myDB.setDatabaseName("./data/"+dbName);
  31.         }

  32.         if(myDB.open())
  33.             return myDB;
  34.     }

  35.     QMessageBox::information(0, "错误信息", "无法打开数据库"+dbName);
  36.     return QSqlDatabase();
  37. }

  38. void DBUtil::closeConnection(QSqlDatabase connection) {

  39.     //援引 ReadLock() 函数
  40.     p_sql_read_unlock unreadLock=(p_sql_read_unlock)mylib->resolve("UnReadlock");
  41.     if (unreadLock)                  //是否成功连接上 UnReadLock() 函数
  42.     {
  43.         qDebug()<<"unread lock";
  44.         unreadLock();               //这里函数指针调用dll中的 UnReadLock() 函数

  45.         connection.close();
  46.     }
  47.     else
  48.     {
  49.         QMessageBox::information(NULL,"ERROR","UnReadlock释放读锁失败!");

  50.     }

  51. }
复制代码



主函数如下:
  1. #pragma execution_character_set("utf-8")

  2. #include <QApplication>

  3. #include "mainwindow.h"
  4. #include "dbutil.h"

  5. int main(int argc, char **argv)
  6. {
  7.     QApplication app(argc, argv);

  8.     DBUtil util = DBUtil();

  9.     QSqlDatabase db = DBUtil::openConnection();

  10.     QSqlQuery sql_query;
  11.     QString sql = "select count(*) from test_table";
  12.     sql_query.prepare(sql);

  13.     if(!sql_query.exec(sql))
  14.     {
  15.         QMessageBox::information(0, "数据库错误信息", sql+ " 语句执行出错\n" + sql_query.lastError().text());
  16.     }
  17.     else
  18.     {
  19.         if(sql_query.first())
  20.             qDebug()<<sql_query.value(0).toString();
  21.     }

  22.     DBUtil::closeConnection(db);

  23.     return app.exec();
  24. }
复制代码


程序报错如下:


附件: 您需要 登录 才可以下载或查看,没有帐号?立即注册
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了