Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
161320 stories
·
33 followers

Announcing Microsoft Desired State Configuration v3.3.0

1 Share

We’re excited to announce the General Availability of Microsoft Desired State Configuration (DSC) v3.3.0. This release delivers three new built-in Windows resources, a new registry-backed adapter, expanded --what-if support, experimental export filtering, expression function updates, and Linux packages published to PMC.

For background on the DSC v3 platform, see:

For information on installing DSC v3.3, see the installation documentation.

What’s New in DSC v3.3

All these changes are driven by real-world use, partner feedback, and community contributions. Special thanks to the WinGet team and the incredible DSC community.

For a complete list of changes, see the release page on GitHub.

New built-in Windows resources

DSC v3.3 adds three new resources to the Microsoft.Windows namespace.

  • Microsoft.Windows/RegistryListManages an array of registry entries in a single resource instance, instead of requiring one Microsoft.Windows/Registry instance per key or value. The underlying registry.exe gained a --list switch to support it, the resource version moved to 1.1, and the registry manifests were consolidated into a single registry.dsc.manifests.json file.
  • Microsoft.Windows/WindowsFeatureListManages Windows features as a list, following the same list-oriented pattern.
  • Microsoft.Windows/PersonalizationManages Windows personalization settings, including accent color, light and dark mode, and transparency.

All three ship in the box. You can discover them, and inspect their schemas, with the DSC CLI:

dsc resource list 'Microsoft.Windows/*'
dsc resource schema --resource Microsoft.Windows/Personalization

New adapter: Microsoft.Windows.Adapter/Registry

v3.3 introduces Microsoft.Windows.Adapter/Registry, a registry-backed adapter that includes helpers for converting between JSON property values and their registry representations. This lets a resource express its desired state as ordinary JSON properties while the adapter handles the registry read and write.

NOTE

The conversion helpers currently cover the types needed by Microsoft.Windows/Personalization. We deliberately started narrow rather than guessing at a complete type mapping up front. We’ll add more conversions as real use cases surface. If you hit a registry type the adapter doesn’t handle, open an issue. That’s exactly the signal we’re looking for.

dsc mcp is now dsc server

The dsc mcp command is renamed to dsc server to better reflect usability. Many of the endpoints that are useful to MCP clients are also useful to integrating tools and provides a clean API for functionality that higher order tools can leverage. The mcp name is retained as a backward-compatible alias, so existing client configurations keep working.

dsc server

Three new tools are available to connected clients in v3.3:

  • show_dsc_schema() — returns the JSON schema for a DSC resource or type
  • invoke_dsc_function() — invokes a DSC built-in function
  • invoke_dsc_expression() — evaluates a DSC expression

Together these let a client inspect what a resource expects and evaluate configuration expressions without shelling out to the CLI.

format() is no longer experimental

The format() expression function graduates to stable in v3.3. It behaves the same as it did in preview, but the experimental warning is gone and you can rely on it in production configurations.

$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
  - name: Echo formatted message
    type: Microsoft.DSC.Debug/Echo
    properties:
      output: "[format('{0}/{1}', 'Microsoft.Windows', 'Personalization')]"

New expression functions: stateChanged() and restartRequired()

DSC v3.3 adds two new stable expression functions for reasoning about resource state within a configuration document:

  • stateChanged() – returns whether a resource instance changed state during the current set operation. The input must be the resource ID for another instance in a configuration, like stateChanged(resourceId('<resourceTypeName>', '<resourceInstanceName>')).
  • restartRequired() – returns whether a system, service, or process requires a restart. The input depends on which kind of restart you want to query:

    • restartRequired('system') – indicates whether the system itself requires a restart.
    • restartRequired('service', '<serviceName>') – indicates whether the specified service requires a restart.
    • restartRequired('process', '<processName>') – indicates whether the specified process requires a restart.

Expanded --what-if support

--what-if lets you preview what a set operation would change without modifying your system. In v3.3, three more resource areas support it.

  • Microsoft.Windows/Service
  • Microsoft.Windows/FirewallRuleList
  • The SSHD config resources

Preview a service change without applying it:

# service.dsc.config.yaml
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
  - name: Print Spooler
    type: Microsoft.Windows/Service
    properties:
      name: Spooler
      startType: Disabled
dsc config set --what-if --file ./service.dsc.config.yaml

DSC reports the state it would set, so you can review the change before committing to it.

