0

Context: I'm trying to write a resource/content manager. When content is loaded, a class describing the resource and holding the unmanaged data is allocated and passed back to the caller. A feature I would like to have for this manager is the ability to reload assets during the runtime of the program. At this point however, the reference to the resource has likely been shared across various parts of the program, and as per my understanding, creating a new resource and assigning an old reference will simply change the reference of that specific variable to the new resource and leave the rest unchanged.

My question is thus: how to I create a new instance of the class, and copy into the memory block where the previous resource is located? Or, what I presume to be the real question here: how do I get around not being able to do this? (I assume due to the arbitrary nature of the pointers, that having different data, especially of different size would not work regardless, but I don't know, and can't find answers elsewhere.)

Speculation (feel free to skip): My first guess as to a solution to the second question is passing around references to the content manager itself with an identifier, but that seems rather unwieldy, having to pass around multiple references in the place of one. Another solution would be having an event system trigger on reload, but having every class that uses these resources having to manage this event also seems like a bad idea.

If more context is required for anyone who may be able to answer, please leave a comment, thank you.

sfbea
  • 159
  • 1
  • 11
  • What do you mean with "unmanaged data"? A IntPtr to some unmanaged memory? What kind of data are you sharing? Plain bytes or some complex types? How is the data shared with the rest of the application? – JonasH Aug 27 '20 at 19:46
  • Texture2D; XNA/Monogame. It's an abstraction over DirectX textures or OpenGL textures loaded into the GPU. In the case of DirectX, the Texture2D class contains a reference to a SharpDX.DirectX.Texture2D class (c++), of which is all managed through interop via the sharpdx bindings, as well as, as I assume, some sort of handle to the texture data on the GPU. OpenGL seems a bit more decoupled under the hood if I'm understanding the source code correctly, seeming to have only some kind of integer ID to refer back to the underlying resource, but preferably I need a catch-all solution. – sfbea Aug 27 '20 at 22:25
  • As for your last question: it's just the reference type being passed around, as mentioned above, nothing fancy, yet. – sfbea Aug 27 '20 at 22:27

1 Answers1

1

If you can get a pointer to the unmanaged memory it is perfectly possible to overwrite it with something else, See copy intptr for some information on how. This will not work if the memory has been copied somewhere else, or if the new data does not have the same size as the old data.

You can do something similar with a managed array of value types, but I do not think you can get a pointer to a reference type object. So you cannot replace an reference object in place. You could however use reflection you change the fields in the object if you wanted, but this is generally not recommended.

One way to approach this kind of problem would be with indirection. Rather than sharing the object, share a wrapper that allows the object to be replaced. It is also possible to add an event to this wrapper that is raised when the object is replaced. With this system various components might need to monitor the resources for changes and handle as appropriate.

If this is for a game I would consider just restarting the entire graphics system and reload all resources, it might be easier than ensuring all components handle reloading correctly.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • Thanks for the reply. I've realised since yesterday I do not need to be handling any of the unmanaged data, I only need to perform some kind of member-wise set of the reference. Reflection appeared to be one way to do this, as you've mentioned. Can I ask why this isn't recommended (besides its reliance on non-api staticity of the type and the error-prone method of retrieving it)? Do you know of other ways to do a member-wise clone on something with private fields? The wrapper idea seems the best to be if reflection is the only other option. – sfbea Aug 28 '20 at 13:38
  • Your last suggestion may be in order too, I will have to see how I am able to mesh certain systems together, am marking your answer as correct so long as I believe it to hold everything relevant to my case, thank you. – sfbea Aug 28 '20 at 13:40
  • @SFB Drago as mentioned messing with private members using reflection is likely to be very fragile. It can be bug-prone since you can bypass any validation and other invariants, and is likely to break when switching versions. Not saying reflection should never be used, but you should be aware of the risks. – JonasH Aug 28 '20 at 14:20