BDE 4.14.0 Production release
|
Provide an efficient cache for read-only bdlt::Calendar
objects.
This component defines the bdlt::CalendarCache
class, a cache for read-only bdlt::Calendar
objects. The bdlt::CalendarCache
class defines two methods for fetching calendars from the cache: a manipulator called getCalendar
and an accessor called lookupCalendar
. Calendars are identified by name using C-style strings, and both retrieval methods return a bsl::shared_ptr<const bdlt::Calendar>
.
The first time a calendar is requested from the cache using the getCalendar
manipulator, the identified calendar is loaded into the cache using the loader that was supplied upon construction of the cache (see bdlt_calendarloader ); a reference to that newly-loaded calendar is then returned. Subsequent requests for the same calendar, using either the getCalendar
or lookupCalendar
method, are efficiently satisfied by returning references to the cached instance. The lookupCalendar
accessor differs from the getCalendar
manipulator in that when a request is made through the accessor for a calendar that is not present in the cache, the calendar is not loaded as a side-effect. In this case, an empty bsl::shared_ptr<const bdlt::Calendar>
is returned instead, which is effectively a null pointer. Note that the calendar-naming convention in effect for a given cache is determined by the concrete loader supplied at construction of the cache.
Calendars stored in a cache can be explicitly invalidated; the invalidate
method is used to invalidate a single calendar and invalidateAll
invalidates all calendars in the cache. Invalidated calendars are removed from the cache. However, a calendar that has been invalidated in the cache remains valid to all outstanding references to it, obtained via earlier calls to the getCalendar
and lookupCalendar
methods, until all of those references have been destroyed. Note that a subsequent request, using the getCalendar
manipulator, for a calendar that has been invalidated incurs the overhead of once again loading that calendar into the cache.
Calendars can also be invalidated on the basis of a timeout. To use this feature of bdlt::CalendarCache
, a bsls::TimeInterval
timeout must be supplied at construction. When a timeout is in effect for a cache, requests for a calendar from the cache using the getCalendar
manipulator may incur the reloading of the calendar if the one in the cache has expired (i.e., the time interval defined by the timeout value has elapsed since the calendar was last loaded). In the case of the lookupCalendar
accessor, an empty bsl::shared_ptr<const bdlt::Calendar>
is returned if the requested calendar is found to have expired.
The bdlt::CalendarCache
class is fully thread-safe (see bsldoc_glossary ) provided that the allocator supplied at construction and the default allocator in effect during the lifetime of cache objects are both fully thread-safe.
The following example illustrates how to use a bdlt::CalendarCache
.
This example shows basic use of a bdlt::CalendarCache
object.
In this example, we assume a hypothetical calendar loader, MyCalendarLoader
, the details of which are not important other than that it supports calendars identified by "DE", "FR", and "US", which nominally identify the major holidays in Germany, France, and the United States, respectively. Furthermore, we cite two specific dates of interest: 2011/07/04, which was a holiday in the US (Independence Day), but not in France, and 2011/07/14, which was a holiday in France (Bastille Day), but not in the US. Note that neither of these dates were holidays in Germany.
First, we create a calendar loader, an instance of MyCalendarLoader
, and use it, in turn, to create a cache. For the purposes of this example, it is sufficient to let the cache use the default allocator:
Next, we retrieve the calendar usA
, identified by "US", verify that the loading of that calendar into the cache was successful (usA.get()
is non-null), and verify that 2011/07/04 is recognized as a holiday in the "US" calendar, whereas 2011/07/14 is not:
Then, we fetch the calendar identified by "FR", this time verifying that 2011/07/14 is recognized as a holiday in the "FR" calendar, but 2011/07/04 is not:
Next, we retrieve the "FR" calendar again, this time via the lookupCalendar
accessor, and note that the request is satisfied by the calendar that is already in the cache:
Then, we invalidate the "US" calendar in the cache and immediately fetch it again. The call to invalidate
removed the "US" calendar from the cache, so it had to be reloaded into the cache to satisfy the request:
Next, all calendars in the cache are invalidated, then reloaded:
Now, verify that references to calendars that were invalidated in the cache are still valid for clients that obtained references to them before they were made invalid:
When usA
, usB
, frA
, and frB
go out of scope, the resources used by the calendars to which they refer are automatically reclaimed.
Finally, using the lookupCalendar
accessor, we attempt to retrieve a calendar that has not yet been loaded into the cache, but that we know to be supported by the calendar loader. Since the lookupCalendar
accessor does not load calendars into the cache as a side-effect, the request fails:
This second example shows the effects on a bdlt::CalendarCache
object that is constructed to have a timeout value. Note that the following snippets of code assume a platform-independent sleepSeconds
method that sleeps for the specified number of seconds.
First, we create a calendar loader and a calendar cache. The cache is constructed to have a timeout of 3 seconds. Of course, such a short timeout is inappropriate for production use, but it is necessary for illustrating the effects of a timeout in this example. As in example 1 (above), we again let the cache use the default allocator:
Next, we retrieve the calendar identified by "DE" from the cache:
Next, we sleep for 2 seconds before retrieving the "FR" calendar:
Next, we sleep for 2 more seconds before attempting to retrieve the "DE" calendar again, this time using the lookupCalendar
accessor. Since the cumulative sleep time exceeds the timeout value established for the cache when it was constructed, the "DE" calendar has expired; hence, it has been removed from the cache:
Next, we verify that the "FR" calendar is still available in the cache:
Finally, we sleep for an additional 2 seconds and verify that the "FR" calendar has also expired: