Archived

This topic is now archived and is closed to further replies.

Guest Doug Moldenhauer

Questions Around Gauge And Dll Programming

Recommended Posts

Hi guys. I'll like to ask a few questions and request some guidance. You may have noticed from my other thread regardingAutopilot and Autothrottle controls that I was interested in trying to improve the responce and control of these systems.The Autothrottle has always been a slug as far as responce is concerned. I got board lastnight and I programmed a Autothrottle Speed hold PID. Currently its just running as a external application that talks to the sim via FSUIPC. TheCurrent responce after some initial tuneing has been pretty good. Its currently as good or better than the stock 737controller. I still have to develop setpoint rate change and I'd like to add feedforward so it will better control durringinitial climbs and decents. At this time there is still some under/overshoot durring a change to climb or decent, however it recovers much morequickly than the stock controller. I can tune to minimize this, however as you would expect, it is a bit nervous durringsteady state. This is why I'd like to add the addition of feedforward from the Pitch controller to give the Autothrottlea kick in the pants durring the transition from steady state to a climb or decent.This will require that I write a Pitch and Altitude controller, perhaps with LVL Change mode.My question is this, once I get all of this working, I'd like to add it to a aircraft that I've been playing around with. It isbased on the stock 737-800 but modified. I was wondering if anyone might offer their suggestions as to how I mightimplement in either a gauge or dll. I would like to use the stock 737 Autopilot panel and buttons, but steer the datato my controller. I currently use the knob on the 2d/3d panel to adjust the speed setpoint, I just dont turn on the stock autothrottle.Should this be a dll? If so, how would I get started. What information should I have to create a dll as I've never donethat for the simulator. I assume I will have to modify the current autopilot panel and have the mode buttons set myinternal variables. Where should I start to get information regarding that?Any suggestions would be greatly appreciated.Thanks in advance Doug

Share this post


Link to post
Share on other sites
Help AVSIM continue to serve you!
Please donate today!

Programming a gauge or a DLL is exactly the same, because a gauge IS a DLL.The main difference I see here is that if you program it as a gauge, it will work only of the gauge is used in your aircraft panel because the gauge DLL will be loaded only when the panel is loaded, which is certainly what you want.If you program it as a DLL (I'd rather say "as a module"), it is loaded when FS2004/FSX starts and it is valid for all the aircrafts, it does not depend on the panel you use. This can be useful for general usage purpose but I don't think it is the right strategy for your throttle controller.BTW, I congratulate you for this hard work because I know how difficult it is. I have developed the same kind of PID for the Wilco Airbus Series :)Eric

Share this post


Link to post
Share on other sites
Programming a gauge or a DLL is exactly the same, because a gauge IS a DLL.The main difference I see here is that if you program it as a gauge, it will work only of the gauge is used in your aircraft panel because the gauge DLL will be loaded only when the panel is loaded, which is certainly what you want.If you program it as a DLL (I'd rather say "as a module"), it is loaded when FS2004/FSX starts and it is valid for all the aircrafts, it does not depend on the panel you use. This can be useful for general usage purpose but I don't think it is the right strategy for your throttle controller.BTW, I congratulate you for this hard work because I know how difficult it is. I have developed the same kind of PID for the Wilco Airbus Series :)Eric
Rocky, thanks for the information. I'm going to continue tonight and get the rate controller for the Speed Setpoint programmed, and then start on the Pitch, Altitude, and Vertical Rate Controllers. Once that is completed, I should be able to implement the Feedforward from the Vertical Controllers into the Autothrottle Speed Controller.I think I'll continue as a standalone controller at this time to minimize some of the complexity and focus more on the engineering issues, as I don't know much about GAU programming at this time.. I'm sure once I get everything working properly, moving it over to a GAU should be fairly easy to do once I learn about GAU file details.Any other suggestions from your experience would be appreciated :)

Share this post


Link to post
Share on other sites
Programming a gauge or a DLL is exactly the same, because a gauge IS a DLL.The main difference I see here is that if you program it as a gauge, it will work only of the gauge is used in your aircraft panel because the gauge DLL will be loaded only when the panel is loaded, which is certainly what you want.If you program it as a DLL (I'd rather say "as a module"), it is loaded when FS2004/FSX starts and it is valid for all the aircrafts, it does not depend on the panel you use. This can be useful for general usage purpose but I don't think it is the right strategy for your throttle controller.BTW, I congratulate you for this hard work because I know how difficult it is. I have developed the same kind of PID for the Wilco Airbus Series :)Eric
As Rocky says, C gauge files are indeed DLLs. The problem is that the gauges.h header file is somewhat archaic and convoluted, with the DLL code structure of the gauge code hidden behind a mass of Macros and pre-processor directives. This makes figuring out how the code is structured, works and interfaces with (I believe) panel.dll somewhat of a nightmare for those who are actually familiar with creating DLLs..well, at least I did ;)If you also code using Visual Studio 2005 or 2008, you will likely have to spend time wrestling the dated code generated by the gauges.h macros into an acceptable form using a lot of casting and other 'arm-twisting' methods to generate valid C++ code that these later versions of Visual Studio will not complain about.I'm hoping that in the next iteraration of Flight Simulator that the develeopment team revisit the gauges.h file and rewrite it so that those familiar with programming in C++ can avoid this macro psuedo-language, thereby getting back to a cleaner C++ syntax - it would make setting breakpoints and debugging a lot cleaner too.And while I'm at it could the development team please provide us with a gauge drawing surface that can be used from video card memory so we can make use of hardware acceleration for gauge graphics ;)

Share this post


Link to post
Share on other sites

I agree with you Darren, I really hope MS will provide us a better gauge.h, more C++ oriented, and a way to use accelerated graphics for the gauges.But I don't fully agree with you about the macros in gauges.h. I think it is not so bad because it helps people to build a gauge without having to be an expert in DLL development. It was my case some years ago and I was very happy to find these macros ;-)Eric

Share this post


Link to post
Share on other sites

Wow... I have zero issues using gauges.h in VS C++ unaltered.FYI, rendering to the card's memory is a waste of time. None of what we do gauge-wise requires that.

Share this post


Link to post
Share on other sites

Well I hope I don't have a real hard time trying to get a GAU file created. Don't laugh....but I'm using Visual C++ 6.0. That is what I used to use years back when I was writting code more often. I had Visual Studio 2005 and Visual Studio 2008 dot net versions but I don't learn quite as fast as I used to as I'm gettingolder hahahhahahah :( I wrote some code with Visual Studio 2008 to exchange data back and forth with a Microcontroller I built via USB com, but that was the only application I've written in the dot Net code.I've been able to compile and run the MFC programs from FSUIPC but I havn't tried any gauge compiling from the SDK yet.

Share this post


Link to post
Share on other sites
Wow... I have zero issues using gauges.h in VS C++ unaltered.FYI, rendering to the card's memory is a waste of time. None of what we do gauge-wise requires that.
Interesting point of view, Ed. So how do you think we can have gauges with accelerated graphics instead of GDI+ which is NOT accelerated?I think that replacing GDI+ with a faster (or an accelerated) library would greatly improve the frame rate of our aircrafts.Don't you think so?Eric

Share this post


Link to post
Share on other sites

Well, first GDI+ is accelerated. Just not all of it.Replacing GDI+... sure.However, once again... rendering directly to the card's memory isn't going to do much for us.

Share this post


Link to post
Share on other sites
Well, first GDI+ is accelerated. Just not all of it.Replacing GDI+... sure.However, once again... rendering directly to the card's memory isn't going to do much for us.
GDI+ is accelerated? Interesting, I didn't know this. In this case I wonder why it is so slow... But I don't work for Microsoft and I don't have access to the source code of GDI+, so I can't tell if GDI+ is accelerated or not. I really thought it was NOT accelerated, but I may be wrong here.Now about the renedering to card's memory, this may not be the right phrasing. What I mean here is that I would like to be able tu use the card's acceleration to draw gauge graphics. I can't believe my card is able to draw thousands of texture polygons per second and it is not able of drawing some anti-aliased lines and circles :)Eric

Share this post


