14#ifndef OR_TOOLS_MATH_OPT_STORAGE_UPDATE_TRACKERS_H_
15#define OR_TOOLS_MATH_OPT_STORAGE_UPDATE_TRACKERS_H_
24#include "absl/base/thread_annotations.h"
25#include "absl/container/flat_hash_set.h"
26#include "absl/log/check.h"
27#include "absl/synchronization/mutex.h"
43template <
typename Data>
47 using IdDataPair = std::pair<UpdateTrackerId, std::unique_ptr<Data>>;
56 template <
typename... T>
99 Data&
GetData(UpdateTrackerId update_tracker);
100 const Data&
GetData(UpdateTrackerId update_tracker)
const;
108 static typename std::vector<IdDataPair>::iterator FindTracker(
109 std::vector<IdDataPair>& v, UpdateTrackerId update_tracker);
110 static typename std::vector<IdDataPair>::const_iterator FindTracker(
111 const std::vector<IdDataPair>& v, UpdateTrackerId update_tracker);
115 void UpdateHasPendingActions() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
117 mutable
absl::Mutex mutex_;
120 UpdateTrackerId next_update_tracker_ ABSL_GUARDED_BY(mutex_) = {};
126 std::vector<IdDataPair> pending_new_trackers_ ABSL_GUARDED_BY(mutex_);
129 std::vector<IdDataPair> trackers_;
136 absl::flat_hash_set<UpdateTrackerId> pending_removed_trackers_
137 ABSL_GUARDED_BY(mutex_);
146 std::atomic<bool> has_pending_actions_ =
false;
153template <
typename Data>
154void UpdateTrackers<Data>::UpdateHasPendingActions() {
155 has_pending_actions_ =
156 !pending_new_trackers_.empty() || !pending_removed_trackers_.empty();
159template <
typename Data>
160template <
typename... Args>
162 const absl::MutexLock lock(&mutex_);
164 const UpdateTrackerId update_tracker = next_update_tracker_;
165 ++next_update_tracker_;
167 pending_new_trackers_.push_back(std::make_pair(
168 update_tracker, std::make_unique<Data>(std::forward<Args>(args)...)));
169 UpdateHasPendingActions();
171 return update_tracker;
174template <
typename Data>
175typename std::vector<typename UpdateTrackers<Data>::IdDataPair>::iterator
177 const UpdateTrackerId update_tracker) {
178 return std::find_if(v.begin(), v.end(), [&](
const IdDataPair& pair) {
179 return pair.first == update_tracker;
183template <
typename Data>
184typename std::vector<typename UpdateTrackers<Data>::IdDataPair>::const_iterator
185UpdateTrackers<Data>::FindTracker(
const std::vector<IdDataPair>& v,
186 const UpdateTrackerId update_tracker) {
187 return std::find_if(v.begin(), v.end(), [&](
const IdDataPair& pair) {
188 return pair.first == update_tracker;
192template <
typename Data>
194 const UpdateTrackerId update_tracker) {
195 const absl::MutexLock lock(&mutex_);
200 const auto found_new = FindTracker(pending_new_trackers_, update_tracker);
201 if (found_new != pending_new_trackers_.end()) {
202 pending_new_trackers_.erase(found_new);
203 UpdateHasPendingActions();
210 CHECK(pending_removed_trackers_.find(update_tracker) ==
211 pending_removed_trackers_.end())
212 <<
"Update tracker " << update_tracker <<
" does not exist";
215 const auto found_existing = FindTracker(trackers_, update_tracker);
216 CHECK(found_existing != trackers_.end())
217 <<
"Update tracker " << update_tracker <<
" does not exist";
219 pending_removed_trackers_.insert(update_tracker);
220 UpdateHasPendingActions();
223template <
typename Data>
224const std::vector<typename UpdateTrackers<Data>::IdDataPair>&
235 if (has_pending_actions_.load(std::memory_order_relaxed)) {
236 const absl::MutexLock lock(&mutex_);
241 [&](
const IdDataPair& pair) ABSL_SHARED_LOCKS_REQUIRED(mutex_) {
242 const auto found = pending_removed_trackers_.find(pair.first);
243 if (found == pending_removed_trackers_.end()) {
246 pending_removed_trackers_.erase(found);
249 DCHECK(pending_removed_trackers_.empty());
250 pending_removed_trackers_.clear();
253 trackers_.insert(trackers_.end(),
254 std::make_move_iterator(pending_new_trackers_.begin()),
255 std::make_move_iterator(pending_new_trackers_.end()));
256 pending_new_trackers_.clear();
258 UpdateHasPendingActions();
263template <
typename Data>
265 const absl::MutexLock lock(&mutex_);
271 const auto found_new = FindTracker(pending_new_trackers_, update_tracker);
272 if (found_new != pending_new_trackers_.end()) {
273 return *found_new->second;
278 CHECK(pending_removed_trackers_.find(update_tracker) ==
279 pending_removed_trackers_.end())
280 <<
"Update tracker " << update_tracker <<
" does not exist";
283 const auto found_existing = FindTracker(trackers_, update_tracker);
284 CHECK(found_existing != trackers_.end())
285 <<
"Update tracker " << update_tracker <<
" does not exist";
287 return *found_existing->second;
290template <
typename Data>
292 UpdateTrackerId update_tracker)
const {
293 const absl::MutexLock lock(&mutex_);
296 const auto found_new = FindTracker(pending_new_trackers_, update_tracker);
297 if (found_new != pending_new_trackers_.end()) {
298 return *found_new->second;
303 CHECK(pending_removed_trackers_.find(update_tracker) ==
304 pending_removed_trackers_.end())
305 <<
"Update tracker " << update_tracker <<
" does not exist";
308 const auto found_existing = FindTracker(trackers_, update_tracker);
309 CHECK(found_existing != trackers_.end())
310 <<
"Update tracker " << update_tracker <<
" does not exist";
312 return *found_existing->second;
const std::vector< IdDataPair > & GetUpdatedTrackers()
Data & GetData(UpdateTrackerId update_tracker)
UpdateTrackerId NewUpdateTracker(T &&... args)
std::pair< UpdateTrackerId, std::unique_ptr< Data > > IdDataPair
A pair (tracker_id, tracker_data).
void DeleteUpdateTracker(UpdateTrackerId update_tracker)
void STLEraseAllFromSequenceIf(T *v, P pred)
Remove each element e in v satisfying pred(e).
An object oriented wrapper for quadratic constraints in ModelStorage.