Unspecified rules handling for Microsoft.Windows/FirewallRuleList

In this release of DSC, the Microsoft.Windows/FirewallRuleList resource added the unspecifiedRules property to control how DSC treats firewall rules you didn’t list in your configuration.

The unspecifiedRules property has three fields to provide more fine-grained control:

  • action (required) – indicates whether the resource should ignore, disable, or remove the rules.
  • direction (optional) – limits the action to Inbound or Outbound rules if specified. To apply the action to all unspecified rules regardless of direction omit this field.
  • profiles (optional) – limits the action to an array of specified profiles – Domain, Private, Public, or All.

The following snippet shows an instance of Microsoft.Windows/FirewallRuleList that disables every inbound rule for the Public profile:

# firewall.dsc.config.yaml
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
  - name: Firewall rules
    type: Microsoft.Windows/FirewallRuleList
    properties:
      rules: [] # Define no rules to apply to _all_ rules
      unspecifiedRules:
        action: disable
        direction: Inbound
        profiles: [Public]

Synthetic export filtering (experimental)

This feature is experimental in v3.3 and its syntax may change in a future release.

Starting with version 3.3.0, the DSC engine supports synthetic export filtering for resources that don’t directly implement filtering for instances in export operations.

In this release, resources can opt into letting the DSC engine filter the resources returned by the export operation by defining the export.supportsFiltering field in a resource manifest as false.

When a resource opts into using synthetic export:

  1. A user defines an input instance of the resource, defining one or more properties to filter the exported instances on.
  2. DSC invokes the export operation for the resource without passing the defined filtering properties from the resource instance.
  3. The resource emits the full list of instances to DSC.
  4. The DSC engine uses the defined properties in the resource instance to filter the emitted instances the resource returned.

The synthetic export filtering in this release has the following limitations:

  • The provided input for the instance must be an object where every property is a valid property name for the resource.
  • The value for every property in the input object must be one of:
    • A valid value for the property, which DSC uses for an exact match.
    • A string with at least one wildcard character (*), which DSC uses for a case-insensitive wildcard match.
  • When the property is defined in the resource schema as an object you can specify the subproperties as valid values or wildcard matching strings. DSC applies the filter through nested layers, enabling you to filter for deeply nested subproperties as well as top-level properties.
  • When the property is defined in the resource schema as an array you can specify one or more items. When you specify multiple items, DSC treats each item as a logical OR filter.
  • There is no builtin filtering behavior for more complex cases, like version range matching or minimum/maximum bounds for integer properties.

For example, the following snippet of a configuration document shows how you could export a subset of Windows services even though Microsoft.Windows/Service doesn’t implement export filtering:

# services.dsc.config.yaml
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
  # Only exports services where the startup type begins with `auto` and the logon account inludes
  # `local` in the account name
  - name: Automatically starting local account services
    type: Microsoft.Windows/Service
    properties:
      startType: Auto*
      logonAccount: '*Local*'
  # Only exports services that depend on `rpcss` or a service that starts with `w`
  - name: Services depending on RpcSs or a service that starts with w
    type: Microsoft.Windows/Service
    properties:
      dependencies:
        - RpcSs
        - w*
  # Only exports services where the following are all true:
  # - the startup type begins with `auto`
  # - the logon account inludes `local` in the account name
  # - the service depends on `rpcss` or a service that starts with `w`
  - name: Combined service filter
    type: Microsoft.Windows/Service
    properties:
      startType: Auto*
      logonAccount: '*Local*'
      dependencies:
        - RpcSs
        - w*

--required-version replaces --version

The dsc resource * commands now take --required-version instead of --version. The old flag is retained as a backward-compatible alias.

The rename better reflects the semantics and usage for the parameter. The previous name, --version, implied an exact match for a specific version instead of a version requirement, which is how DSC actually parses and uses the parameter value. You can specify Rust-like semantic version requirements, like ^1.1, ~1.2.3, and >=1.

dsc resource schema --resource Microsoft.Windows/RegistryList --required-version '^1.1.0'

Microsoft/OSInfo version comparison

Microsoft/OSInfo now supports version comparison, so a configuration can assert a version constraint on the OS rather than matching an exact value. Starting with this release, you can specify the version field with a comparison operator followed by a full or partial version, like >10.1. The available comparators are:

  • Equal to (=) – this is the default comparator, requiring an exact match for the text that follows the comparator.
  • Less than (<)
  • Less than or equal to (<=)
  • Greater than (>)
  • Greater than or equal to (>=)

