Skip to content

Commit ef615c8

Browse files
lgritzzachlewis
authored andcommitted
api: use shared_ptr for ImageCache and TextureSystem (AcademySoftwareFoundation#4377)
Change IC::create() and TS::create() to return shared_ptr instead of a raw pointer. This cleans up a lot of lingering lifetime management issue of these classes. The switch to 3.0 is an opportunity to make breaking changes to these APIs. For the sake of downstream users, we define preprocessor symbols OIIO_IMAGECACHE_CREATE_SHARED and OIIO_TEXTURESYSTEM_CREATE_SHARED to signal that the new APIs are present. Some very minor changes may be needed at the call site. --------- Signed-off-by: Larry Gritz <lg@larrygritz.com> Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
1 parent 0eedbcb commit ef615c8

File tree

20 files changed

+140
-171
lines changed

20 files changed

+140
-171
lines changed

src/iconvert/iconvert.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,8 @@ convert_file(const std::string& in_filename, const std::string& out_filename)
356356
// subimage appending, we gather them all first.
357357
std::vector<ImageSpec> subimagespecs;
358358
if (out->supports("multiimage") && !out->supports("appendsubimage")) {
359-
ImageCache* imagecache = ImageCache::create();
360-
int nsubimages = 0;
359+
auto imagecache = ImageCache::create();
360+
int nsubimages = 0;
361361
ustring ufilename(in_filename);
362362
imagecache->get_image_info(ufilename, 0, 0, ustring("subimages"),
363363
TypeInt, &nsubimages);
@@ -370,7 +370,6 @@ convert_file(const std::string& in_filename, const std::string& out_filename)
370370
adjust_spec(in.get(), out.get(), inspec, subimagespecs[i]);
371371
}
372372
}
373-
ImageCache::destroy(imagecache);
374373
}
375374

376375
bool ok = true;

src/idiff/idiff.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,9 @@ getargs(int argc, char* argv[])
119119

120120

121121
static bool
122-
read_input(const std::string& filename, ImageBuf& img, ImageCache* cache,
123-
int subimage = 0, int miplevel = 0)
122+
read_input(const std::string& filename, ImageBuf& img,
123+
std::shared_ptr<ImageCache> cache, int subimage = 0,
124+
int miplevel = 0)
124125
{
125126
if (img.subimage() >= 0 && img.subimage() == subimage
126127
&& img.miplevel() == miplevel)
@@ -232,7 +233,7 @@ main(int argc, char* argv[])
232233

233234
// Create a private ImageCache so we can customize its cache size
234235
// and instruct it store everything internally as floats.
235-
ImageCache* imagecache = ImageCache::create(true);
236+
std::shared_ptr<ImageCache> imagecache = ImageCache::create(true);
236237
imagecache->attribute("forcefloat", 1);
237238
if (sizeof(void*) == 4) // 32 bit or 64?
238239
imagecache->attribute("max_memory_MB", 512.0);
@@ -418,7 +419,6 @@ main(int argc, char* argv[])
418419
}
419420

420421
imagecache->invalidate_all(true);
421-
ImageCache::destroy(imagecache);
422422
shutdown();
423423
return ret;
424424
}

src/include/OpenImageIO/imagebuf.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ enum class InitializePixels { No = 0, Yes = 1 };
7777
/// translate into a different data format than appears in the file).
7878
///
7979
/// ImageBuf data coming from disk files may optionally be backed by
80-
/// ImageCache, by explicitly passing an `ImageCache*` to the ImageBuf
80+
/// ImageCache, by explicitly passing an ImageCache to the ImageBuf
8181
/// constructor or `reset()` method (pass `ImageCache::create()` to get a
8282
/// pointer to the default global ImageCache), or by having previously set the
8383
/// global OIIO attribute `"imagebuf:use_imagecache"` to a nonzero value. When
@@ -186,9 +186,9 @@ class OIIO_API ImageBuf {
186186
/// ensure that it remains valid for the lifetime of the ImageBuf.
187187
///
188188
explicit ImageBuf(string_view name, int subimage = 0, int miplevel = 0,
189-
ImageCache* imagecache = nullptr,
190-
const ImageSpec* config = nullptr,
191-
Filesystem::IOProxy* ioproxy = nullptr);
189+
std::shared_ptr<ImageCache> imagecache = {},
190+
const ImageSpec* config = nullptr,
191+
Filesystem::IOProxy* ioproxy = nullptr);
192192

193193
/// Construct a writable ImageBuf with the given specification
194194
/// (including resolution, data type, metadata, etc.). The ImageBuf will
@@ -270,9 +270,9 @@ class OIIO_API ImageBuf {
270270
/// as if newly constructed with the same arguments, as a read-only
271271
/// representation of an existing image file.
272272
void reset(string_view name, int subimage = 0, int miplevel = 0,
273-
ImageCache* imagecache = nullptr,
274-
const ImageSpec* config = nullptr,
275-
Filesystem::IOProxy* ioproxy = nullptr);
273+
std::shared_ptr<ImageCache> imagecache = {},
274+
const ImageSpec* config = nullptr,
275+
Filesystem::IOProxy* ioproxy = nullptr);
276276

277277
/// Destroy any previous contents of the ImageBuf and re-initialize it
278278
/// as if newly constructed with the same arguments, as a read/write
@@ -1005,9 +1005,9 @@ class OIIO_API ImageBuf {
10051005
/// image being in RAM somewhere?
10061006
bool cachedpixels() const;
10071007

1008-
/// A pointer to the underlying ImageCache, or nullptr if this ImageBuf
1009-
/// is not backed by an ImageCache.
1010-
ImageCache* imagecache() const;
1008+
/// A shared pointer to the underlying ImageCache, or empty if this
1009+
/// ImageBuf is not backed by an ImageCache.
1010+
std::shared_ptr<ImageCache> imagecache() const;
10111011

10121012
/// Return the address where pixel `(x,y,z)`, channel `ch`, is stored in
10131013
/// the image buffer. Use with extreme caution! Will return `nullptr`
@@ -1151,7 +1151,7 @@ class OIIO_API ImageBuf {
11511151
// Deprecated things -- might be removed at any time
11521152

11531153
OIIO_DEPRECATED("Use `ImageBuf(name, 0, 0, imagecache, nullptr)` (2.2)")
1154-
ImageBuf(string_view name, ImageCache* imagecache)
1154+
ImageBuf(string_view name, std::shared_ptr<ImageCache> imagecache)
11551155
: ImageBuf(name, 0, 0, imagecache)
11561156
{
11571157
}
@@ -1164,7 +1164,7 @@ class OIIO_API ImageBuf {
11641164
}
11651165

11661166
OIIO_DEPRECATED("Use `reset(name, 0, 0, imagecache)` (2.2)")
1167-
void reset(string_view name, ImageCache* imagecache)
1167+
void reset(string_view name, std::shared_ptr<ImageCache> imagecache)
11681168
{
11691169
reset(name, 0, 0, imagecache);
11701170
}

src/include/OpenImageIO/imagecache.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
// Does invalidate() support the optional `force` flag?
2525
#define OIIO_IMAGECACHE_INVALIDATE_FORCE 1
2626

27+
// Does ImageCache::create() return a shared pointer?
28+
#define OIIO_IMAGECACHE_CREATE_SHARED 1
29+
2730

2831

2932
OIIO_NAMESPACE_BEGIN
@@ -56,8 +59,7 @@ class OIIO_API ImageCache {
5659
/// or destroy the concrete implementation, so two static methods of
5760
/// ImageCache are provided:
5861

59-
/// Create a ImageCache and return a raw pointer to it. This should
60-
/// only be freed by passing it to `ImageCache::destroy()`!
62+
/// Create a ImageCache and return a shared pointer to it.
6163
///
6264
/// @param shared
6365
/// If `true`, the pointer returned will be a shared ImageCache (so
@@ -66,30 +68,28 @@ class OIIO_API ImageCache {
6668
/// completely unique ImageCache will be created and returned.
6769
///
6870
/// @returns
69-
/// A raw pointer to an ImageCache, which can only be freed with
71+
/// A shared pointer to an ImageCache, which can only be freed with
7072
/// `ImageCache::destroy()`.
7173
///
7274
/// @see ImageCache::destroy
73-
static ImageCache* create(bool shared = true);
75+
static std::shared_ptr<ImageCache> create(bool shared = true);
7476

75-
/// Destroy an allocated ImageCache, including freeing all system
76-
/// resources that it holds.
77-
///
78-
/// It is safe to destroy even a shared ImageCache, as the implementation
79-
/// of `destroy()` will recognize a shared one and only truly release
80-
/// its resources if it has been requested to be destroyed as many times as
81-
/// shared ImageCache's were created.
77+
/// Release the shared_ptr to an ImageCache, including freeing all
78+
/// system resources that it holds if no one else is still using it. This
79+
/// is not strictly necessary to call, simply destroying the shared_ptr
80+
/// will do the same thing, but this call is for backward compatibility
81+
/// and is helpful if you want to use the teardown option.
8282
///
8383
/// @param cache
84-
/// Raw pointer to the ImageCache to destroy.
84+
/// Shared pointer to the ImageCache to destroy.
8585
///
8686
/// @param teardown
8787
/// For a shared ImageCache, if the `teardown` parameter is
8888
/// `true`, it will try to truly destroy the shared cache if
8989
/// nobody else is still holding a reference (otherwise, it will
9090
/// leave it intact). This parameter has no effect if `cache` was
9191
/// not the single globally shared ImageCache.
92-
static void destroy(ImageCache* cache, bool teardown = false);
92+
static void destroy(std::shared_ptr<ImageCache>& cache, bool teardown = false);
9393

9494
/// @}
9595

src/include/OpenImageIO/texture.h

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
#define OIIO_TEXTURESYSTEM_SUPPORTS_STOCHASTIC 1
2828
#define OIIO_TEXTURESYSTEM_SUPPORTS_DECODE_BY_USTRINGHASH 1
2929

30+
// Does TextureSystem::create() return a shared pointer?
31+
#define OIIO_TEXTURESYSTEM_CREATE_SHARED 1
32+
3033
#ifndef INCLUDED_IMATHVEC_H
3134
// Placeholder declaration for Imath::V3f if no Imath headers have been
3235
// included.
@@ -365,8 +368,7 @@ class OIIO_API TextureSystem {
365368
/// or destroy the concrete implementation, so two static methods of
366369
/// TextureSystem are provided:
367370

368-
/// Create a TextureSystem and return a pointer to it. This should only
369-
/// be freed by passing it to TextureSystem::destroy()!
371+
/// Create a TextureSystem and return a shared pointer to it.
370372
///
371373
/// @param shared
372374
/// If `shared` is `true`, the pointer returned will be a shared
@@ -376,41 +378,39 @@ class OIIO_API TextureSystem {
376378
/// completely unique TextureCache will be created and returned.
377379
///
378380
/// @param imagecache
379-
/// If `shared` is `false` and `imagecache` is not `nullptr`, the
381+
/// If `shared` is `false` and `imagecache` is not empty, the
380382
/// TextureSystem will use this as its underlying ImageCache. In
381383
/// that case, it is the caller who is responsible for eventually
382384
/// freeing the ImageCache after the TextureSystem is destroyed. If
383-
/// `shared` is `false` and `imagecache` is `nullptr`, then a custom
385+
/// `shared` is `false` and `imagecache` is empty, then a custom
384386
/// ImageCache will be created, owned by the TextureSystem, and
385387
/// automatically freed when the TS destroys.
386388
///
387389
/// @returns
388-
/// A raw pointer to a TextureSystem, which can only be freed with
389-
/// `TextureSystem::destroy()`.
390+
/// A shared pointer to a TextureSystem which will be destroyed only
391+
/// when the last shared_ptr to it is destroyed.
390392
///
391393
/// @see TextureSystem::destroy
392-
static TextureSystem *create (bool shared=true,
393-
ImageCache *imagecache=nullptr);
394+
static std::shared_ptr<TextureSystem> create(bool shared=true,
395+
std::shared_ptr<ImageCache> imagecache = {});
394396

395-
/// Destroy an allocated TextureSystem, including freeing all system
396-
/// resources that it holds.
397-
///
398-
/// It is safe to destroy even a shared TextureSystem, as the
399-
/// implementation of `destroy()` will recognize a shared one and only
400-
/// truly release its resources if it has been requested to be destroyed
401-
/// as many times as shared TextureSystem's were created.
397+
/// Release the shared_ptr to a TextureSystem, including freeing all
398+
/// system resources that it holds if no one else is still using it. This
399+
/// is not strictly necessary to call, simply destroying the shared_ptr
400+
/// will do the same thing, but this call is for backward compatibility
401+
/// and is helpful if you want to use the teardown_imagecache option.
402402
///
403403
/// @param ts
404-
/// Raw pointer to the TextureSystem to destroy.
404+
/// Shared pointer to the TextureSystem to destroy.
405405
///
406406
/// @param teardown_imagecache
407407
/// For a shared TextureSystem, if the `teardown_imagecache`
408408
/// parameter is `true`, it will try to truly destroy the shared
409409
/// cache if nobody else is still holding a reference (otherwise, it
410410
/// will leave it intact). This parameter has no effect if `ts` was
411411
/// not the single globally shared TextureSystem.
412-
static void destroy (TextureSystem *ts,
413-
bool teardown_imagecache = false);
412+
static void destroy(std::shared_ptr<TextureSystem>& ts,
413+
bool teardown_imagecache = false);
414414

415415
/// @}
416416

@@ -1652,7 +1652,7 @@ class OIIO_API TextureSystem {
16521652

16531653
/// Return an opaque, non-owning pointer to the underlying ImageCache
16541654
/// (if there is one).
1655-
virtual ImageCache *imagecache () const = 0;
1655+
virtual std::shared_ptr<ImageCache> imagecache() const = 0;
16561656

16571657
virtual ~TextureSystem () { }
16581658

src/iv/imageviewer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,7 @@ ImageViewer::readSettings(bool ui_is_set_up)
791791

792792
OIIO::attribute("imagebuf:use_imagecache", 1);
793793

794-
ImageCache* imagecache = ImageCache::create(true);
794+
auto imagecache = ImageCache::create(true);
795795
imagecache->attribute("automip", autoMipmap->isChecked());
796796
imagecache->attribute("max_memory_MB", (float)maxMemoryIC->value());
797797
}

src/iv/ivmain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ main(int argc, char* argv[])
129129
mainWin->show();
130130

131131
// Set up the imagecache with parameters that make sense for iv
132-
ImageCache* imagecache = ImageCache::create(true);
132+
auto imagecache = ImageCache::create(true);
133133
imagecache->attribute("autotile", 256);
134134
imagecache->attribute("deduplicate", (int)0);
135135
if (ap["no-autopremult"].get<int>())

0 commit comments

Comments
 (0)