Skip to content

fix borrowable_ptr - #16005

Closed
daschuer wants to merge 6 commits into
mainfrom
borrowable_ptr
Closed

fix borrowable_ptr#16005
daschuer wants to merge 6 commits into
mainfrom
borrowable_ptr

Conversation

@daschuer

Copy link
Copy Markdown
Member

This is a copy of #14914 for review purpose.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to fix a thread-safety/race issue in borrowable_ptr by changing how borrowed_ptr instances are created (via an immutable std::weak_ptr), and updates the unit test to exercise the reset/borrow interaction in a multi-threaded scenario.

Changes:

  • Construct borrowed_ptr via m_weakPtr.lock() and make borrow() const.
  • Change reset() behavior to avoid unconditional mutex operations when empty.
  • Update BorrowableTest.TwoThreads to reset the borrowable and add additional borrowing after a forced scheduling point.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.

File Description
src/util/borrowable_ptr.h Adjusts borrowing/reset implementation to address thread-safety concerns by using a weak_ptr for borrowing and changing reset semantics.
src/test/borrowabletest.cpp Updates the concurrency test scenario to validate reset behavior and guard against deadlocks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/test/borrowabletest.cpp Outdated
Comment thread src/test/borrowabletest.cpp Outdated
Comment thread src/test/borrowabletest.cpp
Comment thread src/util/borrowable_ptr.h
Comment thread src/util/borrowable_ptr.h
Comment thread src/util/borrowable_ptr.h
Comment on lines 109 to 112
~borrowable_ptr() {
reset();
m_mutex.unlock();
}

// @brief Assign a new raw pointer to the `borrowable_ptr` but not owning
// @param p Raw pointer to the new object.
// @return Reference to this instance.
borrowable_ptr& operator=(Tp* p) {
reset();
m_mutex.unlock();
m_sharedPtr = std::shared_ptr<Tp>(p, borrowable_deleter(&m_mutex));
return *this;
// m_mutex.unlock();
}

Copilot AI Feb 18, 2026

Copy link

Choose a reason for hiding this comment

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

The destructor leaves a commented-out m_mutex.unlock() behind. Please remove this dead code (and, if unlocking is no longer needed with the updated reset(), consider documenting that in a short comment instead).

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

what do you want to do with this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I have removed the dead code as suggested.

Comment thread src/util/borrowable_ptr.h Outdated
Comment on lines +137 to +139
std::shared_ptr<Tp> m_sharedPtr; ///< Non-owning private shared pointer to the managed object.
// must not be changed after construction, because changing shared pointers is not thread safe.
const std::weak_ptr<Tp> m_weakPtr; ///< Non-owning shared pointer for sharing,

Copilot AI Feb 18, 2026

Copy link

Choose a reason for hiding this comment

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

The member comment for m_weakPtr is misleading/incomplete: it’s a std::weak_ptr (not a shared pointer), and the trailing comma makes the sentence incomplete. Please update the comment to clearly describe why this weak_ptr exists and what thread-safety guarantee it provides.

Suggested change
std::shared_ptr<Tp> m_sharedPtr; ///< Non-owning private shared pointer to the managed object.
// must not be changed after construction, because changing shared pointers is not thread safe.
const std::weak_ptr<Tp> m_weakPtr; ///< Non-owning shared pointer for sharing,
std::shared_ptr<Tp> m_sharedPtr; ///< Private shared pointer to the managed object, reset only by `borrowable_ptr`.
// Must not be changed after construction, because changing shared pointers is not thread safe.
const std::weak_ptr<Tp> m_weakPtr; ///< Const weak reference to `m_sharedPtr` used by `borrow()` so that threads can
///< safely obtain temporary strong references via `lock()` without mutating `m_sharedPtr`.

Copilot uses AI. Check for mistakes.

@daschuer daschuer left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

Comment thread src/test/borrowabletest.cpp
Comment thread src/util/borrowable_ptr.h
Comment thread src/util/borrowable_ptr.h
@daschuer daschuer mentioned this pull request Feb 23, 2026

@ywwg ywwg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this is looking good, as far as I can understand how this works :).

Comment thread src/util/borrowable_ptr.h
Comment on lines 109 to 112
~borrowable_ptr() {
reset();
m_mutex.unlock();
}

// @brief Assign a new raw pointer to the `borrowable_ptr` but not owning
// @param p Raw pointer to the new object.
// @return Reference to this instance.
borrowable_ptr& operator=(Tp* p) {
reset();
m_mutex.unlock();
m_sharedPtr = std::shared_ptr<Tp>(p, borrowable_deleter(&m_mutex));
return *this;
// m_mutex.unlock();
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

what do you want to do with this?

Comment thread src/test/borrowabletest.cpp Outdated
int* p2 = borrowed1.get();
qDebug() << "future2" << (p1 ? *p1 : 0) << (p2 ? *p2 : 0);
int* p2 = borrowed2.get();
qDebug() << "future2 a" << (p1 ? *p1 : 0) << (p2 ? *p2 : 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

stray debug messages?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

removed

@daschuer

daschuer commented Apr 3, 2026

Copy link
Copy Markdown
Member Author

Ups, already merged via ma private repository

@daschuer daschuer closed this Apr 3, 2026
@daschuer
daschuer deleted the borrowable_ptr branch April 3, 2026 23:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants