Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Functional] Adds occa::function and occa::array #442

Merged
merged 20 commits into from
Jan 17, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[Utils] Adds atomic store for key-value pairs
  • Loading branch information
dmed256 committed Jan 17, 2021
commit b53efe306780bad64e042e155ac030664d58c727
100 changes: 100 additions & 0 deletions include/occa/utils/store.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#ifndef OCCA_UTILS_STORE_HEADER
#define OCCA_UTILS_STORE_HEADER

#include <cmath>
#include <map>
#include <memory>

#include <occa/utils/hash.hpp>
#include <occa/utils/mutex.hpp>

#define OCCA_ATOMIC_STORE_HASH_SIZE 128

namespace occa {
template <class HashableKeyType, class ValueType>
class store_t {
private:
using ValueSharedPtr = std::shared_ptr<ValueType>;
using storeMapType = std::map<HashableKeyType, ValueSharedPtr>;

storeMapType store;
mutex_t *mutexList;

inline mutex_t& getMutexForKey(const HashableKeyType &key) {
return mutexList[
std::abs(hash(key).getInt()) % OCCA_ATOMIC_STORE_HASH_SIZE
];
}

public:
store_t() :
mutexList(new mutex_t[OCCA_ATOMIC_STORE_HASH_SIZE]) {}

~store_t() {
delete [] mutexList;
}

void lock(const HashableKeyType &key) {
getMutexForKey(key).lock();
}

void unlock(const HashableKeyType &key) {
getMutexForKey(key).unlock();
}

bool has(const HashableKeyType &key) const {
lock(key);
const bool hasKey = (
store.find(key) != store.end()
);
unlock(key);

return hasKey;
}

size_t size() const {
mutex_t &mutex = mutexList[0];
size_t mapSize;

mutex.lock();
mapSize = store.size();
mutex.unlock();

return mapSize;
}

ValueSharedPtr unsafeGet(const HashableKeyType &key) {
typename storeMapType::iterator it = store.find(key);
if (it != store.end()) {
return it->second;
}
return nullptr;
}

ValueSharedPtr get(const HashableKeyType &key) {
ValueSharedPtr valuePtr;

lock(key);
valuePtr = unsafeGet(key);
unlock(key);

return valuePtr;
}

bool unsafeGetOrCreate(const HashableKeyType &key, ValueSharedPtr &valuePtr) {
typename storeMapType::iterator it = store.find(key);

if (it != store.end()) {
valuePtr = it->second;
return false;
}

valuePtr = std::make_shared<ValueType>();
store[key] = valuePtr;

return true;
}
};
}

#endif
102 changes: 102 additions & 0 deletions src/occa/internal/utils/store.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#ifndef OCCA_UTILS_STORE_HEADER
#define OCCA_UTILS_STORE_HEADER

#include <cmath>
#include <map>
#include <memory>

#include <occa/utils/hash.hpp>
#include <occa/utils/mutex.hpp>

#define OCCA_ATOMIC_STORE_HASH_SIZE 128

namespace occa {
template <class HashableKeyType, class ValueType>
class store_t {
private:
using ValueSharedPtr = std::shared_ptr<ValueType>;
using storeMapType = std::map<HashableKeyType, ValueSharedPtr>;

storeMapType store;
mutex_t *mutexList;

inline mutex_t& getMutexForKey(const HashableKeyType &key) {
return mutexList[
std::abs(hash(key).getInt()) % OCCA_ATOMIC_STORE_HASH_SIZE
];
}

public:
store_t() :
mutexList(new mutex_t[OCCA_ATOMIC_STORE_HASH_SIZE]) {}

~store_t() {
delete [] mutexList;
}

void lock(const HashableKeyType &key) {
getMutexForKey(key).lock();
}

void unlock(const HashableKeyType &key) {
getMutexForKey(key).unlock();
}

bool has(const HashableKeyType &key) const {
lock(key);
const bool hasKey = (
store.find(key) != store.end()
);
unlock(key);

return hasKey;
}

size_t size() const {
mutex_t &mutex = mutexList[0];
size_t mapSize;

mutex.lock();
mapSize = store.size();
mutex.unlock();

return mapSize;
}

ValueSharedPtr unsafeGet(const HashableKeyType &key) {
typename storeMapType::iterator it = store.find(key);
if (it != store.end()) {
return it->second;
}
return nullptr;
}

ValueSharedPtr get(const HashableKeyType &key) {
ValueSharedPtr valuePtr;

lock(key);
valuePtr = unsafeGet(key);
unlock(key);

return valuePtr;
}

bool unsafeGetOrCreate(const HashableKeyType &key, ValueSharedPtr &valuePtr) {
bool createdValuePtr = false;

typename storeMapType::iterator it = store.find(key);
if (it != store.end()) {
valuePtr = it->second;
} else {
valuePtr = std::make_shared<ValueType>();
store[key] = valuePtr;

createdValuePtr = true;
}

return createdValuePtr;
}
};
}

#endif