home *** CD-ROM | disk | FTP | other *** search
- // ------------------------------- //
- // -------- Start of File -------- //
- // ------------------------------- //
- // ----------------------------------------------------------- //
- // C++ Source Code File Name: cacheb.cpp
- // Compiler Used: MSVC40, DJGPP 2.7.2.1, GCC 2.7.2.1, HP CPP 10.24
- // Produced By: Doug Gaer
- // File Creation Date: 02/07/1997
- // Date Last Modified: 03/15/1999
- // Copyright (c) 1997 Douglas M. Gaer
- // ----------------------------------------------------------- //
- // ------------- Program Description and Details ------------- //
- // ----------------------------------------------------------- //
- /*
- The VBD C++ classes are copyright (c) 1997, by Douglas M. Gaer.
- All those who put this code or its derivatives in a commercial
- product MUST mention this copyright in their documentation for
- users of the products in which this code or its derivative
- classes are used. Otherwise, you have the freedom to redistribute
- verbatim copies of this source code, adapt it to your specific
- needs, or improve the code and release your improvements to the
- public provided that the modified files carry prominent notices
- stating that you changed the files and the date of any change.
-
- THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
- THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE
- IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE,
- YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
- CORRECTION.
-
- The Cacheb class is use as base class for the Cache class. It
- incorporates functions that are independent of the bucket type.
- The cache is used to handle requests for file-based objects. The
- cache must determine whether an object is already loaded. If the
- object is not loaded the cache reserves a bucket and loads the
- object into memory. This cache design uses cache pointers to
- reference cache buckets directly, with each cache pointer being
- initialized after the bucket is reserved. The least-recently
- reserved cache bucket is overwritten when the cache fills up.
- */
- // ----------------------------------------------------------- //
- #include "cacheb.h"
- #include "bucketb.h"
-
- Cacheb::Cacheb(Bucketb *b, int n, unsigned bkt_size)
- // Assumes n buckets of size bkt_size have already been
- // allocated. Sets up their Prior and Next pointers to form
- // a circular list.
- : fptr(0)
- {
- Bucketb *p = b;
- for (int i = 0; i<n; i++) {
- p->MakeNull();
- p->Prior = (Bucketb *)((char *)p - bkt_size);
- p->Next = (Bucketb *)((char *)p + bkt_size);
- p = p->Next;
- }
- // Make the list circular
- Bucketb *tail = (Bucketb *)((char *)b + (n-1)*bkt_size);
- tail->Next = b;
- b->Prior = tail;
- // Set up other cache variables
- nbuckets = n; Head = b;
- Hits = 0; Misses = 0; FastBinds = 0;
- }
-
- Cacheb::~Cacheb()
- {
- // Destructor provided for virtuality
- }
-
- void Cacheb::MoveToFront(Bucketb *b)
- // Logically move bucket to front of list, so that it is
- // treated as the most recently reserved bucket.
- {
- if (b == Head->Prior) { // b is tail
- Head = Head->Prior;
- }
- else if (b != Head) {
- // Unhook bucket from where it is
- b->Prior->Next = b->Next;
- b->Next->Prior = b->Prior;
- // Put it before Head
- b->Next = Head;
- b->Prior = Head->Prior;
- b->Prior->Next = b;
- Head->Prior = b;
- Head = b;
- }
- }
-
- void Cacheb::Flush(int empty_bkts)
- // Flushes all buckets in the cache. Makes them empty if
- // empty_bkts is true. Checks for dangling cache pointers.
- {
- // Flush, starting at the front
- Bucketb *b = Head;
- do {
- if (empty_bkts && b->IsLocked())
- #ifdef CPP_EXCEPTIONS
- throw CDanglingPtr();
- #else
- Error->SignalException(EHandler::DanglingPtr);
- #endif
-
- if (fptr->ReadyForWriting()) b->Flush(*fptr);
- if (empty_bkts) b->MakeNull();
- b = b->Next;
- } while(b != Head);
- }
-
- void Cacheb::Clear()
- // Flush all buckets in the cache, and then null them out.
- // An exception is thrown if any dangling cache pointers are found.
- {
- if (fptr) Flush(1);
- Hits = 0; Misses = 0; FastBinds = 0;
- }
-
- Bucketb *Cacheb::AcquireBkt()
- // Finds least recently reserved bucket that isn't locked,
- // flushes the bucket, and moves it to the front. Passes
- // back pointer to bucket or returns 0 if no bucket available.
- {
- Bucketb *b = Head->Prior; // Least-recently reserved bucket
- while(1) {
- if (!b->IsLocked()) break;
- b = b->Prior;
- if (b == Head->Prior) {
- #ifdef CPP_EXCPETIONS
- throw CCacheFull();
- #else
- Error->SignalException(EHandler::CacheFull);
- #endif
- return 0;
- }
- }
- // Flush any data that might be in the bucket and move it to
- // the front so it becomes the most-recently reserved bucket.
- b->Flush(*fptr);
- MoveToFront(b);
- return b;
- }
-
- Bucketb *Cacheb::FindBkt(FAU Address)
- // Searches for a bucket in the cache connected to file address.
- // Returns pointer or 0 if the bucket is not found.
- {
- // Start search from front, (most recently reserved bucket)
- Bucketb *b = Head;
- do {
- if (b->Address == Address) return b;
- b = b->Next;
- } while(b != Head);
- return 0;
- }
-
- Bucketb *Cacheb::ReserveBkt(FAU Address, int ensure_loaded)
- // Reserves a bucket for file address. If ensure_loaded == 1,
- // then if the data at the address is not already in bucket,
- // and is loaded in. Moves bucket to the front and passes back
- // a pointer to bucket, which may be 0 if there is an error.
- {
- Bucketb *b;
-
- if (Address == 0) return 0; // No sense reserving bucket
-
- b = FindBkt(Address);
- if (b == 0) { // Bkt data not loaded, so acquire a bucket
- Misses++;
- b = AcquireBkt();
- if (b) {
- b->Address = Address;
- if (ensure_loaded && Address) {
- b->Fetch(*fptr);
- }
- // If failure fetching data, return null bucket to
- // signal failure, else lock the bucket.
- if (!fptr->IsOK()) b = 0; else b->Lock();
- }
- }
- else {
- Hits++;
- MoveToFront(b);
- b->Lock();
- }
-
- return b;
- }
- // ----------------------------------------------------------- //
- // ------------------------------- //
- // --------- End of File --------- //
- // ------------------------------- //
-