What happens to my old request if I reuse a `RequestID`

The documentation mentions “overwriting” the old request, but does this imply any subscriptions are cancelled? For example, if I request data to be returned every second or frame, then repurpose the same RequestID for a RequestSystemState, will the object data stop coming in?

I understand the confusion I’m causing for my own app is bad, but “overwriting” kind of implies the SimConnect library is not doing any “is already in use” sanity checks.

The samples generally use #defines, which we should have stopped using as soon as constexpr entered the language, or enums, which implies a very static and simple application.

I solved this in the current version of CsSimConnect by never reusing any RequestIDs, but there is likely a limit on how many requests SimConnect can keep track of, and a long-running app could end up using very high numbers that way.

Don’t reuse IDs and don’t overthink it. You get over 4 billion unique IDs out of an int.

If you no longer need some data you subscribed to, unsubscribe from it.

If you want to change a data subscription, pause it first, then change, then start it again.

These are some tips for a happy SimConnect experience.

Sure, if you request 4 million data points at once from SimConnect it will probably hate you. Don’t do that.

An ID can be any int. It doesn’t have to be hard-coded by any means. For C# SimConnect the IDs do need to be cast to Enum type, but this is just a cast. Use a “dummy” Enum type and cast to that (or any enum you happen to have already). The IDs can be generated dynamically, though obviously you need to keep track of what each ID corresponds to on your end so you can correlate with what SimConnect sends back.

Cheers,
-Max

1 Like

PS. CsSimConnect uses polling and waiting inside a loop to get messages from SimConnect. Bleh. Also strange that it chooses to use its own interface to the C++ SimConnect instead of using the official Managed/.NET version. Lastly the opening statement claims one needs a Window handle to use SimConnect, which is not true.

Hey Max, thank you for your response. The most important reason I asked is that there is mention of reusing RequestIDs, so it is apparently something that is being done. If the idea is bad, the documentation should instead say that. I do not know how SimConnect (or the simulator) keeps track of requests, events, or other things-with-ids.

Yes, CsSimConnect uses polling, because I am not an experienced Win32 API user. For me an “Event” is a message relating to something that has happened, not a condition variable. That is why I never looked at it until recently. My bad.

I am unsure which opening statement you are referring to. There are three “modes” of operation for SimConnect:

  1. If you pass a Window handle (type HWND) and an optional message ID, typically WM_USER plus something, SimConnect will use Windows messages with that ID to signal that SimConnect messages are waiting.
  2. If you pass that Windows Event Handle (type HANDLE), SimConnect will use that to signal the availability of messages instead.
  3. If you pass two nullptrs (and a zero for the message ID), SimConnect expects you to poll.

I would have hoped an std::condition_variable would be used instead, making us less dependent on Win32.

Hi,

Sorry, where or in what context is this mentioned? Also there may be confusion about request ID vs. definition ID… when requesting single variables then they’re essentially equivalent, but with structs it may (or may not) matter to the implementation.

You’re right, sorry, it actually says “not using old programming models with Windows handles and such.” It is a very common misconception that in order to avoid polling for messages a Window handle is required…

But you already knew that it is not! :+1:

It’s a C interface… :slight_smile: Also Win32 is required all down the line anyway and it’s not like this is meant to be cross-platform (which is a separate discussion… and one where an abstraction layer between client and SimConnect actually makes sense, IMHO).

Cheers,
-Max

Sorry, where or in what context is this mentioned? Also there may be confusion about request ID vs. definition ID… when requesting single variables then they’re essentially equivalent, but with structs it may (or may not) matter to the implementation.

See the discussion here.

It’s a C interface… :slight_smile: Also Win32 is required all down the line anyway and it’s not like this is meant to be cross-platform (which is a separate discussion… and one where an abstraction layer between client and SimConnect actually makes sense, IMHO).

Well, since we’re not in the realm of device drivers or microcontrollers, there should be no valid reason for sticking with C. Even NVidia moved to Rust and improved the stability of their firmware.

C++ conferences will teach you that C++ does not require you to accept additional overhead for the increased benefit of templates and smart pointers (Repeat after me: “No more void* parameters!”) and proper and ensured cleanup. Using #define for constants isn’t even required in C anymore, because there’s constexpr. Using it to shorthand (well, longhand actually) typedefs is weird. The only reason I could think up for that is that someone is generating the “SimConnect.h” files for both C and C# from the same source, but didn’t want to touch the generator.

In the SIMCONNECT_EXCEPTION enumeration, SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS is explained as:

Specifies that the maximum number of requests allowed has been reached. The maximum is 1000.

Does this refer to the number of currently active Requests or does this put an actual limit on the value of a RequestID?

At least in FSX, the limit was on the number of currently outstanding requests; the only requirement was that a given request ID had to unique relative to any outstanding requests.

Anecdotally, in Asobo’s MSFS (2020) and MSFS 2024, I’ve used non-sequential request ID values (and request ID values larger than 1000) and it’s worked fine.

1 Like

C linkage is the defacto industry standard for language interop. There is not yet a good solution to link C++ symbols with rust for example (there are active efforts like autocxx on this front, but there are still many problems in practice). Exposing C++ symbols in the public API would make it much more difficult to use other languages like rust and C. Well… there’s also the issue that C++ name mangling is not even standardised, so varies between compilers.

C linkage is the defacto industry standard for language interop. There is not yet a good solution to link C++ symbols with rust for example (there are active efforts like autocxx on this front, but there are still many problems in practice). Exposing C++ symbols in the public API would make it much more difficult to use other languages like rust and C. Well… there’s also the issue that C++ name mangling is not even standardised, so varies between compilers.

I wouldn’t be terribly opposed to a Rust API, as it might help to get rid of all those unsafe void pointers, but actually the SimConnect API already is using C++, as the SIMCONNECT_RECV structs are using inheritance. One question Rust would certainly answer well is who owns the message in the DispatchProc vs after a call to GetNextDispatch. In the first case I would expect the SimConnect library to own it, but in the second case? If still SimConnect, when will it free the memory? Or if a static buffer, when will it be overwritten?

I’m slowly building a “real” C++ API as part of my current exercises. Not always easy, but that is because of the single-threadedness of SimConnect.

We do have some rust bindings GitHub - flybywiresim/msfs-rs: A Rusty way to interact with Microsoft Flight Simulator 2020