From da7494b5ba54120a574ef03619d56a839ad3267d Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Mon, 24 Apr 2023 07:26:25 -0300 Subject: [PATCH] Fix mt issues (#178) --- src/db/pool.cr | 6 +++-- src/db/pool_prepared_statement.cr | 37 +++++++++++++++++++++---------- src/db/string_key_cache.cr | 19 +++++++++++----- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/db/pool.cr b/src/db/pool.cr index 28ea417..f3c7a7f 100644 --- a/src/db/pool.cr +++ b/src/db/pool.cr @@ -216,8 +216,10 @@ module DB private def build_resource : T resource = @factory.call - @total << resource - @idle << resource + sync do + @total << resource + @idle << resource + end resource end diff --git a/src/db/pool_prepared_statement.cr b/src/db/pool_prepared_statement.cr index b91ee1a..cb598e2 100644 --- a/src/db/pool_prepared_statement.cr +++ b/src/db/pool_prepared_statement.cr @@ -7,6 +7,7 @@ module DB class PoolPreparedStatement < PoolStatement # connections where the statement was prepared @connections = Set(WeakRef(Connection)).new + @mutex = Mutex.new def initialize(db : Database, query : String) super @@ -20,35 +21,47 @@ module DB end protected def do_close - # TODO close all statements on all connections. - # currently statements are closed when the connection is closed. + @mutex.synchronize do + # TODO close all statements on all connections. + # currently statements are closed when the connection is closed. - # WHAT-IF the connection is busy? Should each statement be able to - # deallocate itself when the connection is free. - @connections.clear + # WHAT-IF the connection is busy? Should each statement be able to + # deallocate itself when the connection is free. + @connections.clear + end end # builds a statement over a real connection # the connection is registered in `@connections` private def build_statement : Statement clean_connections - conn, existing = @db.checkout_some(@connections) + + conn, existing = @mutex.synchronize do + @db.checkout_some(@connections) + end + begin stmt = conn.prepared.build(@query) rescue ex conn.release raise ex end - @connections << WeakRef.new(conn) unless existing + unless existing + @mutex.synchronize do + @connections << WeakRef.new(conn) + end + end stmt end private def clean_connections - # remove disposed or closed connections - @connections.each do |ref| - conn = ref.value - if !conn || conn.closed? - @connections.delete ref + @mutex.synchronize do + # remove disposed or closed connections + @connections.each do |ref| + conn = ref.value + if !conn || conn.closed? + @connections.delete ref + end end end end diff --git a/src/db/string_key_cache.cr b/src/db/string_key_cache.cr index f2cae62..ef77d67 100644 --- a/src/db/string_key_cache.cr +++ b/src/db/string_key_cache.cr @@ -1,21 +1,28 @@ module DB class StringKeyCache(T) @cache = {} of String => T + @mutex = Mutex.new def fetch(key : String) : T - value = @cache.fetch(key, nil) - value = @cache[key] = yield unless value - value + @mutex.synchronize do + value = @cache.fetch(key, nil) + value = @cache[key] = yield unless value + value + end end def each_value - @cache.each do |_, value| - yield value + @mutex.synchronize do + @cache.each do |_, value| + yield value + end end end def clear - @cache.clear + @mutex.synchronize do + @cache.clear + end end end end