Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions CommonData/databaseinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2054,7 +2054,10 @@ sqlite3 * DatabaseInterface::_db()
if(_dbCreated && _dbCreator == id)
return _dbCreated;

return load();
if(!_dbs.count(id))
load();

return _dbs.at(id);
Copy link
Contributor Author

@boutinb boutinb Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RensDofferhoff and me thought also reading in a map is not really thread-safe: a map has no mutex, so if a thread add an element to the map at the same moment that count or at is called, it cannot guarantee the right value.
But as for the moment only one extra thread (the _loaderThread from MainWindow) is used, the map will have in fact only 1 value (the other connection is set in _dbCreated. So that's ok for now...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which is why I put mutexes in the load and creation function...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And there are waaaaay more threads being used so im not sure why you think there is only one?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

class InitColumnTask : public QRunnable look for that

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't matter you only guard against concurrent writes into the map with that mutex.
Reads can happen during load and creation.
count() and at() of std::map are not safe when the map is not const.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then reading in the map should also be enclosed by the mutex.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we still have that potential problem then you mean?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then reading in the map should also be enclosed by the mutex.

Yes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well Ill add it to the PR im opening in a few minutes then!

}

void DatabaseInterface::create()
Expand Down Expand Up @@ -2133,7 +2136,7 @@ void DatabaseInterface::preloadInterfaceForThread()
_db();
}

sqlite3* DatabaseInterface::load()
void DatabaseInterface::load()
{
JASPTIMER_SCOPE(DatabaseInterface::load);
assert(!_dbCreated || std::this_thread::get_id() != _dbCreator);
Expand All @@ -2143,7 +2146,7 @@ sqlite3* DatabaseInterface::load()
{
sqlite3* connection = _dbs.at(std::this_thread::get_id());
_loadMutex.unlock();
return connection;
return;
}

if(!std::filesystem::exists(dbFile()))
Expand Down Expand Up @@ -2196,7 +2199,7 @@ sqlite3* DatabaseInterface::load()
}
}

return db;
return;
}

void DatabaseInterface::close()
Expand Down
4 changes: 1 addition & 3 deletions CommonData/databaseinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,7 @@ class DatabaseInterface
void _runStatementsRepeatedly( const std::string & statements, std::function<bool( std::function<void(sqlite3_stmt *stmt)> ** bindParameters, size_t row)> bindParameterFactory, std::function<void(size_t row, size_t repetition, sqlite3_stmt *stmt)> * processRow = nullptr, bool ignoreFails = false);

void create(); ///< Creates a new sqlite database in sessiondir and loads it
sqlite3* load(); ///< Loads a sqlite database from sessiondir (after loading a jaspfile)


void load(); ///< Loads a sqlite database from sessiondir (after loading a jaspfile)

std::map<std::thread::id, sqlite3*> _dbs;
std::thread::id _dbCreator;
Expand Down
Loading