You can only specify a single comparator for the version. You can’t combine them in a single instance to define a version range. When you specify a comparator other than the equal to comparator (=), you can specify a partial version to match. For example, if you define the version as > 10 the instance will be valid for any operating system versions like 10.0.1 and 11.3.7.

The comparison works for versions that include non-digit segments but the version must start with a digit.

Linux packages on PMC

DSC v3.3 is published to the https://packages.microsoft.com (PMC) for Linux as both RPM and DEB packages. You can now install and update DSC through your distribution’s package manager instead of downloading a tarball from GitHub releases.

Community contributions

This release leaned heavily on the community, and we’re grateful for it.

@Gijsreyn (Gijs Reijn) was the standout contributor this cycle. Gijs contributed Microsoft.Windows/WindowsFeatureList, --what-if support for Microsoft.Windows/Service, Microsoft.Windows/FirewallRuleList, and the SSHD config resources, experimental export filtering, the graduation of format() out of experimental, category and description filters for the function list, and a large amount of documentation work. Thank you, Gijs.

@JohnMcPMS (Winget team) contributed a fix for stdin being inherited by child processes when no input was provided.

@Alex-shearing contributed documentation fixes and documentation for previously undocumented functions.

@ThomasNieto (Thomas Nieto) added dev container support to the repository, making it easier to get a working DSC build environment.

Looking ahead

We’ll keep iterating on the platform based on what you tell us — real configurations, real adapters, and real bug reports shape what we build next. Watch the DSC repository for what’s in flight.

Call to action

Install DSC v3.3.0, try the new Windows resources, and run --what-if against a configuration before you apply it. If you find a bug, hit a gap in the registry adapter’s type conversions, or have feedback on experimental export filtering, open an issue in the DSC repository. Community feedback is what drove this release, and it’s what will drive the next one.

The post Announcing Microsoft Desired State Configuration v3.3.0 appeared first on PowerShell Team.

Read the whole story
alvinashcraft
40 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

NVidia Introduces CUDA GPU Programming In Rust

1 Share
Read the whole story
alvinashcraft
53 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

AI Coding Standards and Repeatable Workflows

1 Share

Keep AI-generated code consistent across tools with repository instructions, continuous integration checks and pull-request evidence before every merge.

Two pull requests reach the same service. Both are formatted, neatly summarized and passing tests. One used Cursor; the other, Claude Code. Yet your review process cannot show whether either change followed your architecture rules, reused approved helpers or proved the behavior it changed. A clean-looking pull request now hides the work your reviewers still need to verify.

Choosing one approved coding agent may look like the easiest way to restore consistency, but the approved tool will change. Don’t try to control which AI coding tool developers use. Control what every code change is expected to demonstrate before it can be merged.

Your coding standard has to survive the next agent. The useful question is what your review process can prove before merge. The tool can change. The receipt cannot.

What Your Review Process Was Actually Measuring

Your reviewers once relied on informal signals. Sloppy formatting suggested a rushed change. A 900-line diff with no tests suggested weak scope control. A focused change in your team’s usual style suggested care.

Formatting was a proxy for effort, a focused diff was a proxy for scope control and tests were a proxy for the developer understanding the change. The signals were imperfect, but reviewers knew how to price them in.

AI-generated code breaks the link between polish and care. Polish is no longer a useful indicator of quality. AI can make bad decisions look polished. An agent can produce formatted, confident code that still calls the wrong API, duplicates an existing helper or misses an edge case. A polished diff now tells your reviewers little about whether the underlying choices are sound.

The loss of trust already appears in developer surveys. Stack Overflow’s 2025 developer survey found that 84% of developers use or plan to use AI tools, while 46% distrust the results. Another 45% say debugging AI-generated code takes more time. The survey leaves your review team with an awkward combination of widespread use, low trust and reported debugging overhead.

The Bill Shows Up in Next Year’s Roadmap

Your team sees extra debugging first. Review comments, incidents and rework accumulate when plausible-looking AI-generated code mishandles an edge case or invents an API.

Maintainability debt reaches your roadmap more quietly. Near-matching helpers, copied business rules and one-off implementations make the next change harder.

Your version-control history offers one way to spot maintainability debt. “Moved code” is existing logic that a developer relocates during refactoring instead of duplicating. GitClear’s maintainability research, based on 623 million changes, reports that moved code fell from 21% of changed lines in 2022 to 3.8% so far in 2026, while copy-pasted code rose to 15.7%.

Your velocity dashboard can show that more code shipped while missing the consolidation work that disappeared. AI can increase short-term development speed while quietly increasing long-term maintenance costs.

Five copies of a pricing rule look productive until the rule changes and a developer updates only three. The missing copies turn yesterday’s output into tomorrow’s production incident. Every hour spent tracing those copies comes out of the capacity assigned to next year’s roadmap.

Write the Standard Where the Agents Will Read It

The debugging and duplication problems share one missing control. Your repository does not tell coding agents what “good work” means for the codebase. Useful instructions name the required commands, module boundaries, approved helpers, protected files and review evidence.

Put those instructions in an AGENTS.md file at your repository root. Compatible coding agents then get a predictable place to find repository-specific guidance.

Across your repository fleet, let the platform team own a version-controlled AGENTS.md template for shared security rules, dependency policy and required evidence. Each service team adds local commands, ownership boundaries and architecture rules in its repository copy.

Give each repository’s AGENTS.md a named owner who removes outdated rules as well as adding new ones. Use one placement rule. AGENTS.md holds guidance an agent must interpret; continuous integration (CI) checks hold rules a machine can enforce.

Keep only these items in AGENTS.md.

  • The exact build, test and lint commands that CI checks run.
  • Local decisions an agent would otherwise guess, such as which module owns persistence or which shared utility already solves a problem.
  • Files the agent cannot change without approval, such as generated clients, vendored dependencies, migrations and permission checks.

Three Layers of AI Standard Controls: AGENTS.md, CI Checks, Pull Request Evidence

Let CI Checks Enforce What Prose Can Only Request

Repository instructions guide an agent, but written guidance cannot guarantee compliance. A sentence in AGENTS.md can be misunderstood or ignored. A required CI check can block the merge.

Your CI checks should enforce formatting, strict type checks, tests, changed-lines coverage, dependency allowlists and security scans.

Coverage needs one additional safeguard because an agent can raise the number without proving behavior. Require every meaningful new test to fail against the pre-change code. A pre-change failure gives reviewers evidence that the test exercises changed behavior; reviewers still need to confirm the intended reason for the failure.

Keep the CI evidence after merge because your auditors need it too. NIST’s Secure Software Development Framework organizes secure development into practices, tasks and implementation examples. Test reports, scan results and build artifacts give your auditors timestamped records; a reminder to be careful does not.

Make the Pull Request Carry Its Own Proof

CI checks catch configured rules, but many architecture-fit questions remain reviewer judgments. Polish no longer proves careful work.

Security testing shows the gap between polish and proof. Veracode’s spring 2026 code security update reports that AI coding assistants exceeded 95% syntax correctness while only about 55% of generated samples passed security testing. Code can look finished without being sound.

Because CI checks cannot encode every architecture decision, your pull-request template should require evidence for the remaining judgments.

  • Scope. Connect the diff to the ticket and identify unrelated changes.
  • Source evidence. Link the documentation or internal standard used for new dependencies, unfamiliar SDK calls and security-sensitive patterns.
  • Interfaces. Name any change to a public API, database schema, event schema or permission model, along with the migration or approval record.
  • Execution evidence. Attach test output, build logs, scan results, migration logs and screenshots for UI changes.

An AI-written description saying all tests pass is only a claim. When the execution evidence is missing, return the pull request before reviewing the diff.

The Objection, and Where to Start

The strongest objection to repository instructions, CI checks and pull-request evidence is process weight. Safeguards that turn a five-minute change into an hour of gate-clearing invite people to bypass them.

Keep the process light by putting each control in the right place. CI checks own deterministic rules, AGENTS.md owns repository-specific guidance and the pull-request template owns required proof. Human reviewers can then focus on two questions. Does the change fit the architecture, and was the ticket the right change to make?

Start with your highest-traffic repository. Record the rules your reviewers already enforce, move three repeated review comments into CI checks and add evidence fields to the pull-request template. Run the process for two sprints before expanding to another repository.

As you expand the rollout, the instruction format must outlive the current agent. The AGENTS.md format is now stewarded by the Linux Foundation’s Agentic AI Foundation. A durable standard is a system every tool has to survive.


Learn About Progress Forge Orchestration