Link to post
Share on other sites
Wow... I have zero issues using gauges.h in VS C++ unaltered.FYI, rendering to the card's memory is a waste of time. None of what we do gauge-wise requires that.
It's not required certainly, but a drawing surface in video memory would mean instant hardware acceleration for anyone wishing to use an API capable of leveraging it. I'm sure during the lifetime of FSX there will also be even more graphically intensive glass cockpit technology arriving in the real world that many developers would like to implement in gauges.Sure today's gauges aren't really pushing things in terms of visual complexity, but isn't this due to the fact that everything is drawn by the CPU and anything more complex would drag framerates down to problematic levels? I'm, thinking of an Avidyne CMAX here. I'd contemtplate a gauge which shys away from the somewhat simplfied graphics of the default GPS graphics, interrogating the terrain and navdata in FSX's BGL files and having a custom rendering system taking this raw data and presenting it in a more realistic manner than the FSX map and GPS display rendering subsystem manages to do.I had OpenGL rendering working quite well in my first attempts with gauge rendering, but as you probably know, the gauge drawing surface is in system memory, so no hardware acceleration. I'm comfortable with OpenGL so leveraging this API and having a drawing surface allowing hardware acceleration would be useful...certainly not a waste of time in my view.I'm finding many GDI+ gauges taking too much of a slice of my framerates these days in FSX becaue I enjoy flying with plenty of weather and other traffic about. GDI+ gauges tend to make my framerates more erratic with the rate varying between +- 10 fps, whereas with something like the methods used by RealityXP gauges affecting my framerates less widldy with maybe +- 2 fps.
GDI+ is accelerated? Interesting, I didn't know this. In this case I wonder why it is so slow... But I don't work for Microsoft and I don't have access to the source code of GDI+, so I can't tell if GDI+ is accelerated or not. I really thought it was NOT accelerated, but I may be wrong here.Now about the renedering to card's memory, this may not be the right phrasing. What I mean here is that I would like to be able tu use the card's acceleration to draw gauge graphics. I can't believe my card is able to draw thousands of texture polygons per second and it is not able of drawing some anti-aliased lines and circles :)Eric
Sadly, the only way a GPU will accelerate any rendering is if the data being manipulated is directly in the memory of your video card and not in system memory. It's all down to the architecture of the GPU pipeline I believe.
Well, first GDI+ is accelerated. Just not all of it.Replacing GDI+... sure.However, once again... rendering directly to the card's memory isn't going to do much for us.
Interesting. In my reading up on GDI+ I never encountered any topics that suggested GDI+ used acceleration to any useful degree and mostly this is reliant on a video card's 2D ecceleration capabilities, which vary wildly from manufacturer to manufacturer. 3D acceleration is much more widely accepted and all you need to do to get 2D graphics within a 3D accelerated card is ignore the Z dimension and render to screen coordinates.I'd certainly like any web-based information that could shed more details on where GDI+ is accelerated. I may take another look at GDI+.

Share this post


Link to post
Share on other sites
Interesting point of view, Ed. So how do you think we can have gauges with accelerated graphics instead of GDI+ which is NOT accelerated?I think that replacing GDI+ with a faster (or an accelerated) library would greatly improve the frame rate of our aircrafts.Don't you think so?Eric
The reason GDI+ is popular is because it's a clean, mature API with lots of features available - on the whole it really is an good general API. The only other option for greater speed is to write your own software rendering subsystem from scratch, which is no mean feat. Having a hardare accelerated drawing surface would provide superior speed to GDI+ by allowing equally mature and clean API's, such as OpenGL, to be used and gain the benefits of hardware accelerated performance automatically.I'm not experienced with GDI+ to be able to do detailed comparisons but I've always wondered if using OpenGL even without hardware acceleration would provide better software rendering performance than GDI+. Maybe there's somebody out there with experience of both API's who may be able to shed light on this?

Share this post


Link to post
Share on other sites

If GDI+ is so slow... how did I get the new Eaglesoft Citation X v2 out the door with tons of GDI+ rendering?I think GDI+ has a bad reputation that's not 100% earned, and probably a great deal of myth.In the Eaglesoft Citation X v2 virtual cockpit there are probably around 25 or so gauges that utilize GDI+ for rendering. On my system (P4 3.4ghz) I can see a steady 24fps in the VC, over 40fps in the 2D... unless FS starts to hog CPU cycles for scenery loads... at which point, you have to realize it's the FS engine and not your gauge that's at fault.

Share this post


Link to post
Share on other sites
If GDI+ is so slow... how did I get the new Eaglesoft Citation X v2 out the door with tons of GDI+ rendering?I think GDI+ has a bad reputation that's not 100% earned, and probably a great deal of myth.In the Eaglesoft Citation X v2 virtual cockpit there are probably around 25 or so gauges that utilize GDI+ for rendering. On my system (P4 3.4ghz) I can see a steady 24fps in the VC, over 40fps in the 2D... unless FS starts to hog CPU cycles for scenery loads... at which point, you have to realize it's the FS engine and not your gauge that's at fault.
I agree somewhat that GDI+ does tend to get overly bashed as being too slow. It's plainly a viable rendering method but the downside of GDI+, as well as any other alternative software rendering engine (RealityXP's methods for example), is that the CPU is doing the rendering work ( as well as gauge logic processing). And with the demands the FSX's engine makes on the CPU for non-graphics stuff such as autogen, terrain loading, traffic, aerodynamics etc, whenever you have load spikes when this data is being streamed in and processed, it adversly affects the entire rendering speed of a software-based renderer.I guess in the end it all boils down to how much of a percentage of gauge-processing time is actually spent in the rendering portions of a gauge using software rendering. Have you Eaglesoft guys needed to do such measurements? If so what are your findings? With that data, we would all be in better position to debate the pro's and con's of GDI+ or other rendering alternatives.I really wish I had the time to know more about GDI+ (and gauge programming generally) to get to the point where I could write efficient rendering code and compare non-accelerated OpenGL rendering to GDI+. Only by measuring performance can we get a definitive view of things so until then, there's no justification for taking overly negative attitudes towards GDI+ or other rendering methods. All we can do is report on percieved effects on framerates due to gauges in-game, which is not at all entirely accurate due to demands on the CPU from all manner of directions.

Share this post


Link to post
Share on other sites

Ed, I guess you are stronger than me in the usage of GDI+ because I made some tests and my conclusion is different.My Airbus uses 4 EFIS (PFD, ND, E/WD and SD) that are big and complex displays. When the EFIS are visible, the frame rate is around 35 FPS on my machine. When I hide the main panel (pressing Shift-1), the frame rate jumps up to 60 FPS, just because it is locked at 60. So my conclusion is that the GDI+ displays are rame rate killers, even if the usage of GDI+ is optimized.Eric

Share this post


Link to post
Share on other sites

That's not a very valid test. Try the same with non-GDI+ gauges rendering the same amount of information (graphics wise). Not eliminate the panel entirely. That only tells you how much faster the sim runs without ANY gauges.As I stated... the Cit X v2 has a great deal of GDI+ rendered gauges in the VC... pretty much all the gaugework except for the standby instruments.A typical rendering time for it's PFD is ~3ms.When discussing 'hardware acceleration'... keep in mind... the graphics card has zero access to flight sim variables and thus wouldn't have a clue regarding object rotation/translation in coordinating with FS. It isn't going to actually do one bit of the rendering for you. Zip, zilch, nada.The only advantage you could gain with using video memory is a reduced 'swap time' to bring your render to the screen. And if that's your bottleneck, you're doing it wrong from the get-go.

Share this post


Link to post
Share on other sites
That's not a very valid test. Try the same with non-GDI+ gauges rendering the same amount of information (graphics wise). Not eliminate the panel entirely. That only tells you how much faster the sim runs without ANY gauges.As I stated... the Cit X v2 has a great deal of GDI+ rendered gauges in the VC... pretty much all the gaugework except for the standby instruments.A typical rendering time for it's PFD is ~3ms.When discussing 'hardware acceleration'... keep in mind... the graphics card has zero access to flight sim variables and thus wouldn't have a clue regarding object rotation/translation in coordinating with FS. It isn't going to actually do one bit of the rendering for you. Zip, zilch, nada.The only advantage you could gain with using video memory is a reduced 'swap time' to bring your render to the screen. And if that's your bottleneck, you're doing it wrong from the get-go.
Not sure what you mean there Ed. I'm likely misunderstanding you but are you assuming flight simulation variables are to be stored in video card memory? If so that's not the case. That would also imply gauge logic code would be stored in video memory. Only the drawing surface, any bitmap sprites for common avioncs graphics (including font and image bitmaps), vertex lists representing common vector shapes (including any vector fonts or stroke-based fonts) for avionics graphics etc would be stored in video card memory. And as for the 'swap time' you mention, there would be hugely reduced need for image data to be swapped from system to video memory because you would be rendering to a surface directly in video memory (or more likely a backbuffer that is blit-copied within very fast video memory to a primary buffer. GPU (Graphics Processing Unit) blits leave CPU blits coughing in the wake of their dust).All your gauge simulation variables would still reside in system memory. You would then make your draw calls sending updated rotation, position, colour changes, fill gradient information as numeric paramaters to these draw calls. Once the draw calls send this small amount of updated information, the CPU then moves on to other things and lets the GPU handle clearing the surface, then processing the rasterisation of all imagery based on rotation, translation and scaling (based on new numeric values sent in draw calls). The GPU would also handle solid fills, gradient fills, pattern fills, copying bitmaps, scrolling bitmaps, scaling bitmaps, applying overlay effects to bitmaps (transparency, tinting etc), clipping, changing brush colors and many other things.There's a whole lot of CPU horsepower going on in a single GDI+ draw call and a lot of it is in rasterisation - which is basically lots and lots of memory manipulation as many bits are shuffled around to create bitmap imagery, lines and arcs etc in memory. All this would be handled by the GPU in a hardware accelerated world while the CPU gets on with other things such as further gauge logic processing and servicing the needs of other FSX system calls. Also, the more gauges you have in a cockpit, the greater the savings in rendering time as the sum of all the time spent rendering in a software-based rendering world is handled concurrently by the GPU.It's probably difficult to envision a CPU / GPU rendering pipeline from a software-based renderer perspective because of the concurrent nature of the processing between the CPU and GPU. In a software-based renderer, the CPU is processing the gauge logic and the rendering code in a linear fashion. Also, in a real-time graphics processing world involving CPU / GPU rendering pipeline you need to adjust your thinking into 'batching' your draw calls. This was a bit of an eye-opener for me when first encountering real-time hardware acclerated graphics, requiring quite a rethink in how often I called and where I had all my draw calls.This very aspect of draw calls and 'batching' is what the cool FSX service packs addressed and why applying the service packs drastically improves FSX framerates. I assume the dev team had discreet draw calls all over the place and have since made heavy use of batch rendering in the SP1 and 2 updates.After dipping into DirectX, getting a serious headache and then discovering the much easier to understand world of OpenGL, you soon realise the benefits of all this concurrent processing that hardware acceleration (which is bsaically offloading processing to the dedicated GPU) brings :)Ultimately we might be able to look forward to a much cleaner gauges.h file and better interaction between gauge code and the FSX engine that would allow easy seperation of suitable gauge logic into it's own thread, allowing it to be processed on seperate cores on multi-core CPUs. This would further spread the CPU load and in association with the GPU concurrently handling rendering loads, greater performance would be achieved for other FSX goodies such as higher levels of autogen, smoother terrain streaming, more complex weather, traffic and 'living world' processing etc.Things actually look quite good for a world of programming languages that provide mechanisms for programmers to easily utilise concurrency in this burgeoning world of multi-core processors. Implementing multiple threading and multi-core processing in your code today is frought with all manner of problems and synchronisation headaches, but Microsoft's next generation of updates for Visual Studio languages seem set to include powerful APIs that make all this multi-core programming really easy. Wether or not this will allow you gauge gurus to work this magic in the current confines of the FSX and gauge code system of interaction is another matter though, which is why I hope we will see efforts made to move away from the current manner in which the Flight Simulator SDK allows us to draw gauges in the next Flight Simulator iteration, and hardware accelerated gauge drawing needs to be a part of it :)
That's not a very valid test. Try the same with non-GDI+ gauges rendering the same amount of information (graphics wise). Not eliminate the panel entirely. That only tells you how much faster the sim runs without ANY gauges.
Ed's right, that's not a fair test. Again I wish I really knew enough about GDI+ to do some useful comparisons with other APIs like OpenGL, AGG etc :)

Share this post


Link to post
Share on other sites

'Concurrent programming'... um... it's called threading. Has been around for ages. Yeah, I know... there's a physical hardware difference... but on the software side... there really isn't.

Share this post


