_once.py 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. # Copyright The OpenTelemetry Authors
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from threading import Lock
  15. from typing import Callable
  16. class Once:
  17. """Execute a function exactly once and block all callers until the function returns
  18. Same as golang's `sync.Once <https://pkg.go.dev/sync#Once>`_
  19. """
  20. def __init__(self) -> None:
  21. self._lock = Lock()
  22. self._done = False
  23. def do_once(self, func: Callable[[], None]) -> bool:
  24. """Execute ``func`` if it hasn't been executed or return.
  25. Will block until ``func`` has been called by one thread.
  26. Returns:
  27. Whether or not ``func`` was executed in this call
  28. """
  29. # fast path, try to avoid locking
  30. if self._done:
  31. return False
  32. with self._lock:
  33. if not self._done:
  34. func()
  35. self._done = True
  36. return True
  37. return False