Skip to content

Conversation

@edolstra
Copy link
Member

@edolstra edolstra commented May 5, 2025

Motivation

Use Meyer's singleton pattern in our various registration classes, as suggested by @xokdvium (#13138 (comment)).

Context


Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@github-actions github-actions bot added new-cli Relating to the "nix" command store Issues and pull requests concerning the Nix store fetching Networking with the outside (non-Nix) world, input locking labels May 5, 2025
Copy link
Contributor

@xokdvium xokdvium left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Diff LGTM

@xokdvium
Copy link
Contributor

xokdvium commented May 5, 2025

@edolstra Formatter is not happy :(

@Mic92 Mic92 force-pushed the singleton-pattern branch from d33cbba to 47989a2 Compare May 5, 2025 07:42
@Mic92 Mic92 enabled auto-merge May 5, 2025 07:42
@Mic92
Copy link
Member

Mic92 commented May 5, 2025

Looks like this made initialization of classes somehow more lazy so they are no longer initialized in the manual generation.

nix-manual> 5 │ There are [multiple types of Nix stores](./types/index.md) with different capabilities, such as the default one on the [local filesystem](./types/local-store.md) (`/nix/store`) or [binary caches](./types/http-binary-cache-store.md).
nix-manual>   │                                                                                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File not found: ./types/local-store.md
nix-manual> 
nix-manual> error: File not found: ./types/http-binary-cache-store.md
nix-manual>   ┌─ store/index.md:5:181
nix-manual>   │
nix-manual> 5 │ There are [multiple types of Nix stores](./types/index.md) with different capabilities, such as the default one on the [local filesystem](./types/local-store.md) (`/nix/store`) or [binary caches](./types/http-binary-cache-store.md).
nix-manual>   │                                                                                                                                                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File not found: ./types/http-binary-cache-store.md
nix-manual> 
nix-manual> error: File not found: ./local-store.md
nix-manual>    ┌─ store/types/index.md:32:11
nix-manual>    │
nix-manual> 32 │ * Use the [local store](./local-store.md) `/nix/store` if `/nix/var/nix`
nix-manual>    │           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File not found: ./local-store.md
nix-manual> 
nix-manual> error: File not found: ./local-daemon-store.md
nix-manual>    ┌─ store/types/index.md:35:61
nix-manual>    │
nix-manual> 35 │   * Otherwise, if `/nix/var/nix/daemon-socket/socket` exists, [connect
nix-manual>    │ ╭─────────────────────────────────────────────────────────────^
nix-manual> 36 │ │   to the Nix daemon listening on that socket](./local-daemon-store.md).
nix-manual>    │ ╰──────────────────────────────────────────────────────────────────────^ File not found: ./local-daemon-store.md
nix-manual> 
nix-manual> error: File not found: ./local-store.md
nix-manual>    ┌─ store/types/index.md:38:37
nix-manual>    │
nix-manual> 38 │ * Otherwise, on Linux only, use the [local chroot store](./local-store.md)
nix-manual>    │                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File not found: ./local-store.md
nix-manual> 
nix-manual> error: File not found: ./local-store.md
nix-manual>    ┌─ store/types/index.md:42:22
nix-manual>    │
nix-manual> 42 │ * Otherwise, use the [local store](./local-store.md) `/nix/store`.
nix-manual>    │                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File not found: ./local-store.md
nix-manual> 
nix-manual> error: File not found: ../../store/types/ssh-store.md
nix-manual>     ┌─ command-ref/nix-store/import.md:460:29
nix-manual>     │
nix-manual> 460 │ > Import the closure into a [remote SSH store](../../store/types/ssh-store.md) using the [`--store`](../../command-ref/conf-file.md#conf-store) option:
nix-manual>     │                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File not found: ../../store/types/ssh-store.md
nix-manual> 
nix-manual> error: File not found: ../store/types/local-store.html
nix-manual>     ┌─ command-ref/conf-file.md:513:127
nix-manual>     │
nix-manual> 513 │   > If you can’t or don’t want to configure `root` to be able to access the remote machine, set [`store`](#conf-store) to any [local store](../store/types/local-store.html), e.g. by passing `--store /tmp` to the command on the local machine.
nix-manual>     │                                                                                                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File not found: ../store/types/local-store.html

Overall it seems useful if this makes the loading order more deterministic but we need to fix the manual then.

Copy link
Member

@roberth roberth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how this is a simplification, because it still relies on the mutation of globals, and the amount of code seems to be about the same.
Feel free to go ahead though, assuming it's an incremental improvement. (if the other comments can be addressed)

@Ericson2314
Copy link
Member

Yes the end state has to be no globals, but from a quick glance this does feel to me like an improvement.

@edolstra
Copy link
Member Author

edolstra commented May 6, 2025

I don't see how this is a simplification

It's a simplification because it replaces

static Commands * commands;
...
RegisterCommand::Commands * RegisterCommand::commands = nullptr;
...
if (!commands)
    commands = new Commands;

(i.e. 3 different sites and a conditional), with just

static Commands & commands()
{
    static Commands commands;
    return commands;
}

@Mic92 Mic92 merged commit 10358c6 into master May 6, 2025
25 checks passed
@Mic92 Mic92 deleted the singleton-pattern branch May 6, 2025 07:31
@Mic92
Copy link
Member

Mic92 commented May 6, 2025

Yes the end state has to be no globals, but from a quick glance this does feel to me like an improvement.

Afaik it provides more thread-safety during initialization and we have to deal with less raw pointer.

@Mic92
Copy link
Member

Mic92 commented May 6, 2025

Just want to add that the merge above was triggered by auto-merge, that I have set up initially. I saw your comments after the fact.

@corngood
Copy link
Contributor

I'm still investigating, but I think this broke nix on cygwin, because it depends on gnu_unique_object symbols to work properly when compiled into multiple shared libs (e.g. nix / libcmd).

@xokdvium
Copy link
Contributor

Yeah, it was an issue with MacOS as well. We need to move the singletons into the libraries. It's sad that non ELF platforms have issues with "vague" linkage.

@corngood
Copy link
Contributor

corngood commented Nov 12, 2025

How did you work around this on MacOS? I was going to attempt moving the data as you suggested.

Edit: do you mean 060c34b ?

The problem I ran into was with RegisterCommand, which could be fixed in a similar way.

@xokdvium
Copy link
Contributor

Yeah, I did suggest moving all the other static variables from headers to .cc files, but seems like we forgot some.

@corngood
Copy link
Contributor

I fixed what I could find in #14551.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fetching Networking with the outside (non-Nix) world, input locking new-cli Relating to the "nix" command store Issues and pull requests concerning the Nix store

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants