Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 10 additions & 0 deletions src/include/OpenImageIO/imageio.h
Original file line number Diff line number Diff line change
Expand Up @@ -3968,6 +3968,16 @@ OIIO_API std::string geterror(bool clear = true);
/// enable globally in an environment where security is a higher priority
/// than being tolerant of partially broken image files.
///
/// - `ustring:cleanup` (int: 0)
///
/// If nonzero, upon exit, do a thorough (and possibly expensive) teardown
/// of ustring internal resources to ensure that there are no apparent
/// memory leaks. This is only desirable in certain debugging situations.
/// Ordinarily, it is better to finish as quickly as possible, so the
/// default of 0 skips a time consuming and pointless teardown of the
/// ustring internal allocations when the app exits. Note that this can
/// also be enabled with the `OIIO_USTRING_CLEANUP` environment variable.
///
/// EXAMPLES:
/// ```
/// // Setting single simple values simply:
Expand Down
6 changes: 5 additions & 1 deletion src/include/imageio_pvt.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ extern atomic_ll IB_local_mem_current;
extern atomic_ll IB_local_mem_peak;
extern std::atomic<float> IB_total_open_time;
extern std::atomic<float> IB_total_image_read_time;
extern OIIO_UTIL_API int oiio_use_tbb; // This lives in libOpenImageIO_Util

// These live in libOpenImageIO_Util
extern OIIO_UTIL_API int oiio_use_tbb;
extern OIIO_UTIL_API int oiio_ustring_cleanup;

OIIO_API const std::vector<std::string>&
font_dirs();
OIIO_API const std::vector<std::string>&
Expand Down
20 changes: 14 additions & 6 deletions src/libOpenImageIO/imageio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,10 @@ attribute(string_view name, TypeDesc type, const void* val)

// Things below here need to buarded by the attrib_mutex
std::lock_guard lock(attrib_mutex);
if (name == "debug" && type == TypeInt) {
oiio_print_debug = *(const int*)val;
return true;
}
if (name == "read_chunk" && type == TypeInt) {
oiio_read_chunk = *(const int*)val;
return true;
Expand Down Expand Up @@ -447,10 +451,6 @@ attribute(string_view name, TypeDesc type, const void* val)
oiio_use_tbb = *(const int*)val;
return true;
}
if (name == "debug" && type == TypeInt) {
oiio_print_debug = *(const int*)val;
return true;
}
if (name == "log_times" && type == TypeInt) {
oiio_log_times = *(const int*)val;
return true;
Expand All @@ -471,6 +471,10 @@ attribute(string_view name, TypeDesc type, const void* val)
oiio_try_all_readers = *(const int*)val;
return true;
}
if (name == "ustring:cleanup" && type == TypeInt) {
oiio_ustring_cleanup = *(const int*)val;
return true;
}
Comment thread
lgritz marked this conversation as resolved.

return false;
}
Expand Down Expand Up @@ -511,6 +515,10 @@ getattribute(string_view name, TypeDesc type, void* val)

// Things below here need to buarded by the attrib_mutex
std::lock_guard lock(attrib_mutex);
if (name == "debug" && type == TypeInt) {
*(int*)val = oiio_print_debug;
return true;
}
if (name == "read_chunk" && type == TypeInt) {
*(int*)val = oiio_read_chunk;
return true;
Expand Down Expand Up @@ -649,8 +657,8 @@ getattribute(string_view name, TypeDesc type, void* val)
*(int*)val = oiio_use_tbb;
return true;
}
if (name == "debug" && type == TypeInt) {
*(int*)val = oiio_print_debug;
if (name == "ustring:cleanup" && type == TypeInt) {
*(int*)val = oiio_ustring_cleanup;
return true;
}
if (name == "log_times" && type == TypeInt) {
Expand Down
42 changes: 40 additions & 2 deletions src/libutil/ustring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,29 @@
#include <OpenImageIO/dassert.h>
#include <OpenImageIO/export.h>
#include <OpenImageIO/strutil.h>
#include <OpenImageIO/sysutil.h>
#include <OpenImageIO/thread.h>
#include <OpenImageIO/unordered_map_concurrent.h>
#include <OpenImageIO/ustring.h>



OIIO_NAMESPACE_BEGIN
namespace pvt {

// If nonzero, the ustring table will be freed at process exit. This is off by
// default because cleanup is unnecessary (the OS reclaims the memory) and can
// add measurable time at exit for large tables. Enable it when using valgrind
// or other leak detectors to suppress false positives. Settable via
// OIIO::attribute("ustring:cleanup",1) or the OIIO_USTRING_CLEANUP
// environment variable.
OIIO_UTIL_API int oiio_ustring_cleanup = Strutil::stoi(
Sysutil::getenv("OIIO_USTRING_CLEANUP"));

} // namespace pvt
OIIO_NAMESPACE_END


OIIO_NAMESPACE_3_1_BEGIN

// Use rw spin locks
Expand Down Expand Up @@ -43,10 +62,25 @@ template<unsigned BASE_CAPACITY, unsigned POOL_SIZE> struct TableRepMap {
, memory_usage(sizeof(*this) + POOL_SIZE
+ sizeof(ustring::TableRep*) * BASE_CAPACITY)
{
pool_allocs.push_back(pool);
}

~TableRepMap()
{ /* just let memory leak */
{
if (OIIO::pvt::oiio_ustring_cleanup) {
// If requested, take the time to properly destroy all the entries
// and everything we malloced.
ustring_write_lock_t lock(mutex);
for (size_t i = 0; i <= mask; ++i) {
if (entries[i])
entries[i]->~TableRep();
}
free(entries);
for (auto p : pool_allocs)
free(p);
} else {
/* just let memory leak */
}
}

size_t get_memory_usage()
Expand Down Expand Up @@ -187,13 +221,16 @@ template<unsigned BASE_CAPACITY, unsigned POOL_SIZE> struct TableRepMap {

if (len >= POOL_SIZE) {
memory_usage += len;
return (char*)malloc(len); // no need to try and use the pool
char* r = (char*)malloc(len); // no need to try and use the pool
pool_allocs.push_back(r);
return r;
}
if (pool_offset + len > POOL_SIZE) {
// NOTE: old pool will leak - this is ok because ustrings cannot be freed
memory_usage += POOL_SIZE;
pool = (char*)malloc(POOL_SIZE);
pool_offset = 0;
pool_allocs.push_back(pool);
}
char* result = pool + pool_offset;
pool_offset += len;
Expand All @@ -207,6 +244,7 @@ template<unsigned BASE_CAPACITY, unsigned POOL_SIZE> struct TableRepMap {
char* pool;
size_t pool_offset = 0;
size_t memory_usage;
std::vector<char*> pool_allocs;
#ifdef USTRING_TRACK_NUM_LOOKUPS
size_t num_lookups = 0;
#endif
Expand Down
Loading