xref: /aosp_15_r20/external/cronet/third_party/libc++/src/src/include/tzdb/tzdb_list_private.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
10 
11 #ifndef _LIBCPP_SRC_INCLUDE_TZDB_TZDB_LIST_PRIVATE_H
12 #define _LIBCPP_SRC_INCLUDE_TZDB_TZDB_LIST_PRIVATE_H
13 
14 #include <__mutex/unique_lock.h>
15 #include <forward_list>
16 
17 // When threads are not available the locking is not required.
18 #ifndef _LIBCPP_HAS_NO_THREADS
19 #  include <shared_mutex>
20 #endif
21 
22 #include "types_private.h"
23 #include "tzdb_private.h"
24 
25 _LIBCPP_BEGIN_NAMESPACE_STD
26 
27 namespace chrono {
28 
29 //===----------------------------------------------------------------------===//
30 //                          Private API
31 //===----------------------------------------------------------------------===//
32 
33 // The tzdb_list stores a list of "tzdb" entries.
34 //
35 // The public tzdb database does not store the RULE entries of the IANA
36 // database. These entries are considered an implementation detail. Since most
37 // of the tzdb_list interface is exposed as "a list of tzdb entries" it's not
38 // possible to use a helper struct that stores a tzdb and the RULE database.
39 // Instead this class stores these in parallel forward lists.
40 //
41 // Since the nodes of a forward_list are stable it's possible to store pointers
42 // and references to these nodes.
43 class tzdb_list::__impl {
44 public:
__impl()45   __impl() { __load_no_lock(); }
46 
__load()47   [[nodiscard]] const tzdb& __load() {
48 #ifndef _LIBCPP_HAS_NO_THREADS
49     unique_lock __lock{__mutex_};
50 #endif
51     __load_no_lock();
52     return __tzdb_.front();
53   }
54 
55   using const_iterator = tzdb_list::const_iterator;
56 
__front()57   const tzdb& __front() const noexcept {
58 #ifndef _LIBCPP_HAS_NO_THREADS
59     shared_lock __lock{__mutex_};
60 #endif
61     return __tzdb_.front();
62   }
63 
__erase_after(const_iterator __p)64   const_iterator __erase_after(const_iterator __p) {
65 #ifndef _LIBCPP_HAS_NO_THREADS
66     unique_lock __lock{__mutex_};
67 #endif
68 
69     __rules_.erase_after(std::next(__rules_.cbegin(), std::distance(__tzdb_.cbegin(), __p)));
70     return __tzdb_.erase_after(__p);
71   }
72 
__begin()73   const_iterator __begin() const noexcept {
74 #ifndef _LIBCPP_HAS_NO_THREADS
75     shared_lock __lock{__mutex_};
76 #endif
77     return __tzdb_.begin();
78   }
__end()79   const_iterator __end() const noexcept {
80     //  forward_list<T>::end does not access the list, so no need to take a lock.
81     return __tzdb_.end();
82   }
83 
84 private:
85   // Loads the tzdbs
86   // pre: The caller ensures the locking, if needed, is done.
__load_no_lock()87   void __load_no_lock() { chrono::__init_tzdb(__tzdb_.emplace_front(), __rules_.emplace_front()); }
88 
89 #ifndef _LIBCPP_HAS_NO_THREADS
90   mutable shared_mutex __mutex_;
91 #endif
92   forward_list<tzdb> __tzdb_;
93 
94   forward_list<__tz::__rules_storage_type> __rules_;
95 };
96 
97 } // namespace chrono
98 
99 _LIBCPP_END_NAMESPACE_STD
100 
101 #endif // _LIBCPP_SRC_INCLUDE_TZDB_TZDB_LIST_PRIVATE_H
102