src/dxapi/native/util/concurrent_object_set.h (160 lines of code) (raw):

/* * Copyright 2021 EPAM Systems, Inc * * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. Licensed under the Apache License, * Version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ #pragma once #include "platform/platform.h" #include "util/srw_lock.h" #include <unordered_set> namespace DxApiImpl { class concurrent_ptr_set_iter; class concurrent_ptr_set { friend class concurrent_ptr_set_iter; public: void add(void * v) { dx_thread::srw_write section(thisLock_); if (data_.end() == data_.find(v)) { data_.emplace(v); } } size_t size() { dx_thread::srw_read section(thisLock_); return data_.size(); } void remove(void * v) { dx_thread::srw_write section(thisLock_); data_.erase(v); } template<typename T> T * find(T * v) { dx_thread::srw_read section(thisLock_); return data_.end() == data_.find(v) ? NULL : v; } // Caution! dx_thread::srw_lock& lock() { return thisLock_; } void lock_read() { thisLock_.get_shared(); } void lock_write() { thisLock_.get_exclusive(); } void unlock_read() { thisLock_.release_shared(); } void unlock_write() { thisLock_.release_exclusive(); } protected: dx_thread::srw_lock thisLock_; std::unordered_set<void *> data_; }; class concurrent_ptr_set_iter { public: const void * next() { void * x = NULL; for (void * i : data_) { x = i; break; } if (NULL != x) { data_.erase(x); } return x; } size_t size() { return data_.size(); } concurrent_ptr_set_iter(concurrent_ptr_set &o) { o.lock_read(); data_ = o.data_; o.unlock_read(); } protected: std::unordered_set<void *> data_; }; template<typename T> class concurrent_obj_set { template<typename TT> friend class concurrent_obj_set_iter; public: void add(const T &v) { dx_thread::srw_write section(thisLock_); if (data_.end() == data_.find(v)) { data_.emplace(v); } } size_t size() { dx_thread::srw_read section(thisLock_); return data_.size(); } void clear() { dx_thread::srw_write section(thisLock_); data_.clear(); } void remove(const T &v) { dx_thread::srw_write section(thisLock_); data_.erase(v); } const T* find(const T &v) { dx_thread::srw_read section(thisLock_); return data_.end() == data_.find(v) ? NULL : &v; } // Caution! dx_thread::srw_lock& lock() { return thisLock_; } void lock_read() { thisLock_.get_shared(); } void lock_write() { thisLock_.get_exclusive(); } void unlock_read() { thisLock_.release_shared(); } void unlock_write() { thisLock_.release_exclusive(); } protected: dx_thread::srw_lock thisLock_; std::unordered_set<T> data_; }; template<typename T> class concurrent_obj_set_iter { public: bool next(T& to) { const T * x = NULL; for (auto const &i : data_) { x = &i; to = i; break; } if (NULL != x) { data_.erase(*x); return true; } return false; } size_t size() { return data_.size(); } concurrent_obj_set_iter(concurrent_obj_set<T> &o) { o.lock_read(); data_ = o.data_; o.unlock_read(); } protected: std::unordered_set<T> data_; }; };