-
Notifications
You must be signed in to change notification settings - Fork 596
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove boost thread_specific_ptr #4221
Changes from 8 commits
534dfa7
17a1d2f
5aa4023
661b178
6815efb
cb86c35
6554173
d66fb64
bab0860
d7e1afe
5bc1265
ab60908
fd2db6e
ac5752c
da93004
00b8168
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,8 @@ | |
#include <memory> | ||
#include <vector> | ||
|
||
#include <tsl/robin_map.h> | ||
|
||
#include <OpenImageIO/dassert.h> | ||
#include <OpenImageIO/deepdata.h> | ||
#include <OpenImageIO/filesystem.h> | ||
|
@@ -19,21 +21,19 @@ | |
|
||
#include "imageio_pvt.h" | ||
|
||
#include <boost/thread/tss.hpp> | ||
using boost::thread_specific_ptr; | ||
|
||
|
||
OIIO_NAMESPACE_BEGIN | ||
using namespace pvt; | ||
|
||
|
||
// store an error message per thread, for a specific ImageInput | ||
static thread_local tsl::robin_map<const ImageInput*, std::string> | ||
input_error_messages; | ||
|
||
class ImageInput::Impl { | ||
public: | ||
// So we can lock this ImageInput for the thread-safe methods. | ||
std::recursive_mutex m_mutex; | ||
// Thread-specific error message for this ImageInput. | ||
thread_specific_ptr<std::string> m_errormessage; | ||
int m_threads = 0; | ||
|
||
// The IOProxy object we will use for all I/O operations. | ||
|
@@ -1090,18 +1090,14 @@ ImageInput::append_error(string_view message) const | |
{ | ||
if (message.size() && message.back() == '\n') | ||
message.remove_suffix(1); | ||
std::string* errptr = m_impl->m_errormessage.get(); | ||
if (!errptr) { | ||
errptr = new std::string; | ||
m_impl->m_errormessage.reset(errptr); | ||
} | ||
std::string& err_str = input_error_messages[this]; | ||
OIIO_DASSERT( | ||
errptr->size() < 1024 * 1024 * 16 | ||
err_str.size() < 1024 * 1024 * 16 | ||
&& "Accumulated error messages > 16MB. Try checking return codes!"); | ||
if (errptr->size() < 1024 * 1024 * 16) { | ||
if (errptr->size() && errptr->back() != '\n') | ||
*errptr += '\n'; | ||
*errptr += std::string(message); | ||
if (err_str.size() < 1024 * 1024 * 16) { | ||
if (err_str.size() && err_str.back() != '\n') | ||
err_str += '\n'; | ||
err_str.append(message.begin(), message.end()); | ||
} | ||
} | ||
|
||
|
@@ -1110,8 +1106,10 @@ ImageInput::append_error(string_view message) const | |
bool | ||
ImageInput::has_error() const | ||
{ | ||
std::string* errptr = m_impl->m_errormessage.get(); | ||
return (errptr && errptr->size()); | ||
auto iter = input_error_messages.find(this); | ||
if (iter == input_error_messages.end()) | ||
return false; | ||
return iter.value().size() > 0; | ||
} | ||
|
||
|
||
|
@@ -1120,11 +1118,13 @@ std::string | |
ImageInput::geterror(bool clear) const | ||
{ | ||
std::string e; | ||
std::string* errptr = m_impl->m_errormessage.get(); | ||
if (errptr) { | ||
e = *errptr; | ||
if (clear) | ||
errptr->clear(); | ||
auto iter = input_error_messages.find(this); | ||
if (iter != input_error_messages.end()) { | ||
e = iter.value(); | ||
if (clear) { | ||
iter.value().clear(); | ||
iter.value().shrink_to_fit(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why shrink_to_fit instead of erase? You're freeing the characters, but not getting rid of the node in the hash table that contains the string itself. You could imagine a pattern of repeated ImageInput constructions (with errors) that would lead to a fuller and fuller hash table containing unusabl empty strings? Versus actually removing the hash table entry when the ImageInput is destroyed by the right thread (which is mostly). I don't think it's a problem in practice -- to be a real issue, you'd need tons of created and then destroyed ImageInput objects that encountered errors along the way. I'm happy to make that a "cross that very unlikely bridge when we get to it." But I'm curious if you did this because you spotted some big flaw in my proposal that I hadn't considered. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I see what you mean now. Yes of course erase makes more sense. |
||
} | ||
} | ||
return e; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this was
input_error_messages.erase(iter)
, instead ofclear()
, then any time an error was retrieved/clear by the right thread, the entry in the map would fully be cleaned up, instead of "leaking", even though the thing it leaks is usually an empty string.