Expose a list<tzdb>

* Existing API always accesses the front of the list.
* Add locate_zone and current_zone member functions to tzdb.
* reload_tzdb() pushes a new database to the front of the list.
* get_tzdb_list() exposes the list<tzdb>&.
This commit is contained in:
Howard Hinnant
2017-07-17 23:05:16 -04:00
parent 0f7fd4a04e
commit c110f40e76

View File

@@ -37,7 +37,7 @@
Document number: D0355R4<br> Document number: D0355R4<br>
<br> <br>
<a href="mailto:howard.hinnant@gmail.com">Howard E. Hinnant</a><br> <a href="mailto:howard.hinnant@gmail.com">Howard E. Hinnant</a><br>
2017-07-07<br> 2017-07-17<br>
</address> </address>
<hr> <hr>
<h1>Extending <code>&lt;chrono&gt;</code> to Calendars and Time Zones</h1> <h1>Extending <code>&lt;chrono&gt;</code> to Calendars and Time Zones</h1>
@@ -59,6 +59,7 @@ Document number: D0355R4<br>
<h3>Changes since <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0355r3.html">R3</a></h3> <h3>Changes since <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0355r3.html">R3</a></h3>
<ul> <ul>
<li>Make the database singleton a <code>list&lt;tzdb&gt;</code> instead of a single <code>tzdb</code>.</li>
<li>Rewrite in terms of <code>string_view</code>.</li> <li>Rewrite in terms of <code>string_view</code>.</li>
<li>Improve spec for operator-(const year_month&amp; x, const year_month&amp; y).</li> <li>Improve spec for operator-(const year_month&amp; x, const year_month&amp; y).</li>
<li>Refine constraints on conversions from calendar types to sys_days.</li> <li>Refine constraints on conversions from calendar types to sys_days.</li>
@@ -1406,6 +1407,7 @@ template&lt;class charT, class traits, class Rep, class Period&gt;
struct tzdb; struct tzdb;
const tzdb&amp; get_tzdb(); const tzdb&amp; get_tzdb();
list&lt;TZ_DB*gt;&amp; get_tzdb_list();
const time_zone* locate_zone(string_view tz_name); const time_zone* locate_zone(string_view tz_name);
const time_zone* current_zone(); const time_zone* current_zone();
@@ -9083,46 +9085,34 @@ struct tzdb
vector&lt;time_zone&gt; zones; vector&lt;time_zone&gt; zones;
vector&lt;link&gt; links; vector&lt;link&gt; links;
vector&lt;leap&gt; leaps; vector&lt;leap&gt; leaps;
const time_zone* locate_zone(string_view tz_name) const;
const time_zone* current_zone() const;
}; };
list&lt;tzdb&gt;
</pre> </pre>
<p> <p>
The <code>tzdb</code> database is a singleton. And access to it is The <code>list&lt;tzdb&gt;</code> database is a singleton. Access is
<i>read-only</i>, except for <code>reload_tzdb()</code> which re-initializes it. granted to it via the <code>get_tzdb_list()</code> function which
Each <code>vector</code> is sorted to enable fast lookup. You can iterate over returns a reference to it. However this access is only needed for
and inspect this database. those applications which need to have long uptimes and have a need to
update the time zone database while running. Other applications can
implicitly access the <code>front()</code> of this list via the
<i>read-only</i> namespace scope functions <code>get_tzdb()</code>,
<code>locate_zone()</code> and <code>current_zone()</code>. Each
<code>vector</code> in <code>tzdb</code> is sorted to enable fast
lookup. You can iterate over and inspect this database. And even
hold multiple versions of the database at once, via the
<code>list&lt;tzdb&gt;</code>.
</p> </p>
<pre> <pre>
const tzdb&amp; get_tzdb(); const time_zone* tzdb::locate_zone(string_view tz_name) const;
</pre> </pre>
<blockquote> <blockquote>
<p> <p>
<i>Effects:</i> If this is the first access to the database, will initialize
the database.
</p>
<p>
<i>Returns:</i> A <code>const</code> reference to the database.
</p>
<p>
<i>Thread Safety:</i> It is safe to call this function from multiple threads at
one time.
</p>
<p>
<i>Throws:</i> <code>runtime_error</code> if for any reason a reference can not
be returned to a valid <code>tzdb</code>.
</p>
</blockquote>
<pre>
const time_zone* locate_zone(string_view tz_name);
</pre>
<blockquote>
<p>
<i>Effects:</i> Calls <code>get_tzdb()</code> which will initialize the timezone
database if this is the first reference to the database.
</p>
<p>
<i>Returns:</i> If a <code>time_zone</code> is found for which <i>Returns:</i> If a <code>time_zone</code> is found for which
<code>name() == tz_name</code>, returns a pointer to that <code>time_zone</code>. <code>name() == tz_name</code>, returns a pointer to that <code>time_zone</code>.
Otherwise if a <code>link</code> is found where <code>tz_name == link.name()</code>, Otherwise if a <code>link</code> is found where <code>tz_name == link.name()</code>,
@@ -9131,11 +9121,66 @@ then a pointer is returned to the <code>time_zone</code> for which
alternative name for a <code>time_zone</code>. <i>&mdash; end note</i>] alternative name for a <code>time_zone</code>. <i>&mdash; end note</i>]
</p> </p>
<p> <p>
<i>Throws:</i> Any exception propagated from <code>get_tzdb()</code>. If a <i>Throws:</i> If a <code>const time_zone*</code> can not be found as
<code>const time_zone*</code> can not be found as described in the described in the <i>Returns</i> clause, throws a
<i>Returns</i> clause, throws a <code>runtime_error</code>. [<i>Note:</i> <code>runtime_error</code>. [<i>Note:</i> On non-exceptional return,
On non-exceptional return, the return value is <i>always</i> a pointer to a the return value is <i>always</i> a pointer to a valid
valid <code>time_zone</code>. <i>&mdash; end note</i>] <code>time_zone</code>. <i>&mdash; end note</i>]
</p>
</blockquote>
<pre>
const time_zone* tzdb::current_zone() const;
</pre>
<blockquote>
<p>
<i>Returns:</i> A <code>const time_zone*</code> referring to the time zone which your
computer has set as its local time zone.
</p>
</blockquote>
<pre>
list&lt;tzdb&gt;&amp; get_tzdb_list();
</pre>
<blockquote>
<p>
<i>Effects:</i> If this is the first access to the database, will
initialize the database. If this call initializes the database, the
resulting database will be a <code>list&lt;tzdb&gt;</code> with
<code>size() == 1</code>.
</p>
<p>
<i>Returns:</i> A reference to the database.
</p>
<p>
<i>Thread Safety:</i> It is safe to call this function from multiple threads at
one time.
</p>
<p>
<i>Throws:</i> <code>runtime_error</code> if for any reason a
reference can not be returned to a valid
<code>list&lt;tzdb&gt;&amp;</code> containing one or more valid
<code>tzdb</code>.
</p>
</blockquote>
<pre>
const tzdb&amp; get_tzdb();
</pre>
<blockquote>
<p>
<i>Returns:</i> <code>get_tzdb_list().front()</code>.
</p>
</blockquote>
<pre>
const time_zone* locate_zone(string_view tz_name);
</pre>
<blockquote>
<p>
<i>Returns:</i> <code>get_tzdb().locate_zone(tz_name)</code> which
will initialize the timezone database if this is the first reference
to the database.
</p> </p>
</blockquote> </blockquote>
@@ -9144,23 +9189,13 @@ const time_zone* current_zone();
</pre> </pre>
<blockquote> <blockquote>
<p> <p>
<i>Effects:</i> Calls <code>locate_zone()</code> which will initialize the timezone <i>Returns:</i> <code>get_tzdb().current_zone()</code>.
database if this is the first reference to the database.
</p>
<p>
<i>Returns:</i> A <code>const time_zone*</code> referring to the time zone which your
computer has set as its local time zone.
</p>
<p>
<i>Throws:</i> Any exception propagated from <code>locate_zone()</code>.
[<i>Note:</i> On non-exceptional return, the return value is <i>always</i> a
pointer to a valid <code>time_zone</code>. <i>&mdash; end note</i>]
</p> </p>
</blockquote>
<p> <p>
<a href="#Wording">Back to TOC</a> <a href="#Wording">Back to TOC</a>
</p> </p>
</blockquote>
<a name="time.timezone.database.remote"></a><h3>23.17.12.1.1 Remote time zone database support [time.timezone.database.remote]</h3> <a name="time.timezone.database.remote"></a><h3>23.17.12.1.1 Remote time zone database support [time.timezone.database.remote]</h3>
<p class = note> <p class = note>
@@ -9177,19 +9212,17 @@ const tzdb&amp; reload_tzdb();
<a href="http://www.iana.org/time-zones">IANA website</a>. If the <a href="http://www.iana.org/time-zones">IANA website</a>. If the
<a href="http://www.iana.org/time-zones">IANA website</a> is unavailable, or if the <a href="http://www.iana.org/time-zones">IANA website</a> is unavailable, or if the
latest version is already installed, there are no effects. Otherwise, a new version latest version is already installed, there are no effects. Otherwise, a new version
is available. It is downloaded and installed, and then the program re-initializes is available. It is downloaded and installed, and then the program initializes
the <code>tzdb</code> singleton from the new disk files. a new <code>tzdb</code> from the new disk files and pushes it to the front of
the <code>list&lt;tzdb&gt;&amp;</code> accessed by <code>get_tzdb_list()</code>.
</p> </p>
<p> <p>
<i>Returns:</i> A <code>const</code> reference to the database. <i>Returns:</i> <code>get_tzdb_list().front()</code>.
</p> </p>
<p> <p>
<i>Thread Safety:</i> This function is <i>not</i> thread safe. You must <i>Thread Safety:</i> This function is <i>not</i> thread safe. You must
provide your own synchronization among threads accessing the time zone database provide your own synchronization among threads accessing the time zone database
to safely use this function. If this function re-initializes the database, all outstanding to safely use this function.
<code>const time_zone*</code> are invalidated (including those held within
<code>zoned_time</code> objects). And afterwards, all outstanding
<code>sys_info</code> may hold obsolete data.
</p> </p>
<p> <p>
<i>Throws:</i> <code>runtime_error</code> if for any reason a reference can not <i>Throws:</i> <code>runtime_error</code> if for any reason a reference can not