Link to post
Share on other sites
Here's an image of our 2D panel. Note the frame rates. Every gauge on the panel is a GDI+ gauge except the analog (standby) instruments.http://i107.photobucket.com/albums/m316/wa...framerate2d.jpgMy system is a P4 3.4ghz... so it's not a current system by any stretch of the imagination. :(
There's another side to the equation to keep in mind when we are talking about overall framerates, and that is the current level of detail of the FSX simulation settings you are happy with.It all depends on the importance each FSX simmer places on the balance between how things look, the quality of immersion of the simulated world and the responsiveness provided by the average framerate. I for one like detailed weather with volumetric clouds and decent levels of commercial and GA traffic, plus road traffic. I much prefer IFR style flying in 'tricky' weather. There's nothing like flying on instruments in the soup, flying an approach to minimums and breaking out of the clouds to find the runway all lined up nice in your GA aircraft - none of this automagic, button-pushing, dial-twisting jet business for me, no sir :)I'd love to get into more VFR flying but the processing costs of autogen or VFR-city style add-ons and real-world textures (preferably with night-textures support) and all at reasonable levels of detail to navigate accurately by, while maintaining my personal minimum of 30 fps do not seem doable at this time. At least not on my Athlon 64 FX-57, 4GB Ram, 2 x 400Gb SATA HDDs and GeForce 9800 GX2 system.Highly detailed add-on texture packs based on real-world aerial mapping imagery are not good enough for me, I also want to see sufficient details in the terrain height and other 3D object references like cities, towns and other landmarks.I'm probably severely CPU-bound with my single-core system, but I'm not sure whether even a 4-core processor would make accurate and realistic VFR in FSX at a steady 30 fps enjoyable for me. Probably time to upgrade and find out I guess :)Therefore the ability for gauge and aicraft add-ons to take as little a slice out of my base framerate, allowing enough CPU time for FSX to present a world detail that is acceptable to your own personal tastes is important.

Share this post


Link to post
Share on other sites

That image was in FS9 with all detail sliders to the right. All of them.There isn't a CPU setup today that likes FSX with all detail sliders to the right.

Share this post


Link to post
Share on other sites
'Concurrent programming'... um... it's called threading. Has been around for ages. Yeah, I know... there's a physical hardware difference... but on the software side... there really isn't.
Just because you slap something in a seperate thread does not mean it automatically runs on another core, thereby spreading the load intelligently. I'm highlighting the nature of concurrency, or to paraphrase you "um...threading" in the context of the growing surge of multiple cores appearing and achieving 'true' parrallel programming. I'm also pointing out how tricky it is for programmers to make full use of threading when you have shared data thrown into the mix. Which is why Microsoft's latest additions to the Visual Studio languages are exciting to me because they will make synhronisation headaches less painful.Threading may well have been around for ages but things really happening at the same time in different threads has been pure illusion until recently. Threading on a CPU in the past was not parallel, your code was being time-spliced with existing running code but ultimately all running one after the other. The CPU was simply running fast enough for it to appear concurrent. Things are changing now thanks to GPU's and multi-core CPUs

Share this post


Link to post
Share on other sites
That image was in FS9 with all detail sliders to the right. All of them.There isn't a CPU setup today that likes FSX with all detail sliders to the right.
Firstly those two paragraphs appear mutually exclusive to me given the fact that the 38 fps shown is a very acceptable figure to me. If you have all detail sliders to the right then how does that tally with the statement in your second paragraph?There's also the issue of just where you are in the world. Your screenshot is at night and you are on a runway so there's no indication of surrounding terrain complexity, texture quality, traffic levels, actual clouds being rendered as opposed to it just being a clear night etc. It all depends on what the simulator is currently handling at your given location and what is actually in view out of the cockpit. I too can have all sliders maxed if I'm flying in a very sparsley populated part of the UK, with clear weather, at a small default airport.What I look for is a performance from an add-on that will not send me dipping below my personal 30 fps minimum as soon as a reasonably detailed airport comes into view with AI planes and ground vehicles in view because it's taking a non-trivial slice from what I normally get.As I said, each of us has different levelks of acceptable simulation rates when in even the most detailed of surroundings but it's difficult to gauge the importance of that decent FPS figure in the screenshot when there appears to be very little going on in the view shown out the cockpit :)

Share this post


Link to post
Share on other sites

And yet... the requirements for safe threading are the same for safe multi-core.To implement a multi-core application... one takes advantage of using multiple threads. Microsoft may have changed their name... but the sheer nature of the beast is actually one and the same.I've been doing threading for years and years... so multi-core is no different to me. Thread-safe is core-safe.

Share this post


Link to post
Share on other sites