{"id":19142675,"url":"https://github.com/jgaa/glad","last_synced_at":"2025-08-22T13:09:58.186Z","repository":{"id":160418553,"uuid":"634764900","full_name":"jgaa/glad","owner":"jgaa","description":"Some useful algorithms / building bricks built on top of boost.Asio","archived":false,"fork":false,"pushed_at":"2023-08-15T10:09:21.000Z","size":686,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-22T19:25:25.657Z","etag":null,"topics":["asio","header-only-library"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jgaa.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,"publiccode":null,"codemeta":null}},"created_at":"2023-05-01T05:58:49.000Z","updated_at":"2024-10-13T23:36:05.000Z","dependencies_parsed_at":"2024-11-09T07:40:43.452Z","dependency_job_id":null,"html_url":"https://github.com/jgaa/glad","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jgaa/glad","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jgaa%2Fglad","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jgaa%2Fglad/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jgaa%2Fglad/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jgaa%2Fglad/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jgaa","download_url":"https://codeload.github.com/jgaa/glad/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jgaa%2Fglad/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259567095,"owners_count":22877640,"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":["asio","header-only-library"],"created_at":"2024-11-09T07:28:05.719Z","updated_at":"2025-06-13T02:33:10.829Z","avatar_url":"https://github.com/jgaa.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The Glad Project\n\nMy intention is to create and implement a handful of useful algorithms in C++ 20, primarily for use in my own applications. But if you find something useful here, feel free to use it and to contribute suggestions and pull requests.\n\nThe first one is an asynchronous \"smart\" cache designed for use-cases like caching API-keys/RBAC data in web-services. \n\nThe project is named after a tiny, very ill puppy one of my dogs found in my garden late one evening. Despite a tough and difficult start of his life, he has always been very very happy. *Glad* is the Norwegian word for happy ;)\n\n![Glad the dog](glad-the-dog/images/glad02.jpg)\n(Glad, here with his big friend Ares)\n\n## AsyncCache\n\nThe cache is a trivial key/value store. If an item is not found,\na fetch method (supplied by you) are called to asynchronously get the\nvalue. The request is paused, and the thread freed up to do other work.\n\nIf more requests comes in for a key that is in the process of being looked up,\nthey are added to a list of pending requests. When the value is available,\nany and all pending requests are resumed.\n\n**Features:**\n- Uses asio composed completion templates. Fully asynchronous continuations includes:\n    - asio/C++ 20 co-routines\n    - asio stackless co-routines\n    - asio stackfull co-routines\n    - callbacks\n    - futures\n- A value is only fetched once from the outside. If a thousand almost simultaneous requests for the same key occurs, one request is made to lookup the key using the user-supplied *fetch* functor. When the value (or an error) is available, all the requests pending for that key are resumed (as threads becomes available). \n- A key can be invalidated at any time, also when there is a fetch operation in progress and one or more requests are waiting for that key. If there are requests waiting, a new fetch operation will be initiated to ensure that the requesters get the correct value.\n- A key can be erased at any time. \n- Internally, the cache use sharding to allow fast, simultaneous processing of different keys.\n\n**Performance**\nThe performance can certainly be improved on. But at the moment, it's fast enough for my use.\n\n*perftest*, ran on my aging gaming laptop using the default settings.\n```\nStarting up (using jgaa::glad 0.1.0, boost 1_82).\nUsing 8 threads and 7 shards.\nI will create 10,000,000 objects and then read 20,000,000 existing objects using sequential keys and 10,000 failed keys (errors on fetch). \n...\nSpent 7.91382 seconds doing test stuff, including 4.33107 seconds for writes (2,308,900.62839 writes/sec) and 3.58275 seconds for reads (5,582,310.94078 reads/sec)\ncputime=46.24357, system=5.56283, minflt=1,271,752, majflt=5, nswap=0, nsignals=0, nvcsw=560,072, nivcsw=256, maxrss=3,248,528, ixrss=0, idrss=0, isrss=0\nDone\n```\n\nExamples:\n- [Simple example with C++ 20 coroutine](examples/cxx20-simple.cpp)\n\nBlog-post: [A smart asynchronous object-cache in C++](https://lastviking.eu/async_cache.html)\n\n\n## AsyncWaitFor\n\nThis class allow any number of clients to wait on it for some condition to become true.\n\nThe condition is user defined through a static lambda expression.\n\nIt expose two interesting methods:\n\n```C++\n     /*! Evaluate all waiting items against the condition.\n     *\n     *  Any items that match the condition, using the\n     *  static `validateT` template functor will be\n     *  resumed.\n     *\n     *  The method returns immediately.\n     */\n    template \u003ctypename cT\u003e\n    void onChange(const cT\u0026 condition) {\n```\n\n```C++\n    /*! Async wait for something to complete.\n     *\n     *  \\param what A variable that states what we are waiting for.\n     *  \\param duration How long we are willing to wait before we time out.\n     *  \\param token asio continuation.\n     */\n    template \u003ctypename CompletionToken, typename Rep, typename Period\u003e\n    auto wait(T what, std::chrono::duration\u003cRep, Period\u003e duration, CompletionToken\u0026\u0026 token) {\n```\n\nThe class is quite generic and can be used for many things.\n\nOne use-case is to allow callers to wait for something like an incremental\ncounter to reach a threshold, where each caller specify their own threshold value.\nThe value for a client does not need to be unique.\n\n**Features:**\n- Uses asio composed completion templates. Fully asynchronous continuations includes:\n    - asio/C++ 20 co-routines\n    - asio stackless co-routines\n    - asio stackfull co-routines\n    - callbacks\n    - futures\n- User defined type to wait for.\n- User-defined functor to evaluate when a condition is satisfied.\n\nExamples:\n- [Simple \"counter\" example with C++ 20 coroutine](examples/wait-for-counter.cpp)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjgaa%2Fglad","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjgaa%2Fglad","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjgaa%2Fglad/lists"}