From 5fb1043ec7e05c196a6a7f5caa9c8491e3ee4e66 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 8 Nov 2023 20:25:49 +0800 Subject: [PATCH] Unfair lock --- Package.swift | 8 +-- Sources/Database/DatabaseImports.swift | 3 ++ Sources/Database/DiskSqlite.swift | 58 ++++++++++----------- Sources/WalletConnectUtils/UnfairLock.swift | 21 ++++++++ 4 files changed, 52 insertions(+), 38 deletions(-) create mode 100644 Sources/Database/DatabaseImports.swift create mode 100644 Sources/WalletConnectUtils/UnfairLock.swift diff --git a/Package.swift b/Package.swift index 0f7ce4e77..93c74e302 100644 --- a/Package.swift +++ b/Package.swift @@ -37,15 +37,9 @@ let package = Package( .library( name: "WalletConnectNetworking", targets: ["WalletConnectNetworking"]), - .library( - name: "WalletConnectSync", - targets: ["WalletConnectSync"]), .library( name: "WalletConnectVerify", targets: ["WalletConnectVerify"]), - .library( - name: "WalletConnectHistory", - targets: ["WalletConnectHistory"]), .library( name: "WalletConnectModal", targets: ["WalletConnectModal"]), @@ -132,7 +126,7 @@ let package = Package( dependencies: ["WalletConnectUtils", "WalletConnectNetworking"]), .target( name: "Database", - dependencies: []), + dependencies: ["WalletConnectUtils"]), .target( name: "WalletConnectModal", dependencies: ["QRCode", "WalletConnectSign"], diff --git a/Sources/Database/DatabaseImports.swift b/Sources/Database/DatabaseImports.swift new file mode 100644 index 000000000..39a0c89b7 --- /dev/null +++ b/Sources/Database/DatabaseImports.swift @@ -0,0 +1,3 @@ +#if !CocoaPods +@_exported import WalletConnectUtils +#endif diff --git a/Sources/Database/DiskSqlite.swift b/Sources/Database/DiskSqlite.swift index 1c13cb827..8d7b77c49 100644 --- a/Sources/Database/DiskSqlite.swift +++ b/Sources/Database/DiskSqlite.swift @@ -7,54 +7,50 @@ public final class DiskSqlite: Sqlite { private var db: OpaquePointer? - private let lock = NSLock() + private let lock = UnfairLock() public init(path: String) { self.path = path } public func openDatabase() throws { - defer { lock.unlock() } - lock.lock() - - guard sqlite3_open_v2(path, &db, SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_FULLMUTEX, nil) == SQLITE_OK else { - throw SQLiteError.openDatabase(path: path) + try lock.locked { + guard sqlite3_open_v2(path, &db, SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_FULLMUTEX, nil) == SQLITE_OK else { + throw SQLiteError.openDatabase(path: path) + } } } public func query(sql: String) throws -> [Row] { - defer { lock.unlock() } - lock.lock() - - var queryStatement: OpaquePointer? - guard sqlite3_prepare_v2(db, sql, -1, &queryStatement, nil) == SQLITE_OK else { - throw SQLiteError.queryPrepare(statement: sql) - } - var rows: [Row] = [] - while sqlite3_step(queryStatement) == SQLITE_ROW { - let decoder = SqliteRowDecoder(statement: queryStatement) - guard let row = try? Row(decoder: decoder) else { continue } - rows.append(row) + return try lock.locked { + var queryStatement: OpaquePointer? + guard sqlite3_prepare_v2(db, sql, -1, &queryStatement, nil) == SQLITE_OK else { + throw SQLiteError.queryPrepare(statement: sql) + } + var rows: [Row] = [] + while sqlite3_step(queryStatement) == SQLITE_ROW { + let decoder = SqliteRowDecoder(statement: queryStatement) + guard let row = try? Row(decoder: decoder) else { continue } + rows.append(row) + } + sqlite3_finalize(queryStatement) + return rows } - sqlite3_finalize(queryStatement) - return rows } public func execute(sql: String) throws { - defer { lock.unlock() } - lock.lock() - - var error: UnsafeMutablePointer? - guard sqlite3_exec(db, sql, nil, nil, &error) == SQLITE_OK else { - let message = error.map { String(cString: $0) } - throw SQLiteError.exec(error: message) + try lock.locked { + var error: UnsafeMutablePointer? + guard sqlite3_exec(db, sql, nil, nil, &error) == SQLITE_OK else { + let message = error.map { String(cString: $0) } + throw SQLiteError.exec(error: message) + } } } public func closeConnection() { - defer { lock.unlock() } - lock.lock() - - sqlite3_close(db) + lock.locked { + sqlite3_close(db) + } } } diff --git a/Sources/WalletConnectUtils/UnfairLock.swift b/Sources/WalletConnectUtils/UnfairLock.swift new file mode 100644 index 000000000..3e22d97d9 --- /dev/null +++ b/Sources/WalletConnectUtils/UnfairLock.swift @@ -0,0 +1,21 @@ +import Foundation + +public final class UnfairLock { + private var lock: UnsafeMutablePointer + + public init() { + lock = UnsafeMutablePointer.allocate(capacity: 1) + lock.initialize(to: os_unfair_lock()) + } + + deinit { + lock.deallocate() + } + + @discardableResult + public func locked(_ f: () throws -> ReturnValue) rethrows -> ReturnValue { + os_unfair_lock_lock(lock) + defer { os_unfair_lock_unlock(lock) } + return try f() + } +}