If you’re ready to move from isolated AI coding tasks to repeatable engineering workflows, Progress Forge (formerly Progress Agent Harness) is designed for exactly that shift. It orchestrates the AI coding agents your team already uses through structured workflows with visibility, governance and human review built in.

Explore the Progress Forge Early Access Program to see how it can help you put these ideas into practice.

Request a Demo

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

std::call_once vs. std::async

1 Share

Last time, we compared magic statics with std::call_once and concluded that std::call_once lets you construct magic statics-like behavior for non-static variables.

But there is also std::async for delayed execution. Can we use that instead?

The idea here is that you tell std::async that you want it to defer execution of something (say, a lambda). It returns a std::future representing that deferred execution.

auto f = std::async(std::launch::deferred, ⟦ lambda ⟧);

At some later point, you can ask for the deferred execution to execute and retrieve the result.

auto value = future.get();

There are a few catches here.

To permit getting non-copyable types, getting the value is a destructive operation: You are allowed to call get() only once, and subsequent calls result in undefined behavior. This is a problem for the case where you ask for the value multiple times, but you can fix it by converting the std::future to a std::shared_future:

auto f = std::async(std::launch::deferred, ⟦ lambda ⟧).share();

When you call get() on a shared_future, it gives you a const reference to the cached value and retains the cached value for future calls. The shared_future::get() method is marked const, which in the C++ standard library means that it is thread-safe with respect to itself and other const members. Therefore, you can call get() as many times as you like, and the first will run the lambda and return the result, and the others will return the already-calculated result.

Okay, so our Gadget class can look like this:

class Gadget
{
public:
    Gadget(std::shared_ptr<Widget> const& widget) : widget(widget) {}

    bool can_reverse_polarity()
    {
        return can_reverse_polarity_future.get();
    }

private:
    std::shared_ptr<Widget> const widget;
    std::shared_future<bool> const can_reverse_polarity_future =
        std::async(std::launch::deferred,
            [=] {
                return is_configuration_enabled("polarity_reversal") &&
                is_widget_polarity_reversible(*widget);
            }).share();
};

So why choose one over the other?

Well, std::call_once is very small. Visual Studio builds it out of the Win32 INIT_ONCE, which is the size of a pointer.¹

On the other hand std::future and std::shared_future involve a heap allocation to manage the shared state, as well to store the invocable and its parameters, and the result. Also, since std::async supports other modes of execution, you pull in code to support those other modes that you might even be using. (For example, it has to worry about the possibility that you pass std::launch::async, so it links in the thread library, as well as other machinery to support wait_for.)

But a significant difference between them has to do with their exception behavior, which we haven’t even talked about yet.

We’ll do that next time.

¹ I can’t find what gcc builds it out of, but an old implementation I found just builds it manually with many defects. Just a quick look at it shows that it is not exception-safe and suffers from data races. The code appears to have moved around, but it’s still intact. It seems that the lack of exception safety is called out with a todo-like comment. The data race is addressed by a comment saying that the processor implicitly makes all loads acquire and all stores release, and while that may be true, it doesn’t prevent the compiler from reordering the stores and loads. The compiler might decide to inline the callback and then reorder the stores so that the store to done happens before the end of the callback.

The post <CODE>std::call_once</CODE> vs. <CODE>std::async</CODE> appeared first on The Old New Thing.

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

Magic statics vs. std::call_once

1 Share

Suppose you have some function like

bool should_use_widgets()
{
    bool supported = ⟦ complex code to check OS features ⟧;
    return supported && is_configuration_enabled("widgets");
}

Since OS Widget support is not something that changes during the lifetime of the program, you want to calculate it once and cache the result.

One way is to use a so-called “magic static”:

bool should_use_widgets()
{
    static const bool supported = [] {
        return ⟦ complex code to check OS features ⟧;
    }();
    return supported && is_configuration_enabled("widgets");
}

Function-local statics are initialized the first time execution reaches the variable. On subsequent executions, nothing happens.

Another way is to use std::call_once.

bool is_supported_cached;
std::once_flag is_supported_once;

bool are_widgets_supported()
{
    std::call_once(is_supported_once, [] {
        is_supported_cached = ⟦ complex code to check OS features ⟧;
    });
    return is_supported_cached && is_configuration_enabled("widgets");
}

Why would you choose one over the other?

