{"id":23437872,"url":"https://github.com/sanam2405/memecache","last_synced_at":"2025-04-09T19:22:19.612Z","repository":{"id":222150910,"uuid":"755750416","full_name":"sanam2405/memecache","owner":"sanam2405","description":"A minimal, no pain, in-memory caching library for general use 📝","archived":false,"fork":false,"pushed_at":"2025-03-10T12:02:13.000Z","size":47,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-10T13:22:02.851Z","etag":null,"topics":["cache","inmemory-cache"],"latest_commit_sha":null,"homepage":"https://sanam.live/memecache","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sanam2405.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-02-10T23:40:46.000Z","updated_at":"2025-03-10T12:02:16.000Z","dependencies_parsed_at":"2024-03-12T05:49:33.284Z","dependency_job_id":null,"html_url":"https://github.com/sanam2405/memecache","commit_stats":null,"previous_names":["sanam2405/memecache"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanam2405%2Fmemecache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanam2405%2Fmemecache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanam2405%2Fmemecache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanam2405%2Fmemecache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sanam2405","download_url":"https://codeload.github.com/sanam2405/memecache/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248095513,"owners_count":21046861,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","inmemory-cache"],"created_at":"2024-12-23T14:38:49.945Z","updated_at":"2025-04-09T19:22:19.585Z","avatar_url":"https://github.com/sanam2405.png","language":"C++","readme":"# Memecache\n\n## _A minimal, no pain, in-memory caching library for general use_\n\nThis is minimal, _**thread-safe caching library**_, with the support for multiple cache eviction policies and can also extend _custom cache eviction policies_.\n\nThe currently supported cache eviction policies include:\n\n- _First-In/First-Out (FIFO)_\n- _Last-In/First-Out (LIFO)_\n- _Least Recently Used (LRU)_\n\nAn exhaustive list of cache algorithms can be found here - [Wikipedia](https://en.wikipedia.org/wiki/Cache_algorithms)\n\n## Usage\n\nTo use this library, it is necessary to include the header containing the _cache implementation_ (`cache.hpp` file)\nand the corresponding appropriate headers containing the required cache eviction policy as per the requirement.\nIf a policy is not mentioned explicitly, then `NoCachePolicy` is be implemented whereby the replacement candidate for removal is chosen to be the first key that was added in the internal `key_storage` container.\n\nCurrently there are three cache eviction policies supported:\n\n- `fifo_cache_policy.hpp`\n- `lifo_cache_policy.hpp`\n- `lru_cache_policy.hpp`\n\n### An example usage of the LRU policy:\n\n```cpp\n#include \"cache.hpp\"\n#include \"lru_cache_policy.hpp\"\n\n// alias for easy class typing\ntemplate \u003ctypename Key, typename Value\u003e\nusing lru_cache_t = typename caches::fixed_sized_cache\u003cKey, Value, caches::LRUCachePolicy\u003e;\n\nvoid memecache(...) {\n  constexpr std::size_t CACHE_SIZE = 256;\n  lru_cache_t\u003cchar, int\u003e cache(CACHE_SIZE);\n\n  lru_cache.Put('M', 24);\n  lru_cache.Put('P', 5);\n  lru_cache.Put('B', 2001);\n\n  std::cout \u003c\u003c \"Using LRU Eviction Policy\\n\"\n            \u003c\u003c \"Value for key '\"\n            \u003c\u003c \"M\"\n            \u003c\u003c \"': \" \u003c\u003c lru_cache.Get('M') \u003c\u003c '\\n';\n  std::cout \u003c\u003c \"Value for key '\"\n            \u003c\u003c \"P\"\n            \u003c\u003c \"': \" \u003c\u003c lru_cache.Get('P') \u003c\u003c '\\n';\n  std::cout \u003c\u003c \"Value for key '\"\n            \u003c\u003c \"B\"\n            \u003c\u003c \"': \" \u003c\u003c lru_cache.Get('B') \u003c\u003c '\\n';\n  /*\n  Output:\n\n    Using LRU Eviction Policy\n    Value for key 'M': 24\n    Value for key 'P': 5\n    Value for key 'B': 2001\n\n  */\n}\n```\n\n### An example usage of _memecache_ demonstrating its thread-safety:\n\n```cpp\n#include \"include/cache.hpp\"\n#include \"include/fifo_cache_policy.hpp\"\n#include \"include/lifo_cache_policy.hpp\"\n#include \u003ciostream\u003e\n#include \u003cmutex\u003e\n#include \u003cthread\u003e\n\n// mutex to synchronize access to std::cout\nstd::mutex cout_mutex;\n\n// alias for easy class typing\ntemplate \u003ctypename Key, typename Value\u003e\nusing fifo_cache_t = caches::fixed_sized_cache\u003cKey, Value, caches::FIFOCachePolicy\u003e;\ntemplate \u003ctypename Key, typename Value\u003e\nusing lifo_cache_t = caches::fixed_sized_cache\u003cKey, Value, caches::LIFOCachePolicy\u003e;\n\nvoid printLine() { std::cout \u003c\u003c \"==============================================================================\\n\"; }\n\nvoid cache_operations_fifo(fifo_cache_t\u003cstd::string, int\u003e\u0026 cache, const std::string\u0026 key, int value, bool insert)\n{\n    if (insert)\n    {\n        cache.Put(key, value);\n    }\n    else\n    {\n        try\n        {\n            // lock cout access\n            std::lock_guard\u003cstd::mutex\u003e lock(cout_mutex);\n            printLine();\n            std::cout \u003c\u003c \"Using FIFO Eviction Policy\\n\"\n                      \u003c\u003c \"Value for key '\" \u003c\u003c key \u003c\u003c \"': \" \u003c\u003c cache.Get(key) \u003c\u003c '\\n';\n        }\n        catch (const std::range_error\u0026 e)\n        {\n            std::cerr \u003c\u003c e.what() \u003c\u003c '\\n';\n        }\n    }\n}\n\nvoid cache_operations_lifo(lifo_cache_t\u003cstd::string, int\u003e\u0026 cache, const std::string\u0026 key, int value, bool insert)\n{\n    if (insert)\n    {\n        cache.Put(key, value);\n    }\n    else\n    {\n        try\n        {\n            // lock cout access\n            std::lock_guard\u003cstd::mutex\u003e lock(cout_mutex);\n            printLine();\n            std::cout \u003c\u003c \"Using LIFO Eviction Policy\\n\"\n                      \u003c\u003c \"Value for key '\" \u003c\u003c key \u003c\u003c \"': \" \u003c\u003c cache.Get(key) \u003c\u003c '\\n';\n        }\n        catch (const std::range_error\u0026 e)\n        {\n            std::cerr \u003c\u003c e.what() \u003c\u003c '\\n';\n        }\n    }\n}\n\nint main()\n{\n    std::cout \u003c\u003c \"Hello Enterpret!\\n\";\n\n    constexpr std::size_t CACHE_SIZE = 256;\n    fifo_cache_t\u003cstd::string, int\u003e fifo_cache(CACHE_SIZE);\n    lifo_cache_t\u003cstd::string, int\u003e lifo_cache(CACHE_SIZE);\n\n    // creating multiple threads to perform cache operations concurrently\n    std::thread t1(cache_operations_fifo, std::ref(fifo_cache), \"Hello\", 100, true);\n    std::thread t2(cache_operations_fifo, std::ref(fifo_cache), \"world\", 6996, true);\n    std::thread t3(cache_operations_fifo, std::ref(fifo_cache), \"Hello\", 0, false);\n    std::thread t4(cache_operations_fifo, std::ref(fifo_cache), \"world\", 0, false);\n\n    std::thread t5(cache_operations_lifo, std::ref(lifo_cache), \"Hello\", 200, true);\n    std::thread t6(cache_operations_lifo, std::ref(lifo_cache), \"world\", 7997, true);\n    std::thread t7(cache_operations_lifo, std::ref(lifo_cache), \"Hello\", 0, false);\n    std::thread t8(cache_operations_lifo, std::ref(lifo_cache), \"world\", 0, false);\n\n\n\n    // joining the threads and waiting for their completion\n    t1.join();\n    t2.join();\n    t3.join();\n    t4.join();\n\n    t5.join();\n    t6.join();\n    t7.join();\n    t8.join();\n\n    return 0;\n}\n\n\n/*\nOutput\n\nHello Enterpret!\n==============================================================================\nUsing LIFO Eviction Policy\nValue for key 'Hello': 200\n==============================================================================\nUsing LIFO Eviction Policy\nValue for key 'world': 7997\n==============================================================================\nUsing FIFO Eviction Policy\nValue for key 'Hello': 100\n==============================================================================\nUsing FIFO Eviction Policy\nValue for key 'world': 6996\n==============================================================================\n*/\n\n```\n\nA more exhaustive usage and demonstration of the library is shown in the `main.cpp` and `mainthread.cpp` files. Run the `./main`\nand `./mainthread` executables after building the project for demonstration purpose.\n\n### Creating _Custom Cache Eviction Policies_\n\nTo implement a custom cache eviction or cache replacement policy, include the `cache_policy.hpp` header file containing the _cache policy interface_ and subsequently override the `Insert(...)`, `Touch(...)`, `Erase(...)` and `ReplacementCandidate(...)` methods as per the requirements.\n\n```cpp\n    /*\n     * Cache policy abstract base class\n     * Key - Type of a key a policy works with\n     */\n    template \u003ctypename Key\u003e class ICachePolicy\n    {\n    public:\n        virtual ~ICachePolicy() = default;\n\n        /*\n         * Handles element insertion in the cache\n         * key - Key that should be used by the policy\n         */\n        virtual void Insert(const Key\u0026 key) = 0;\n\n        /*\n         * Handles request to the key-value in the cache\n         * key - Key that should be used by the policy\n         */\n        virtual void Touch(const Key\u0026 key) = 0;\n\n        /*\n         * Handles deletion of key-value from the cache\n         * key - Key that should be used by the policy\n         */\n\n        virtual void Erase(const Key\u0026 key) = 0;\n\n        /*\n         * Returns the key of the replacement candidate\n         * Key - Replacement candidate's key according to selected eviction policy\n         */\n        virtual const Key\u0026 ReplacementCandidate() const = 0;\n    };\n```\n\n### Requirements\n\n- A compatible C++11 compiler\n\n### Cloning, building and running locally\n\n- Clone the repository\n\n```console\n    git clone git@github.com:sanam2405/memecache.git\n```\n\n- Install _cmake_\n\n```console\n    brew install cmake\n```\n\n- Create a `build` directory in the root of the project\n\n```console\n    mkdir build\n    cd build\n```\n\n- Generate the build files\n\n```console\n    cmake ..\n```\n\n- Build the project\n\nFor building, use `make` if available\n\n```console\n    make\n```\n\nOtherwise use the below command for building\n\n```console\n    cmake --build .\n```\n\n- Run the executables\n\n```console\n    ./main\n    ./mainthread\n```\n\n## _Built with ❤️ by [Manas](https://sanam.live)_\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanam2405%2Fmemecache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsanam2405%2Fmemecache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanam2405%2Fmemecache/lists"}