Freestanding `try_lock_for` and `try_lock_until`

This is a bit of a cross-post since I’ve asked about it on std-proposals@lists.isocpp.org prior to this. I did however not get any feedback at all so I’ll ask here.


I wanted to create a unique_multilock class template with all the member functions of unique_lock but that is capable of locking multiple lockables like scoped_lock.

Most of it seems pretty straight forward, but for TimedLockables I realized that std::try_lock_for/std::try_lock_until are “missing”.

What I have in mind are two functions templates like this:

template <class Clock, class Duration, TimedLockable... Ls>
[[nodiscard]] bool
try_lock_until(const std::chrono::time_point<Clock, Duration>& tp, Ls&... ls);

template <class Rep, class Period, TimedLockable... Ls>
[[nodiscard]] bool
try_lock_for(const std::chrono::duration<Rep, Period>& dur, Ls&... ls);

I wonder, are there any inherent reasons why we shouldn’t have such function templates in the standard library? If so, I won’t pursure writing a proposal. If it’s just a case of “noone wanted them bad enough to write a proposal”, I may go ahead and ask the Beman project for support in doing so.

Best regards,
Ted Lyngmo

Ps. I have something of a reference implementation up for code review if you’d like to take a peek at it:

I’m not an expert in this domain, but maybe an answer to the following questions would help:

  • Is there an easy-to-understand, concrete use case for this functionality that is representative of when someone would want this?
  • What are folks doing now instead? How is this better?

Hi David!

I got some feedback on std-proposals after a while and wrote a proposal to which I got feedback. I fixed the issues in my first version and I didn’t get any feedback on the updated one, so I sent that in:

It has an example of how it can be used and since there currently are no available standard functions for timed locking of multiple lockables, people who need one probably redesign their code to not need such a function or write a specialized function to provide deadlock free locking of multiple timed lockables for their use case. It’s not hard to write one, but neither is writing std::lockand we have that in the library - and since I wanted this algorithm myself, I thought, why not try to fill the gap by trying to standardize it.

I realized just after sending it in that I’m referencing the second newest C++ draft and not the most current. :roll_eyes:

Br,
Ted

Thanks for the link. These seem like reasonable additions to me. It’d be great to get a Beman implementation!

1 Like

These seem like reasonable additions to me. It’d be great to get a Beman implementation!

Glad to hear it! I could provide an adaption of my reference implementation to Beman if you’d like or should we wait to see if it’s looking like it’s going to be approved?

Br,
Ted

Sorry to be late to the convo – I had a draft reply back in August that got lost in too much other stuff.

reference implementation to Beman

Yes please - we’d love to have it here! After all, that’s our core mission :slight_smile:

There’s 2 ways to proceed basically - you could xfer your repo under Beman or create a new one using exemplar and cookie cutter. The adavantage of the later is all the most recent CI and structure is automatically there. I’ve sent your Github id an invite to the github project.

1 Like

Hi Jeff!

I’m starting to get close to have an implementation of what became beman.timed_lock_alg ready. At least I think the code and tests are ready.

I based it on exemplarand I still have a few files with exemplar in them and I’m not quite sure what I need to change. I’ve left them untouched for now.

$ git grep -li exemplar
.github/CODEOWNERS
cookiecutter/check_cookiecutter.sh
cookiecutter/{{cookiecutter.project_name}}/infra/.github/workflows/beman-tidy.yml
cookiecutter/{{cookiecutter.project_name}}/infra/cmake/use-fetch-content.cmake
infra/.github/workflows/beman-tidy.yml

There are probably quite a lot in the README that needs polishing too. It says it fails CI Testing and I don’t really know how to deal with that.

Br,
Ted

Hi Ted!
Thanks for contributing. Almost all the issues you’re facing are known issues that we’ve been planning to address but haven’t done yet since these are still early stages for Beman; in the future this kind of thing should be more ironed out.

  • cookiecutter is a mechanism we have for automatically performing some of the find-and-replaces of exemplar that you did manually. Unfortunately we haven’t documented it properly so it’s difficult for new maintainers to discover how to use it. Since it’s only relevant to exemplar, you should remove the cookiecutter directory as well as the file .github/workflows/cookiecutter_test.yml.
  • It looks like you broke the beman-submodule CI check by changing the instances of the text exemplar inside of infra/cmake/use-fetch-content.cmake. The fact that the file contains exemplar is essentially a mistake that we’re tracking as https://github.com/bemanproject/infra/issues/4, but currently those exemplars should not be changed. This is because the contents of the infra subdirectory must be exactly in alignment with the contents of the bemanproject/infra repository, which is what the beman-submodule check is checking for.
  • beman CI uses the pre-commit tool to enforce style guidelines; we’re unfortunately also missing documentation about how this works for Beman, but it looks like the style got out of sync due to an update to the CMake style checker version.
    I created a pull request to address the first three issues: Remove cookiecutter; bump infra beman-submodule; update CMake style for pre-commit by ednolan · Pull Request #3 · bemanproject/timed_lock_alg · GitHub
1 Like

Fast as a shark! Many thanks!

I also noticed that it seems it’s compiling with -fsanitize=thread which results in:

/usr/lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/mutex:207:48: error: 'class std::timed_mutex' has no member named '_M_clocklock'
  207 |           return static_cast<_Derived*>(this)->_M_clocklock(CLOCK_MONOTONIC,

I encountered this issue when starting with this implementation and wrote Bug 121496 - [14 Regression] ‘class std::timed_mutex’ has no member named ‘_M_clocklock’ with -fsanitize=thread

I’m not sure how to get around that bug in this case though.

Br,
Ted

Other issues:

  • CI is really slow right now both because we’re relying on an undersized free CI allocation from GitHub and because we get a thundering herd of scheduled jobs at 11:30AM ET due to a lack of randomization of scheduled job times; we’re working on fixing the latter.
  • For the GCC bug, I’m seeing “fixed for 14.4 and 15.3,” which apparently haven’t been released yet and so we don’t support in CI. You can see which versions we use for each image here
  • But you have control over which compilers you use for CI for your library, which is configured by editing the JSON configurations in .github/workflows/ci_tests.yml. You could either disable the TSan job by deleting the string "Release.TSan" from that part of the configuration, or change the configuration so that it runs with GCC trunk instead of GCC 15.2.0-- just use the string trunk where the configuration says 15/14/13, etc. Please remove from the CI configuration any compiler versions and C++ versions that you don’t support-- exemplar comes with the maximally broad range of tests. You should also update the “Supported Platforms” section of the README when you do so.
1 Like

Also, please don’t use the “production ready” badge in the README yet-- we’re still fleshing out the process for applying “production ready” status to libraries (this was the main subject of yesterday’s weekly meeting), but it will require some form of review process before libraries get toggled over from “under development.”

1 Like

Thanks! It took a few tries to get all tests happy :slight_smile:

One tricky thing with the timings in the tests is that they need to be long enough to to get the expected results, but the unexpected results are really ok too as long as it doesn’t deadlock. I had to add 100ms here and there to get all runners to get the expected results so the tests take a little too long for my liking (0.17s on my machine).

I’m thinking it may be possible to mock the platform specific clock, like clock_gettime, and to step it in a controlled way during the tests. Do you know if that’d be feasible in these workflows? I have no idea of how to do it for MSVC but I’ve done similar things on Linux before.

Br,
Ted

Another question: Should I create a PR in the website repo to put the library in the list of libraries at Beman Libraries | The Beman Project or is that something you do after review?

Br,
Ted

Yeah, you can go ahead with the website PR.

2 Likes