Haio
0.2.X
Homebrew Asset IO/CDN
Toggle main menu visibility
Loading...
Searching...
No Matches
deduplication.cpp
Go to the documentation of this file.
1
#include <
cache/cache.hpp
>
2
3
#include <boost/asio/as_tuple.hpp>
4
#include <boost/asio/steady_timer.hpp>
5
#include <boost/asio/use_awaitable.hpp>
6
7
namespace
asio = boost::asio;
8
9
namespace
Haio::Cdn::Detail
{
10
11
/**
12
* the answer lives here rather than being read back from a store, so waiters are
13
* served even when nothing is being stored.
14
*/
15
struct
SingleFlight::Pending
{
16
std::shared_ptr<asio::steady_timer>
timer
;
17
std::optional<Result<CacheEntry>>
answer
;
18
};
19
20
SingleFlight::SingleFlight
(asio::any_io_executor executor) : executor_(std::move(executor)) {}
21
22
/**
23
* the map carries no lock because the cdn runs one io_context on one thread, so a
24
* coroutine only ever yields at a co_await and never mid update. putting the server
25
* on a thread pool means revisiting exactly this.
26
*/
27
asio::awaitable<Result<CacheEntry>>
SingleFlight::run
(
const
std::string& key,
const
Producer
& produce) {
28
if
(
const
auto
waiting = inFlight_.find(key); waiting != inFlight_.end()) {
29
auto
pending = waiting->second;
30
co_await
pending->timer->async_wait(asio::as_tuple(asio::use_awaitable));
31
if
(pending->answer)
co_return
*pending->answer;
32
// the leader left without an answer, so this caller does the work instead
33
}
34
35
auto
pending = std::make_shared<Pending>();
36
pending->timer = std::make_shared<asio::steady_timer>(executor_, asio::steady_timer::time_point::max());
37
inFlight_.emplace(key, pending);
38
39
/**
40
* the timer has to be cancelled however this ends, including by an exception, or
41
* every waiter parks forever. the answer is written before the wake, so a waiter
42
* that runs the instant it is cancelled already has something to read.
43
*/
44
struct
Wake {
45
SingleFlight
& owner;
46
std::string key;
47
std::shared_ptr<Pending> pending;
48
~Wake() {
49
owner.inFlight_.erase(key);
50
pending->timer->cancel();
51
}
52
} wake{*
this
, key, pending};
53
54
auto
made =
co_await
produce();
55
pending->answer = made;
56
co_return
made;
57
}
58
59
}
cache.hpp
Haio::Cdn::Detail::SingleFlight::SingleFlight
SingleFlight(boost::asio::any_io_executor executor)
Definition
deduplication.cpp:20
Haio::Cdn::Detail::SingleFlight::Pending::answer
std::optional< Result< CacheEntry > > answer
Definition
deduplication.cpp:17
Haio::Cdn::Detail::SingleFlight::run
boost::asio::awaitable< Result< CacheEntry > > run(const std::string &key, const Producer &produce)
Definition
deduplication.cpp:27
Haio::Cdn::Detail::SingleFlight::Pending::timer
std::shared_ptr< asio::steady_timer > timer
Definition
deduplication.cpp:16
Haio::Cdn::Detail::SingleFlight::Producer
std::function< boost::asio::awaitable< Result< CacheEntry > >()> Producer
Definition
cache.hpp:25
Haio::Cdn::Detail::SingleFlight::Pending
Definition
deduplication.cpp:15
Haio::Cdn::Detail
Definition
cache.hpp:14
library
frontend
cdn
cache
policy
deduplication.cpp
Generated by
1.18.0