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_;
};
};