rippled
Loading...
Searching...
No Matches
CanProcess.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2024 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_BASICS_CANPROCESS_H_INCLUDED
21#define RIPPLE_BASICS_CANPROCESS_H_INCLUDED
22
23#include <functional>
24#include <mutex>
25#include <set>
26
67{
68public:
69 template <class Mutex, class Collection, class Item>
70 CanProcess(Mutex& mtx, Collection& collection, Item const& item)
71 : cleanup_(insert(mtx, collection, item))
72 {
73 }
74
76 {
77 if (cleanup_)
78 cleanup_();
79 }
80
81 explicit
82 operator bool() const
83 {
84 return static_cast<bool>(cleanup_);
85 }
86
87private:
88 template <bool useIterator, class Mutex, class Collection, class Item>
89 std::function<void()>
90 doInsert(Mutex& mtx, Collection& collection, Item const& item)
91 {
93 // TODO: Use structured binding once LLVM 16 is the minimum supported
94 // version. See also: https://github.com/llvm/llvm-project/issues/48582
95 // https://github.com/llvm/llvm-project/commit/127bf44385424891eb04cff8e52d3f157fc2cb7c
96 auto const insertResult = collection.insert(item);
97 auto const it = insertResult.first;
98 if (!insertResult.second)
99 return {};
100 if constexpr (useIterator)
101 return [&, it]() {
102 std::unique_lock<Mutex> lock(mtx);
103 collection.erase(it);
104 };
105 else
106 return [&]() {
107 std::unique_lock<Mutex> lock(mtx);
108 collection.erase(item);
109 };
110 }
111
112 // Generic insert() function doesn't use iterators because they may get
113 // invalidated
114 template <class Mutex, class Collection, class Item>
115 std::function<void()>
116 insert(Mutex& mtx, Collection& collection, Item const& item)
117 {
118 return doInsert<false>(mtx, collection, item);
119 }
120
121 // Specialize insert() for std::set, which does not invalidate iterators for
122 // insert and erase
123 template <class Mutex, class Item>
124 std::function<void()>
125 insert(Mutex& mtx, std::set<Item>& collection, Item const& item)
126 {
127 return doInsert<true>(mtx, collection, item);
128 }
129
130 // If set, then the item is "usable"
132};
133
134#endif
RAII class to check if an Item is already being processed on another thread, as indicated by it's pre...
Definition: CanProcess.h:67
CanProcess(Mutex &mtx, Collection &collection, Item const &item)
Definition: CanProcess.h:70
std::function< void()> insert(Mutex &mtx, std::set< Item > &collection, Item const &item)
Definition: CanProcess.h:125
std::function< void()> cleanup_
Definition: CanProcess.h:131
std::function< void()> insert(Mutex &mtx, Collection &collection, Item const &item)
Definition: CanProcess.h:116
std::function< void()> doInsert(Mutex &mtx, Collection &collection, Item const &item)
Definition: CanProcess.h:90