Magic statics are certainly more convenient. You don’t have to juggle two variables. You just declare a function-local static and initialize it. One problem is that they have to be a function-local static. Multiple functions can’t access that same cached variable. But that’s easy to work around: Have a function whose sole job is to manage that one static.

bool are_widgets_supported_in_os()
{
    static const bool supported = [] {
        return ⟦ complex code to check OS features ⟧;
    }();
    return supported;
}

bool are_widgets_supported()
{
    return are_widgets_supported_in_os() &&
        is_configuration_enabled("widgets");
}

bool are_widget_carriers_supported()
{
    return are_widgets_supported_in_os() &&
        is_configuration_enabled("widget_carriers");
}

This trick is often used for singleton patterns.

class Singleton
{
public:
    static Singleton& GetInstance()
    {
        static Singleton instance;
        return instance;
    }

    ⟦ various methods go here ⟧;

private:
    Singleton() = default;
    Singleton(Singleton const&) = delete;
    Singleton& operator=(Singleton const&) = delete;
    ~Singleton() = default;
}

So when would you use call_once?

Magic statics work only for statics. Maybe you want to lazy-initialize a non-static data member.

Suppose we have a Gadget that is constructed with an associated Widget. And suppose that the Gadget support for polarity reversal is dependent on whether the Widget supports polarity reversal. Furthermore, polarity reversibility is expensive to calculate, but since it is an immutable property, we can calculate it only once and cache the result.

class Gadget
{
public:
    Gadget(std::shared_ptr<Widget> const& widget) : widget(widget) {}

    bool can_reverse_polarity()
    {
        return can_reverse_polarity_cached;
    }

private:
    std::shared_ptr<Widget> const widget;
    bool can_reverse_polarity_cached =
        is_configuration_enabled("polarity_reversal") &&
        is_widget_polarity_reversible(*widget);
};

The can_reverse_polarity_cached is a non-static data member with an explicit initializer, so it initializes at the construction of the Gadget class, rather than initializing on demand the first time somebody calls can_reverse_polarity.

“No problem,” you say. “I can use a magic static.”

    bool can_reverse_polarity()
    {
        static bool can_reverse_polarity_cached =           
            is_configuration_enabled("polarity_reversal") &&
            is_widget_polarity_reversible(*widget);         

        return can_reverse_polarity_cached;
    }

Function-static variables in a member function are static with respect to the member function. All instances of Gadget share the same member function, and therefore they all share the same can_reverse_polarity_cached variable. The time you call Gadget::can_reverse_polarity(), it calculates the reversibility of the Widget that is associated with the Gadget you called it from, and that value is then locked in for all future calls to Gadget::can_reverse_polarity(), even though the future calls may be on unrelated Gadgets.

What we want is a variant of magic statics that initialize for each instance of the class, rather than once for all instances.

That’s the case for std::call_once.

class Gadget
{
public:
    Gadget(std::shared_ptr<Widget> const& widget) : widget(widget) {}

    bool can_reverse_polarity()
    {
        std::call_once(can_reverse_polarity_once, [] {          
            can_reverse_polarity_cached =                       
                is_configuration_enabled("polarity_reversal") &&
                is_widget_polarity_reversible(*widget);         
        });                                                     
        return can_reverse_polarity_cached;
    }

private:
    std::shared_ptr<Widget> const widget;
    bool can_reverse_polarity_cached; // initializes on demand
    std::once_flag can_reverse_polarity_once;                 
};

I guess you could encapsulate this in a lazy<T> type.¹

template<typename T, typename L>
struct lazy
{
    lazy(L&& l) : init(std::forward<L>(l)) {}

    T& get() {
        std::call_once(once, [&] {
            value.emplace(init());
        });
        return *value;
    }
private:
    std::optional<T> value;
    std::once_flag once;
    std::decay_t<L> init;
};

template<typename T, typename L>
lazy<T, L> make_lazy(L&& l)
{
    return { std::forward<L>(l) };
}

void test()
{
    auto v = make_lazy<int>([] {
        printf("Slow calculation\n");
        return 42;
    });

    printf("Value is %d\n", v.get());
    printf("Value is still %d\n", v.get());
}

But wait, we also have std::async with deferred execution. Should we use that? We’ll look at this question next time.

¹ Note that this is not the same as the std::lazy proposal.

The post Magic statics vs. <CODE>std::call_once</CODE> appeared first on The Old New Thing.

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

Why are short videos bad for learning?

1 Share
Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories