diff options
author | lloyd <[email protected]> | 2008-11-11 18:03:44 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-11-11 18:03:44 +0000 |
commit | 6a1e19928007c0047518e8e15b92bba116bf7a58 (patch) | |
tree | 70ce4ccb0f859884dac49895ebcff3e1d00b6b2e /src/algo_factory/algo_cache.h | |
parent | a26685bf9feee9b9457bd1313b3943701aa37367 (diff) |
Add a new cache at the level of Algorithm_Factory. Intent is to replace
the caches included in the Engines, allowing faster search/query along
and making the Engine implementations mostly or entirely stateless, also
removing the need for a two-phase initialization there.
Stil buggy + incomplete.
Diffstat (limited to 'src/algo_factory/algo_cache.h')
-rw-r--r-- | src/algo_factory/algo_cache.h | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/algo_factory/algo_cache.h b/src/algo_factory/algo_cache.h new file mode 100644 index 000000000..ab6778d14 --- /dev/null +++ b/src/algo_factory/algo_cache.h @@ -0,0 +1,111 @@ +/** +* An algorithm cache (used by Algorithm_Factory) +*/ + +#ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ +#define BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ + +#include <botan/scan_name.h> +#include <botan/mutex.h> +#include <stdexcept> +#include <map> +#include <string> + +namespace Botan { + +template<typename T> +class Algorithm_Cache + { + public: + const T* get(const SCAN_Name& request); + void add(T* algo, const std::string& provider); + + Algorithm_Cache(Mutex* m) : mutex(m) {} + ~Algorithm_Cache(); + private: + Mutex* mutex; + std::map<std::string, std::map<std::string, T*> > algorithms; + typedef typename std::map<std::string, std::map<std::string, T*> >::iterator algorithms_iterator; + typedef typename std::map<std::string, T*>::iterator provider_iterator; + }; + +/** +* Look for an algorithm implementation in the cache +*/ +template<typename T> +const T* Algorithm_Cache<T>::get(const SCAN_Name& request) + { + Mutex_Holder lock(mutex); + + algorithms_iterator algo = algorithms.find(request.as_string()); + + if(algo == algorithms.end()) + return 0; + + const std::string requested_provider = request.providers_string(); + + if(requested_provider != "") + { + provider_iterator provider = algo->second.find(requested_provider); + + if(provider != algo->second.end()) + return provider->second; + } + else // no specific provider requested: pick one + { + provider_iterator provider = algo->second.begin(); + + while(provider != algo->second.end()) + ++provider; + + provider = algo->second.begin(); + // @fixme: Just picks the lexicographically first one + if(provider != algo->second.end()) + return provider->second; + } + + return 0; // cache miss + } + +/** +* Add an implementation to the cache +*/ +template<typename T> +void Algorithm_Cache<T>::add(T* algo, const std::string& provider) + { + if(!algo) + return; + + Mutex_Holder lock(mutex); + + delete algorithms[algo->name()][provider]; + algorithms[algo->name()][provider] = algo; + } + +/** +* Algorithm_Cache<T> Destructor +*/ +template<typename T> +Algorithm_Cache<T>::~Algorithm_Cache() + { + algorithms_iterator algo = algorithms.begin(); + + while(algo != algorithms.end()) + { + provider_iterator provider = algo->second.begin(); + + while(provider != algo->second.end()) + { + delete provider->second; + ++provider; + } + + ++algo; + } + + delete mutex; + } + +} + +#endif |