BDE 4.14.0 Production release
|
Provide an efficient cache for read-only bdlt::Timetable
objects.
This component defines the bdlt::TimetableCache
class, a cache for read-only bdlt::Timetable
objects. The bdlt::TimetableCache
class defines two methods for fetching timetables from the cache: a manipulator called getTimetable
and an accessor called lookupTimetable
. Timetables are identified by name using C-style strings, and both retrieval methods return a bsl::shared_ptr<const bdlt::Timetable>
.
The first time a timetable is requested from the cache using the getTimetable
manipulator, the identified timetable is loaded into the cache using the loader that was supplied upon construction of the cache (see bdlt_timetableloader ); a reference to that newly-loaded timetable is then returned. Subsequent requests for the same timetable, using either the getTimetable
or lookupTimetable
method, are efficiently satisfied by returning references to the cached instance. The lookupTimetable
accessor differs from the getTimetable
manipulator in that when a request is made through the accessor for a timetable that is not present in the cache, the timetable is not loaded as a side-effect. In this case, an empty bsl::shared_ptr<const bdlt::Timetable>
is returned instead, which is effectively a null pointer. Note that the timetable-naming convention in effect for a given cache is determined by the concrete loader supplied at construction of the cache.
Timetables stored in a cache can be explicitly invalidated; the invalidate
method is used to invalidate a single timetable and invalidateAll
invalidates all timetables in the cache. Invalidated timetables are removed from the cache. However, a timetable that has been invalidated in the cache remains valid to all outstanding references to it, obtained via earlier calls to the getTimetable
and lookupTimetable
methods, until all of those references have been destroyed. Note that a subsequent request, using the getTimetable
manipulator, for a timetable that has been invalidated incurs the overhead of once again loading that timetable into the cache.
Timetables can also be invalidated on the basis of a timeout. To use this feature of bdlt::TimetableCache
, a bsls::TimeInterval
timeout must be supplied at construction. When a timeout is in effect for a cache, requests for a timetable from the cache using the getTimetable
manipulator may incur the reloading of the timetable if the one in the cache has expired (i.e., the time interval defined by the timeout value has elapsed since the timetable was last loaded). In the case of the lookupTimetable
accessor, an empty bsl::shared_ptr<const bdlt::Timetable>
is returned if the requested timetable is found to have expired.
The bdlt::TimetableCache
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::TimetableCache
.
This example shows basic use of a bdlt::TimetableCache
object.
In this example, we assume a hypothetical timetable loader, MyTimetableLoader
, the details of which are not important other than that it supports timetables identified by "ZERO", "ONE", and "TWO". Furthermore, the value of the initial transition code for each of these timetables is given by the timetable's name (e.g., if Z
has the value of the timetable identified as "ZERO", then 0 == Z.initialTransitionCode()
).
First, we create a timetable loader, an instance of MyTimetableLoader
, 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 timetable twoA
, identified by "TWO", verify that the loading of that timetable into the cache was successful (twoA.get()
is non-null), and verify that 2 is the value of the initial transition code for timetable "TWO":
Then, we fetch the timetable identified by "ONE", this time verifying that 1 is the value of the initial transition code for the "ONE" timetable:
Next, we retrieve the "ONE" timetable again, this time via the lookupTimetable
accessor, and note that the request is satisfied by the timetable that is already in the cache:
Then, we invalidate the "TWO" timetable in the cache and immediately fetch it again. The call to invalidate
removed the "TWO" timetable from the cache, so it had to be reloaded into the cache to satisfy the request:
Next, all timetables in the cache are invalidated, then reloaded:
Now, verify that references to timetables that were invalidated in the cache are still valid for clients that obtained references to them before they were made invalid:
When twoA
, twoB
, oneA
, and oneB
go out of scope, the resources used by the timetables to which they refer are automatically reclaimed.
Finally, using the lookupTimetable
accessor, we attempt to retrieve a timetable that has not yet been loaded into the cache, but that we know to be supported by the timetable loader. Since the lookupTimetable
accessor does not load timetables into the cache as a side-effect, the request fails:
This second example shows the effects on a bdlt::TimetableCache
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 timetable loader and a timetable 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 timetable identified by "ZERO" from the cache:
Next, we sleep for 2 seconds before retrieving the "ONE" timetable:
Next, we sleep for 2 more seconds before attempting to retrieve the "ZERO" timetable again, this time using the lookupTimetable
accessor. Since the cumulative sleep time exceeds the timeout value established for the cache when it was constructed, the "ZERO" timetable has expired; hence, it has been removed from the cache:
Next, we verify that the "ONE" timetable is still available in the cache:
Finally, we sleep for an additional 2 seconds and verify that the "ONE" timetable has also expired: