Skip to content

Commit

Permalink
Unfair lock
Browse files Browse the repository at this point in the history
  • Loading branch information
flypaper0 committed Nov 8, 2023
1 parent 92a6de8 commit 5fb1043
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 38 deletions.
8 changes: 1 addition & 7 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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"]),
Expand Down Expand Up @@ -132,7 +126,7 @@ let package = Package(
dependencies: ["WalletConnectUtils", "WalletConnectNetworking"]),
.target(
name: "Database",
dependencies: []),
dependencies: ["WalletConnectUtils"]),
.target(
name: "WalletConnectModal",
dependencies: ["QRCode", "WalletConnectSign"],
Expand Down
3 changes: 3 additions & 0 deletions Sources/Database/DatabaseImports.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#if !CocoaPods
@_exported import WalletConnectUtils
#endif
58 changes: 27 additions & 31 deletions Sources/Database/DiskSqlite.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<Row: SqliteRow>(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<CChar>?
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<CChar>?
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)
}
}
}
21 changes: 21 additions & 0 deletions Sources/WalletConnectUtils/UnfairLock.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Foundation

public final class UnfairLock {
private var lock: UnsafeMutablePointer<os_unfair_lock>

public init() {
lock = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
lock.initialize(to: os_unfair_lock())
}

deinit {
lock.deallocate()
}

@discardableResult
public func locked<ReturnValue>(_ f: () throws -> ReturnValue) rethrows -> ReturnValue {
os_unfair_lock_lock(lock)
defer { os_unfair_lock_unlock(lock) }
return try f()
}
}

0 comments on commit 5fb1043

Please sign in to comment.