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 | #include <chrono> |
12 | |
13 | #include <__mutex/unique_lock.h> |
14 | #include <forward_list> |
15 | |
16 | // When threads are not available the locking is not required. |
17 | #ifndef _LIBCPP_HAS_NO_THREADS |
18 | # include <shared_mutex> |
19 | #endif |
20 | |
21 | _LIBCPP_BEGIN_NAMESPACE_STD |
22 | |
23 | namespace chrono { |
24 | |
25 | //===----------------------------------------------------------------------===// |
26 | // Private API |
27 | //===----------------------------------------------------------------------===// |
28 | |
29 | class tzdb_list::__impl { |
30 | public: |
31 | explicit __impl(tzdb&& __tzdb) { __tzdb_.push_front(std::move(__tzdb)); } |
32 | |
33 | using const_iterator = tzdb_list::const_iterator; |
34 | |
35 | const tzdb& front() const noexcept { |
36 | #ifndef _LIBCPP_HAS_NO_THREADS |
37 | shared_lock __lock{__mutex_}; |
38 | #endif |
39 | return __tzdb_.front(); |
40 | } |
41 | |
42 | const_iterator erase_after(const_iterator __p) { |
43 | #ifndef _LIBCPP_HAS_NO_THREADS |
44 | unique_lock __lock{__mutex_}; |
45 | #endif |
46 | return __tzdb_.erase_after(__p); |
47 | } |
48 | |
49 | tzdb& __emplace_front(tzdb&& __tzdb) { |
50 | #ifndef _LIBCPP_HAS_NO_THREADS |
51 | unique_lock __lock{__mutex_}; |
52 | #endif |
53 | return __tzdb_.emplace_front(std::move(__tzdb)); |
54 | } |
55 | |
56 | const_iterator begin() const noexcept { |
57 | #ifndef _LIBCPP_HAS_NO_THREADS |
58 | shared_lock __lock{__mutex_}; |
59 | #endif |
60 | return __tzdb_.begin(); |
61 | } |
62 | const_iterator end() const noexcept { |
63 | // forward_list<T>::end does not access the list, so no need to take a lock. |
64 | return __tzdb_.end(); |
65 | } |
66 | |
67 | const_iterator cbegin() const noexcept { return begin(); } |
68 | const_iterator cend() const noexcept { return end(); } |
69 | |
70 | private: |
71 | #ifndef _LIBCPP_HAS_NO_THREADS |
72 | mutable shared_mutex __mutex_; |
73 | #endif |
74 | forward_list<tzdb> __tzdb_; |
75 | }; |
76 | |
77 | //===----------------------------------------------------------------------===// |
78 | // Public API |
79 | //===----------------------------------------------------------------------===// |
80 | |
81 | _LIBCPP_EXPORTED_FROM_ABI tzdb_list::tzdb_list(tzdb&& __tzdb) : __impl_{new __impl(std::move(__tzdb))} {} |
82 | |
83 | _LIBCPP_EXPORTED_FROM_ABI tzdb_list::~tzdb_list() { delete __impl_; } |
84 | |
85 | _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const tzdb& tzdb_list::front() const noexcept { |
86 | return __impl_->front(); |
87 | } |
88 | |
89 | _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::erase_after(const_iterator __p) { |
90 | return __impl_->erase_after(__p); |
91 | } |
92 | |
93 | _LIBCPP_EXPORTED_FROM_ABI tzdb& tzdb_list::__emplace_front(tzdb&& __tzdb) { |
94 | return __impl_->__emplace_front(std::move(__tzdb)); |
95 | } |
96 | |
97 | _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::begin() const noexcept { |
98 | return __impl_->begin(); |
99 | } |
100 | _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::end() const noexcept { |
101 | return __impl_->end(); |
102 | } |
103 | |
104 | _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::cbegin() const noexcept { |
105 | return __impl_->cbegin(); |
106 | } |
107 | _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::cend() const noexcept { |
108 | return __impl_->cend(); |
109 | } |
110 | |
111 | } // namespace chrono |
112 | |
113 | _LIBCPP_END_NAMESPACE_STD |
114 | |