tesseract  3.03
/usr/local/google/home/jbreiden/tesseract-ocr-read-only/ccutil/object_cache.h
Go to the documentation of this file.
00001 
00002 // File:        object_cache.h
00003 // Description: A string indexed object cache.
00004 // Author:      David Eger
00005 // Created:     Fri Jan 27 12:08:00 PST 2012
00006 //
00007 // (C) Copyright 2012, Google Inc.
00008 // Licensed under the Apache License, Version 2.0 (the "License");
00009 // you may not use this file except in compliance with the License.
00010 // You may obtain a copy of the License at
00011 // http://www.apache.org/licenses/LICENSE-2.0
00012 // Unless required by applicable law or agreed to in writing, software
00013 // distributed under the License is distributed on an "AS IS" BASIS,
00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 // See the License for the specific language governing permissions and
00016 // limitations under the License.
00017 //
00019 
00020 #ifndef TESSERACT_CCUTIL_OBJECT_CACHE_H_
00021 #define TESSERACT_CCUTIL_OBJECT_CACHE_H_
00022 
00023 #include "ccutil.h"
00024 #include "errcode.h"
00025 #include "genericvector.h"
00026 #include "tesscallback.h"
00027 
00028 namespace tesseract {
00029 
00030 // A simple object cache which maps a string to an object of type T.
00031 // Usually, these are expensive objects that are loaded from disk.
00032 // Reference counting is performed, so every Get() needs to be followed later
00033 // by a Free().  Actual deletion is accomplished by DeleteUnusedObjects().
00034 template<typename T>
00035 class ObjectCache {
00036  public:
00037   ObjectCache() {}
00038   ~ObjectCache() {
00039     mu_.Lock();
00040     for (int i = 0; i < cache_.size(); i++) {
00041       if (cache_[i].count > 0) {
00042         tprintf("ObjectCache(%p)::~ObjectCache(): WARNING! LEAK! object %p "
00043                 "still has count %d (id %s)\n",
00044                 this, cache_[i].object, cache_[i].count,
00045                 cache_[i].id.string());
00046       } else {
00047         delete cache_[i].object;
00048         cache_[i].object = NULL;
00049       }
00050     }
00051     mu_.Unlock();
00052   }
00053 
00054   // Return a pointer to the object identified by id.
00055   // If we haven't yet loaded the object, use loader to load it.
00056   // If loader fails to load it, record a NULL entry in the cache
00057   // and return NULL -- further attempts to load will fail (even
00058   // with a different loader) until DeleteUnusedObjects() is called.
00059   // We delete the given loader.
00060   T *Get(STRING id,
00061          TessResultCallback<T *> *loader) {
00062     T *retval = NULL;
00063     mu_.Lock();
00064     for (int i = 0; i < cache_.size(); i++) {
00065       if (id == cache_[i].id) {
00066         retval = cache_[i].object;
00067         if (cache_[i].object != NULL) {
00068           cache_[i].count++;
00069         }
00070         mu_.Unlock();
00071         delete loader;
00072         return retval;
00073       }
00074     }
00075     cache_.push_back(ReferenceCount());
00076     ReferenceCount &rc = cache_.back();
00077     rc.id = id;
00078     retval = rc.object = loader->Run();
00079     rc.count = (retval != NULL) ? 1 : 0;
00080     mu_.Unlock();
00081     return retval;
00082   }
00083 
00084   // Decrement the count for t.
00085   // Return whether we knew about the given pointer.
00086   bool Free(T *t) {
00087     if (t == NULL) return false;
00088     mu_.Lock();
00089     for (int i = 0; i < cache_.size(); i++) {
00090       if (cache_[i].object == t) {
00091         --cache_[i].count;
00092         mu_.Unlock();
00093         return true;
00094       }
00095     }
00096     mu_.Unlock();
00097     return false;
00098   }
00099 
00100   void DeleteUnusedObjects() {
00101     mu_.Lock();
00102     for (int i = cache_.size() - 1; i >= 0; i--) {
00103       if (cache_[i].count <= 0) {
00104         delete cache_[i].object;
00105         cache_.remove(i);
00106       }
00107     }
00108     mu_.Unlock();
00109   }
00110 
00111  private:
00112   struct ReferenceCount {
00113     STRING id;  // A unique ID to identify the object (think path on disk)
00114     T *object;  // A copy of the object in memory.  Can be delete'd.
00115     int count;  // A count of the number of active users of this object.
00116   };
00117 
00118   CCUtilMutex mu_;
00119   GenericVector<ReferenceCount> cache_;
00120 };
00121 
00122 }  // namespace tesseract
00123 
00124 
00125 #endif  // TESSERACT_CCUTIL_OBJECT_CACHE_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines