Are there copy on write maps?

Think about a stack based state, and keeping track of some info you store in a map. Is it possible in Rust (and if so, what would you use) to implement a copy on write strategy for those maps?

On the C++ side I have the following GraphicsState (the copy on write was implemented after the book's publication):

struct GraphicsState {
...
    // Updated after book publication: floatTextures, spectrumTextures, and
    // namedMaterials are all implemented using a "copy on write" approach
    // for more efficient GraphicsState management.  When state is pushed
    // in pbrtAttributeBegin(), we don't immediately make a copy of these
    // maps, but instead record that each one is shared.  Only if an item
    // is added to one is a unique copy actually made.
    using FloatTextureMap = std::map<std::string, std::shared_ptr<Texture<Float>>>;
    std::shared_ptr<FloatTextureMap> floatTextures;
    bool floatTexturesShared = false;

    using SpectrumTextureMap = std::map<std::string, std::shared_ptr<Texture<Spectrum>>>;
    std::shared_ptr<SpectrumTextureMap> spectrumTextures;
    bool spectrumTexturesShared = false;

    using NamedMaterialMap = std::map<std::string, std::shared_ptr<MaterialInstance>>;
    std::shared_ptr<NamedMaterialMap> namedMaterials;
    bool namedMaterialsShared = false;
...
}

So far I have used HashMap for those maps on the Rust side:

#[derive(Default)]
pub struct GraphicsState {
...
    pub float_textures: HashMap<String, Arc<Texture<Float> + Send + Sync>>,
    pub spectrum_textures: HashMap<String, Arc<Texture<Spectrum> + Send + Sync>>,
...
    pub named_materials: HashMap<String, Option<Arc<Material + Send + Sync>>>,
...
}

Any ideas?

Maybe you're looking for this? https://crates.io/crates/im

2 Likes

Thanks, @vorner, I will check that out ...

RPDS is also a good choice: https://crates.io/crates/rpds Which one to choose comes down to what API you prefer (or need) — there are some differences in the advanced methods.

2 Likes

Thanks, @passcod, that looks interesting too :+1:

For less ideal but simpler solution, there's Arc::make_mut() method which clones its content if this Arc has more than one owner, and returns &mut of it. So Arc<HashMap> can be used for it.

3 Likes

That, @Hyeonu, might be the easiest solution for now. Thanks.

I implemented @Hyeonu's solution for now:

https://github.com/wahn/rs_pbrt/commit/314df14f055d318407a86177dc802c0d5ee1b513

Thanks, again, for all the hints. That's really good to know for the future :+1:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.