14#ifndef OR_TOOLS_MATH_OPT_ELEMENTAL_THREAD_SAFE_ID_MAP_H_
15#define OR_TOOLS_MATH_OPT_ELEMENTAL_THREAD_SAFE_ID_MAP_H_
23#include "absl/base/thread_annotations.h"
24#include "absl/container/flat_hash_set.h"
25#include "absl/synchronization/mutex.h"
26#include "absl/types/span.h"
91 std::vector<std::pair<int64_t, V*>>
GetAll()
const;
126 int64_t
Insert(std::unique_ptr<V> value);
135 void ApplyPendingModifications() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
137 void UpdateHasPendingModifications() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
139 mutable
absl::Mutex mutex_;
140 std::atomic<
bool> has_pending_modifications_ =
false;
141 int64_t next_id_ ABSL_GUARDED_BY(mutex_) = 0;
143 std::vector<
std::pair<int64_t,
std::unique_ptr<V>>> elements_;
144 std::vector<
std::pair<int64_t,
std::unique_ptr<V>>> pending_inserts_
145 ABSL_GUARDED_BY(mutex_);
146 absl::flat_hash_set<int64_t> pending_deletes_ ABSL_GUARDED_BY(mutex_);
154absl::Span<const
std::pair<int64_t,
std::unique_ptr<V>>>
156 if (has_pending_modifications_.load(std::memory_order_relaxed)) {
157 absl::MutexLock lock(&mutex_);
158 ApplyPendingModifications();
160 return absl::MakeConstSpan(elements_);
165 absl::MutexLock lock(&mutex_);
166 return static_cast<int64_t
>(elements_.size() + pending_inserts_.size()) -
167 static_cast<int64_t
>(pending_deletes_.size());
172 absl::MutexLock lock(&mutex_);
173 if (pending_deletes_.contains(
id)) {
176 for (
const auto& [key, value] : pending_inserts_) {
181 for (
const auto& [key, value] : elements_) {
191 absl::MutexLock lock(&mutex_);
192 std::vector<std::pair<int64_t, V*>> result;
193 for (
const auto& [
id, diff] : elements_) {
194 if (!pending_deletes_.contains(
id)) {
195 result.push_back({id, diff.get()});
198 for (
const auto& [
id, diff] : pending_inserts_) {
199 if (!pending_deletes_.contains(
id)) {
200 result.push_back({id, diff.get()});
208 absl::MutexLock lock(&mutex_);
209 if (has_pending_modifications_.load()) {
210 ApplyPendingModifications();
212 for (
const auto& [key, value] : elements_) {
222 absl::MutexLock lock(&mutex_);
223 const int64_t result = next_id_;
225 pending_inserts_.push_back(std::make_pair(result, std::move(value)));
226 has_pending_modifications_ =
true;
232 absl::MutexLock lock(&mutex_);
233 for (
auto it = pending_inserts_.begin(); it != pending_inserts_.end(); ++it) {
234 if (it->first == key) {
235 pending_inserts_.erase(it);
236 UpdateHasPendingModifications();
240 for (
const auto& [k, v] : elements_) {
242 auto [unused, inserted] = pending_deletes_.insert(k);
244 UpdateHasPendingModifications();
254 if (!pending_deletes_.empty()) {
256 &elements_, [
this](
const std::pair<int64_t, std::unique_ptr<V>>& entry)
257 ABSL_SHARED_LOCKS_REQUIRED(mutex_) {
258 return pending_deletes_.contains(entry.first);
260 pending_deletes_.clear();
262 for (
auto& kv : pending_inserts_) {
263 elements_.push_back(std::move(kv));
265 pending_inserts_.clear();
266 has_pending_modifications_ =
false;
271 has_pending_modifications_ =
272 !pending_inserts_.empty() || !pending_deletes_.empty();
V * Get(int64_t id) const
V * UpdateAndGet(int64_t id)
absl::Span< const std::pair< int64_t, std::unique_ptr< V > > > UpdateAndGetAll()
int64_t Insert(std::unique_ptr< V > value)
Inserts value into the map and returns the assigned key.
ThreadSafeIdMap()=default
bool Erase(int64_t key)
Erases key from the map, returning true if the key was found in the map.
std::vector< std::pair< int64_t, V * > > GetAll() const
int64_t Size() const
The number of elements in the map.
void STLEraseAllFromSequenceIf(T *v, P pred)
Remove each element e in v satisfying pred(e).
An object oriented wrapper for quadratic constraints in ModelStorage.
For infeasible and unbounded see Not checked if options check_solutions_if_inf_or_unbounded and the If options first_solution_only is false
problem is infeasible or unbounded (default).