BDE 4.14.0 Production release
Loading...
Searching...
No Matches
baltzo_zoneinfocache.h
Go to the documentation of this file.
1/// @file baltzo_zoneinfocache.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// baltzo_zoneinfocache.h -*-C++-*-
8#ifndef INCLUDED_BALTZO_ZONEINFOCACHE
9#define INCLUDED_BALTZO_ZONEINFOCACHE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup baltzo_zoneinfocache baltzo_zoneinfocache
15/// @brief Provide a cache for time-zone information.
16/// @addtogroup bal
17/// @{
18/// @addtogroup baltzo
19/// @{
20/// @addtogroup baltzo_zoneinfocache
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#baltzo_zoneinfocache-purpose"> Purpose</a>
25/// * <a href="#baltzo_zoneinfocache-classes"> Classes </a>
26/// * <a href="#baltzo_zoneinfocache-description"> Description </a>
27/// * <a href="#baltzo_zoneinfocache-thread-safety"> Thread Safety </a>
28/// * <a href="#baltzo_zoneinfocache-usage"> Usage </a>
29/// * <a href="#baltzo_zoneinfocache-example-1-creating-a-concrete-baltzo-loader"> Example 1: Creating a Concrete baltzo::Loader </a>
30/// * <a href="#baltzo_zoneinfocache-example-2-creating-and-using-a-baltzo-zoneinfocache"> Example 2: Creating and Using a baltzo::ZoneinfoCache </a>
31///
32/// # Purpose {#baltzo_zoneinfocache-purpose}
33/// Provide a cache for time-zone information.
34///
35/// # Classes {#baltzo_zoneinfocache-classes}
36///
37/// - baltzo::ZoneinfoCache: a cache for time-zone information
38///
39/// @see baltzo_zoneinfo, baltzo_defaultzoneinfocache
40///
41/// # Description {#baltzo_zoneinfocache-description}
42/// This component defines a class, `baltzo::ZoneinfoCache`, that
43/// serves as a cache of `baltzo::Zoneinfo` objects. A time-zone cache is
44/// supplied, on construction, with a `baltzo::Loader` object to obtain
45/// time-zone information objects from some data source. Invocation of the
46/// `getZoneinfo` method for a specified time zone returns the address of either
47/// previously cached data, or if that data is not cache-resident, a new loaded
48/// `baltzo::Zoneinfo` object, which is cached for use in subsequent calls to
49/// `getZoneinfo` and `lookupZoneinfo`. Addresses returned by either of these
50/// methods are valid for the lifetime of the cache.
51///
52/// ## Thread Safety {#baltzo_zoneinfocache-thread-safety}
53///
54///
55/// `baltzo::ZoneinfoCache` is fully *thread-safe*, meaning that all non-creator
56/// operations on an object can be safely invoked simultaneously from multiple
57/// threads.
58///
59/// ## Usage {#baltzo_zoneinfocache-usage}
60///
61///
62/// In this section, we demonstrate creating a `baltzo::ZoneinfoCache` object
63/// and using it to access time zone information.
64///
65/// ### Example 1: Creating a Concrete baltzo::Loader {#baltzo_zoneinfocache-example-1-creating-a-concrete-baltzo-loader}
66///
67///
68/// A `baltzo::ZoneinfoCache` object is provided a `baltzo::Loader` on
69/// construction. The `loader` is used to populate the cache per user requests
70/// via the `getZoneinfo` method. In this example, we use a `TestLoader`
71/// implementation of the `baltzo::Loader` protocol, based on the
72/// @ref baltzo_testloader component. In this example, our test loader is
73/// explicitly primed with responses for requests for certain time-zone
74/// identifiers. Note that, in practice, a `loader` typically obtains time-zone
75/// information from some external data store (e.g., see
76/// @ref baltzo_datafileloader ).
77///
78/// We start by creating and initializing a couple of example time zone
79/// information objects. Note that the `baltzo::Zoneinfo` objects below are
80/// illustrative, and contain no actual time zone information:
81/// @code
82/// baltzo::Zoneinfo newYorkZoneinfo;
83/// newYorkZoneinfo.setIdentifier("America/New_York");
84///
85/// baltzo::Zoneinfo londonZoneinfo;
86/// londonZoneinfo.setIdentifier("Europe/London");
87/// @endcode
88/// Next we create a description of Eastern Standard Time (EST) and Greenwich
89/// Mean Time (GMT):
90/// @code
91/// baltzo::LocalTimeDescriptor est(-5 * 60 * 60, false, "EST");
92/// baltzo::LocalTimeDescriptor gmt( 0, false, "GMT");
93/// @endcode
94/// Then we set the initial transition for `newYorkZoneinfo` to Eastern Standard
95/// Time, and the initial transition for `londonZoneinfo` to Greenwich Mean
96/// Time. Note that such an initial transition is required for a
97/// `baltzo::Zoneinfo` object to be considered Well-Formed (see `isWellFormed`):
98/// @code
99/// bsls::Types::Int64 firstTime = bdlt::EpochUtil::convertToTimeT64(
100/// bdlt::Datetime(1, 1, 1));
101/// newYorkZoneinfo.addTransition(firstTime, est);
102/// londonZoneinfo.addTransition(firstTime, gmt);
103/// @endcode
104/// Next we create a `TestLoader`, and then populate it with our example time
105/// zone information objects:
106/// @code
107/// TestLoader testLoader;
108/// testLoader.setTimeZone(newYorkZoneinfo);
109/// testLoader.setTimeZone(londonZoneinfo);
110/// @endcode
111/// Finally, we verify that `testLoader` contains the configured
112/// `baltzo::Zoneinfo` objects for New York and London:
113/// @code
114/// baltzo::Zoneinfo newYorkResult;
115/// int rc = testLoader.loadTimeZone(&newYorkResult, "America/New_York");
116/// assert(0 == rc);
117/// assert(newYorkZoneinfo == newYorkResult);
118///
119/// baltzo::Zoneinfo londonResult;
120/// rc = testLoader.loadTimeZone(&londonResult, "Europe/London");
121/// assert(0 == rc);
122/// assert(londonZoneinfo == londonResult);
123/// @endcode
124///
125/// ### Example 2: Creating and Using a baltzo::ZoneinfoCache {#baltzo_zoneinfocache-example-2-creating-and-using-a-baltzo-zoneinfocache}
126///
127///
128/// In this example, we create a `baltzo::ZoneinfoCache`, and use it to access
129/// time zone information for several time zones.
130///
131/// We start by creating a `baltzo::ZoneinfoCache` object supplied with the
132/// address of the `TestLoader` we populated in the preceding example:
133/// @code
134/// baltzo::ZoneinfoCache cache(&testLoader);
135/// @endcode
136/// Next, we verify the newly constructed cache does not contain either New York
137/// or London:
138/// @code
139/// assert(0 == cache.lookupZoneinfo("America/New_York"));
140/// assert(0 == cache.lookupZoneinfo("Europe/London"));
141/// @endcode
142/// Then, we call `getZoneinfo` to obtain the data for the New York time zone.
143/// Note that, because this is the first `getZoneinfo` operation on the class,
144/// the time-zone data has not previously been retrieved, and the data must be
145/// loaded using the loader supplied at construction:
146/// @code
147/// const baltzo::Zoneinfo *newYork = cache.getZoneinfo(&rc,
148/// "America/New_York");
149///
150/// assert(0 == rc);
151/// assert(0 != newYork);
152/// assert("America/New_York" == newYork->identifier());
153/// @endcode
154/// Next, we verify that a subsequent call `lookupZoneinfo` for New York,
155/// returns the previously cached value. However, a call to `lookupZoneinfo`
156/// for London will return 0 because the value has not been cached:
157/// @code
158/// assert(newYork == cache.lookupZoneinfo("America/New_York"));
159/// assert(0 == cache.lookupZoneinfo("Europe/London"));
160/// @endcode
161/// Next, we call `getZoneinfo` for London and verify that it returns the
162/// expected value:
163/// @code
164/// const baltzo::Zoneinfo *london = cache.getZoneinfo(&rc, "Europe/London");
165/// assert(0 == rc);
166/// assert(0 != london);
167/// assert("Europe/London" == london->identifier());
168/// @endcode
169/// Finally, we call `getZoneinfo` with time zone identifier unknown to our
170/// `TestLoader`. The call to `getZoneinfo` returns 0 because the time zone
171/// information cannot be loaded. Examination of `rc` shows indicates that the
172/// identifier is not supported:
173/// @code
174/// assert(0 == cache.getZoneinfo(&rc, "badId"));
175/// assert(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
176/// @endcode
177/// @}
178/** @} */
179/** @} */
180
181/** @addtogroup bal
182 * @{
183 */
184/** @addtogroup baltzo
185 * @{
186 */
187/** @addtogroup baltzo_zoneinfocache
188 * @{
189 */
190
191#include <balscm_version.h>
192
193#include <baltzo_loader.h>
194#include <baltzo_zoneinfo.h>
195
196#include <bdlb_cstringless.h>
197
198#include <bslma_bslallocator.h>
200
202
203#include <bslmt_rwmutex.h>
204
205#include <bsls_assert.h>
206#include <bsls_atomic.h>
207#include <bsls_review.h>
208
209#include <bsl_map.h>
210
211
212namespace baltzo {
213
214 // ===================
215 // class ZoneinfoCache
216 // ===================
217
218/// This class provides an efficient mechanism for retrieving information
219/// about a given time zone. The first time a client requests information
220/// for some time-zone identifier, that information is loaded (using the
221/// `Loader` supplied at construction), returned to the client (via a
222/// `const` pointer value), and cached for future use. Subsequent requests
223/// for the same time-zone return the cached information. The returned
224/// values are valid for the lifetime of this object.
225///
226/// This class:
227/// * is *exception-neutral*
228/// * is *fully* *thread-safe*
229/// For terminology see @ref bsldoc_glossary .
230///
231/// See @ref baltzo_zoneinfocache
233
234 public:
235 // TYPES
237
238 private:
239 // PRIVATE TYPES
241
242 // DATA
243 ZoneinfoMap d_cache; // cached time-zone info, indexed by
244 // time-zone id
245
246 Loader *d_loader_p; // loader used to obtain time-zone
247 // information (held, not owned)
248
249 mutable bslmt::RWMutex d_lock; // cache access synchronization
250
251 allocator_type d_allocator; // allocator used to supply memory
252
253 // NOT IMPLEMENTED
255 ZoneinfoCache& operator=(const ZoneinfoCache&);
256
257 public:
258 // TRAITS
261
262 // CREATORS
263
264 /// Create an empty cache of time-zone information that will use the
265 /// specified `loader` to populate the cache, as-needed, with time zone
266 /// information. Optionally specify an `allocator` (e.g., the address
267 /// of a `bslma::Allocator` object) to supply memory; otherwise, the
268 /// default allocator is used. In order the populate the cache for a
269 /// time zone identifier, `loader` must return a `Zoneinfo` object that
270 /// is well-formed (see `ZoneinfoUtil::isWellFormed`) and whose
271 /// `identifier` matches the supplied time zone identifier.
272 explicit ZoneinfoCache(
273 Loader *loader,
274 const allocator_type& allocator = allocator_type());
275
276 /// Destroy this object.
278
279 // MANIPULATORS
280
281 /// Return the address of the non-modifiable `Zoneinfo` object
282 /// describing the time zone identified by the specified `timeZoneId`,
283 /// or 0 if the operation does not succeed. If the information for
284 /// `timeZoneId` has not been previously cached, then attempt to
285 /// populate this object using the `loader` supplied at construction.
286 /// Optionally specify the address of an integer, `rc`, in which to load
287 /// the return code for this operation. If `rc` is specified, load 0
288 /// into `rc` if the operation succeeds, `ErrorCode::k_UNSUPPORTED_ID`
289 /// if the time-zone identifier is not supported, and a negative value
290 /// if the operation does not succeed for any other reason. If the
291 /// returned address is non-zero, the Zoneinfo object returned is
292 /// guaranteed to be well-formed (i.e., `ZoneinfoUtil::isWellFormed`
293 /// will return `true` if called with the returned value), and remain
294 /// valid for the lifetime of this object. The behavior is undefined if
295 /// `rc` is 0.
296 const Zoneinfo *getZoneinfo(const char *timeZoneId);
297 const Zoneinfo *getZoneinfo(int *rc, const char *timeZoneId);
298
299 // ACCESSORS
300
301 /// Return the address of the non-modifiable cached description of the
302 /// time zone identified by the specified `timeZoneId`, and 0 if
303 /// information for `timeZoneId` has not previously been cached (by a
304 /// call to `getZoneinfo`). If the returned address is non-zero, the
305 /// Zoneinfo object returned is guaranteed to be well-formed (i.e.,
306 /// `ZoneinfoUtil::isWellFormed will return `true' if called with the
307 /// returned value), and remain valid for the lifetime of this object.
308 const Zoneinfo *lookupZoneinfo(const char *timeZoneId) const;
309
310 /// Return the allocator used by this object to supply memory. Note
311 /// that if no allocator was supplied at construction the default
312 /// allocator in effect at construction is used.
314};
315
316// ============================================================================
317// INLINE DEFINITIONS
318// ============================================================================
319
320 // -------------------
321 // class ZoneinfoCache
322 // -------------------
323
324// CREATORS
325inline
326ZoneinfoCache::ZoneinfoCache(Loader *loader, const allocator_type& allocator)
327: d_cache(allocator)
328, d_loader_p(loader)
329, d_allocator(allocator)
330{
331 BSLS_ASSERT(0 != loader);
332}
333
334// MANIPULATORS
335inline
336const Zoneinfo *ZoneinfoCache::getZoneinfo(const char *timeZoneId)
337{
338 BSLS_ASSERT(0 != timeZoneId);
339
340 int rc;
341 return getZoneinfo(&rc, timeZoneId);
342}
343
344inline
346{
347 return d_allocator;
348}
349
350} // close package namespace
351
352
353#endif
354
355// ----------------------------------------------------------------------------
356// Copyright 2020 Bloomberg Finance L.P.
357//
358// Licensed under the Apache License, Version 2.0 (the "License");
359// you may not use this file except in compliance with the License.
360// You may obtain a copy of the License at
361//
362// http://www.apache.org/licenses/LICENSE-2.0
363//
364// Unless required by applicable law or agreed to in writing, software
365// distributed under the License is distributed on an "AS IS" BASIS,
366// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
367// See the License for the specific language governing permissions and
368// limitations under the License.
369// ----------------------------- END-OF-FILE ----------------------------------
370
371/** @} */
372/** @} */
373/** @} */
Definition baltzo_loader.h:266
Definition baltzo_zoneinfocache.h:232
~ZoneinfoCache()
Destroy this object.
const Zoneinfo * getZoneinfo(const char *timeZoneId)
Definition baltzo_zoneinfocache.h:336
const Zoneinfo * getZoneinfo(int *rc, const char *timeZoneId)
const Zoneinfo * lookupZoneinfo(const char *timeZoneId) const
allocator_type get_allocator() const
Definition baltzo_zoneinfocache.h:345
BSLMF_NESTED_TRAIT_DECLARATION(ZoneinfoCache, bslma::UsesBslmaAllocator)
bsl::allocator< char > allocator_type
Definition baltzo_zoneinfocache.h:236
Definition baltzo_zoneinfo.h:429
Definition bslma_bslallocator.h:580
Definition bslstl_map.h:619
Definition bslmt_rwmutex.h:147
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition baltzo_datafileloader.h:263
Definition bslma_usesbslmaallocator.h:343