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