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
15from threading import Lock
16from typing import Callable
17
18
19class Once:
20 """Execute a function exactly once and block all callers until the function returns
21
22 Same as golang's `sync.Once <https://pkg.go.dev/sync#Once>`_
23 """
24
25 def __init__(self) -> None:
26 self._lock = Lock()
27 self._done = False
28
29 def do_once(self, func: Callable[[], None]) -> bool:
30 """Execute ``func`` if it hasn't been executed or return.
31
32 Will block until ``func`` has been called by one thread.
33
34 Returns:
35 Whether or not ``func`` was executed in this call
36 """
37
38 # fast path, try to avoid locking
39 if self._done:
40 return False
41
42 with self._lock:
43 if not self._done:
44 func()
45 self._done = True
46 return True
47 return False