Stl: <mutex>: Improve call_once performance by using Init颅Once颅Begin颅Initialize / InitOnceComplete

Created on 14 Mar 2020  路  8Comments  路  Source: microsoft/STL

See Another pattern for using the InitOnce functions

The performance can be improved since callback is not passed to Windows API, so no exception pointer calls needed, only call InitOnceComplete in a destructor (of a local class).

Looks like ABI breaking change.

fixed performance

Most helpful comment

I'd worry about the mixing scenarios - what if a once_flag is used by both old and new TUs?

The contents and interpretation of once_flag don't change; both APIs take an INIT_ONCE. It would be possible for an "old" TU to call_once -> InitOnceExecuteOnce and a new TU to call_once -> InitOnceBeginInit/InitOnceComplete simultaneously.

XP would continue to be supported by the presence of _Execute_once in the redist until vNext.

All 8 comments

@BillyONeal, didn't we make this change in the super-secret massively bitrotted not-yet-public ABI breaking branch? I can't otherwise imagine why InitOnceBeginInitialize/InitOnceComplete would be familiar to me.

Correct, I had already done this. Since we made the determination that this would be ABI breaking though we've gotten the satellite DLL tech, so this could probably be done without an ABI break using that. We could certainly do it with an opt-in switch that says "I only care about Vista+" and call aliases for InitOnceXxx directly.

I'd worry about the mixing scenarios - what if a once_flag is used by both old and new TUs? (I also wouldn't want to see opt-in switches in the headers for XP targeting - we can now assume that XP is never targeted by the headers, we just have to continue supporting it in the redist.)

I'd worry about the mixing scenarios - what if a once_flag is used by both old and new TUs?

The contents and interpretation of once_flag don't change; both APIs take an INIT_ONCE. It would be possible for an "old" TU to call_once -> InitOnceExecuteOnce and a new TU to call_once -> InitOnceBeginInit/InitOnceComplete simultaneously.

XP would continue to be supported by the presence of _Execute_once in the redist until vNext.

What is the strategy if I see another more or less obvious ABI-breaking performance improvement?
Create an issue, or hold on with the assumption "this is probably already done"?

Please create an issue and note that it's ABI-breaking so we can tag it as vNext. We need to port things over by hand, so this will help make sure we don't forget anything critical.

It looks like the fallback spin thingy that __crtInitOnceExecuteOnce does instead of InitOnceExecuteOnce is stateless so I believe this can be done entirely in a satellite (or even the import lib), so I think it could be non-ABI-breaking with effort now that we have those techs.

The contents and interpretation of once_flag don't change; both APIs take an INIT_ONCE. It would be possible for an "old" TU to call_once -> InitOnceExecuteOnce and a new TU to call_once -> InitOnceBeginInit/InitOnceComplete simultaneously.

Unfortunately, I don't see the proof that callback API and API without a callback have the same interpretation of INIT_ONCE. Apparently, there's no such information in the documentation.

I've addressed it with MicrosoftDocs/win32#308 , now is documented here:
https://docs.microsoft.com/en-us/windows/win32/sync/one-time-initialization#synchronous-one-time-initialization

Was this page helpful?
0 / 5 - 0 ratings

Related issues

StephanTLavavej picture StephanTLavavej  路  10Comments

MahmoudGSaleh picture MahmoudGSaleh  路  20Comments

ohhmm picture ohhmm  路  16Comments

Andersama picture Andersama  路  16Comments

jonwil picture jonwil  路  24Comments