惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LangChain Blog
N
Netflix TechBlog - Medium
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Blog — PlanetScale
Blog — PlanetScale
Microsoft Security Blog
Microsoft Security Blog
D
Docker
WordPress大学
WordPress大学
罗磊的独立博客
J
Java Code Geeks
博客园 - 【当耐特】
博客园 - 司徒正美
雷峰网
雷峰网
H
Help Net Security
酷 壳 – CoolShell
酷 壳 – CoolShell
Last Week in AI
Last Week in AI
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
T
Tailwind CSS Blog
Google DeepMind News
Google DeepMind News
M
MIT News - Artificial intelligence
Recent Announcements
Recent Announcements
B
Blog

The Old New Thing

Why do Microsoft job levels start in the high 50's instead of starting at a sane number like 1? - The Old New Thing Why didn't Read­Directory­ChangesW provide a way to correlate the two sides of a rename operation? - The Old New Thing How can I remove the Close button from my window caption? - The Old New Thing Why is the x86 undefined instruction called ud2? Why 2? - The Old New Thing What algorithm did Windows XP use to choose your initial user picture? - The Old New Thing A sample use of the winstart.bat file in Windows 95 - The Old New Thing Why don't we allow stacks to be sparse, instead of forcing them to be contiguous? - The Old New Thing What happens if you change a window class's GCL_CB­WND­EXTRA? - The Old New Thing The case of the progress callback that never got called when progress happened - The Old New Thing The perils of binding to value types in XAML - The Old New Thing Microspeak: Funded / unfunded - The Old New Thing AWE does not require PAE, though PAE makes it much more useful - The Old New Thing On forcing all derived classes to implement a specific non-virtual method, part 2 - The Old New Thing On forcing all derived classes to implement a specific non-virtual method, part 1 - The Old New Thing In the product end game, every change carries significant risk, episode 2 - The Old New Thing Why didn't the Windows Entertainment Pack just run the MS-DOS version inside an emulator? - The Old New Thing Comparing the two holograms on the Windows 95 box - The Old New Thing Reducing C++ template bloat by factoring out the type-dependent portions of the function, practical exam - The Old New Thing Reducing C++ template bloat by factoring out the type-dependent portions of the function - The Old New Thing On wrapping a callable in a lambda that just calls it with the same parameters - The Old New Thing Why did the Microsoft Entertainment Pack for Windows have a special sticker announcing that it also had Tetris? - The Old New Thing How do functions like alloca allocate memory from the stack? - The Old New Thing How do functions like alloca allocate memory from the stack? - The Old New Thing Forcing an ARM64X executable to run as a specific architecture - The Old New Thing A little helper class for managing LPPROC_THREAD_ATTRIBUTE_LISTs - The Old New Thing The comments that go into code versus those that go into the pull request description - The Old New Thing The little-known winstart.bat batch file - The Old New Thing How can I perform a Copy­File&shy in unbuffered mode? - The Old New Thing Creating a fake agile wrapper that is technically agile but is not useful outside its home apartment, part 5 - The Old New Thing Creating a fake agile wrapper that is technically agile but is not useful outside its home apartment, part 4 - The Old New Thing
Sharing the result of a single Windows Runtime IAsyncOper...
Raymond Chen · 2026-05-28 · via The Old New Thing

Last time, we tried to write a coroutine function that cached the result of another coroutine, but our first attempt had lots of problems.

It turns out that you can do it much more simply, and simpler code means fewer places you can mess up.

struct Widget : WidgetT<Widget>
{
    std::optional<winrt::Thing> m_thing;
    wil::unique_event m_busy{ wil::EventOptions::Signaled }; // auto-reset, initially signaled

    IAsyncOperation<winrt::Thing> GetThingAsync()
    {
        auto lifetime = get_strong();

        co_await winrt::resume_on_signal(m_busy.get());
        auto not_busy = m_busy.SetEvent_scope_exit();

        // If we don't have a thing, try to get one.
        if (!m_thing) {
            m_thing = co_await GetThingWorkerAsync();
        }

        co_return *m_thing;
    }
};

We use an auto-reset event to serialize access to the function, remembering to set the event when control leaves the function so that the next caller can try.

Each time we try, we see if we have an answer already. If not, then we try to get the answer. If it fails, then we propagate the exception and m_thing remains empty. Otherwise, we save the answer into m_thing. Regardless of whether we have a cached answer or a fresh answer, we return it. (We can use the * operator because we know that the m_thing contains a value: If it didn’t, we would have attempted to get the value, and if the attempt failed, we would have thrown.)

The above code is careful to accommodate the case that GetThingWorkerAsync succeeds and produces nullptr, using the std::optional‘s empty state as a “no value yet” sentinel. If you know that GetThingWorkerAsync cannot succeed with nullptr, then you can get rid of the std::optional and let nullptr represent the empty state.

struct Widget : WidgetT<Widget>
{
    winrt::Thing m_thing{ nullptr };
    wil::unique_event m_busy{ wil::EventOptions::Signaled }; // auto-reset, initially signaled

    IAsyncOperation<winrt::Thing> GetThingAsync()
    {
        auto lifetime = get_strong();

        co_await winrt::resume_on_signal(m_busy.get());
        auto not_busy = m_busy.SetEvent_scope_exit();

        // If we don't have a thing, try to get one.
        if (!m_thing) {
            m_thing = co_await GetThingWorkerAsync();
            assert(m_thing);
        }

        co_return m_thing;
    }
};

Next time, we’ll come up with a version that tries only once rather than trying until it succeeds.

Category

Topics

Author

Raymond Chen

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.