Skip to content

Commit

Permalink
[api] Added algo.SharedMap
Browse files Browse the repository at this point in the history
  • Loading branch information
pajama-coder committed Aug 7, 2024
1 parent 7f72a5a commit adbcaf0
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 12 deletions.
160 changes: 155 additions & 5 deletions src/api/algo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,10 @@ auto Algo::hash(const pjs::Value &value) -> size_t {
//

Cache::Options::Options(pjs::Object *options) {
thread_local static pjs::ConstStr str_size("size"), str_ttl("ttl");
Value(options, str_size)
Value(options, "size")
.get(size)
.check_nullable();
Value(options, str_ttl)
Value(options, "ttl")
.get_seconds(ttl)
.check_nullable();
}
Expand Down Expand Up @@ -507,6 +506,100 @@ void Quota::Counter::finalize() {
});
}

//
// SharedMap
//

SharedMap::SharedMap(pjs::Str *name)
: m_map(Map::get(name->str()))
{
}

auto SharedMap::size() -> size_t {
return m_map->size();
}

void SharedMap::clear() {
m_map->clear();
}

bool SharedMap::erase(pjs::Str *key) {
return m_map->erase(key->data());
}

bool SharedMap::has(pjs::Str *key) {
return m_map->has(key->data());
}

bool SharedMap::get(pjs::Str *key, pjs::Value &value) {
pjs::SharedValue sv;
if (m_map->get(key->data(), sv)) {
sv.to_value(value);
return true;
} else {
return false;
}
}

void SharedMap::set(pjs::Str *key, const pjs::Value &value) {
pjs::SharedValue sv(value);
m_map->set(key->data(), sv);
}

//
// SharedMap::Map
//

std::map<std::string, SharedMap::Map*> SharedMap::Map::m_maps;
std::mutex SharedMap::Map::m_maps_mutex;

auto SharedMap::Map::get(const std::string &name) -> Map* {
std::lock_guard<std::mutex> lock(m_maps_mutex);
auto &p = m_maps[name];
if (!p) {
p = new Map;
p->retain();
}
return p;
}

auto SharedMap::Map::size() -> size_t {
std::lock_guard<std::mutex> lock(m_mutex);
return m_map.size();
}

void SharedMap::Map::clear() {
std::lock_guard<std::mutex> lock(m_mutex);
m_map.clear();
}

bool SharedMap::Map::erase(pjs::Str::CharData *key) {
std::lock_guard<std::mutex> lock(m_mutex);
auto i = m_map.find(key);
if (i == m_map.end()) return false;
m_map.erase(i);
return true;
}

bool SharedMap::Map::has(pjs::Str::CharData *key) {
std::lock_guard<std::mutex> lock(m_mutex);
auto i = m_map.find(key);
return i != m_map.end();
}

bool SharedMap::Map::get(pjs::Str::CharData *key, pjs::SharedValue &value) {
std::lock_guard<std::mutex> lock(m_mutex);
auto i = m_map.find(key);
if (i == m_map.end()) return false;
value = i->second;
return true;
}

void SharedMap::Map::set(pjs::Str::CharData *key, const pjs::SharedValue &value) {
std::lock_guard<std::mutex> lock(m_mutex);
m_map[key] = value;
}

//
// URLRouter
//
Expand Down Expand Up @@ -1469,8 +1562,16 @@ template<> void ClassDef<Cache>::init() {
ctor([](Context &ctx) -> Object* {
Function *allocate = nullptr, *free = nullptr;
Object *options = nullptr;
if (!ctx.arguments(0, &allocate, &free, &options)) return nullptr;
return Cache::make(options, allocate, free);
if (
ctx.try_arguments(2, &allocate, &free, &options) ||
ctx.try_arguments(1, &allocate, &options) ||
ctx.try_arguments(0, &options)
) {
return Cache::make(options, allocate, free);
} else {
ctx.error_argument_type(0, "a function or an object");
return nullptr;
}
});

method("get", [](Context &ctx, Object *obj, Value &ret) {
Expand Down Expand Up @@ -1555,6 +1656,54 @@ template<> void ClassDef<Constructor<Quota>>::init() {
ctor();
}

//
// SharedMap
//

template<> void ClassDef<SharedMap>::init() {
ctor([](Context &ctx) -> Object * {
Str *name;
if (!ctx.arguments(1, &name)) return nullptr;
return SharedMap::make(name);
});

accessor("size", [](Object *obj, Value &ret) { ret.set((int)obj->as<SharedMap>()->size()); });

method("clear", [](Context &ctx, Object *obj, Value &ret) {
obj->as<SharedMap>()->clear();
});

method("delete", [](Context &ctx, Object *obj, Value &ret) {
Str *key;
if (!ctx.arguments(1, &key)) return;
ret.set(obj->as<SharedMap>()->erase(key));
});

method("has", [](Context &ctx, Object *obj, Value &ret) {
Str *key;
if (!ctx.arguments(1, &key)) return;
ret.set(obj->as<SharedMap>()->has(key));
});

method("get", [](Context &ctx, Object *obj, Value &ret) {
Str *key;
if (!ctx.arguments(1, &key)) return;
if (!obj->as<SharedMap>()->get(key, ret)) ret = Value::undefined;
});

method("set", [](Context &ctx, Object *obj, Value &ret) {
Str *key;
Value value;
if (!ctx.arguments(2, &key, &value)) return;
obj->as<SharedMap>()->set(key, value);
});
}

template<> void ClassDef<Constructor<SharedMap>>::init() {
super<Function>();
ctor();
}

//
// URLRouter
//
Expand Down Expand Up @@ -1882,6 +2031,7 @@ template<> void ClassDef<Algo>::init() {
ctor();
variable("Cache", class_of<Constructor<Cache>>());
variable("Quota", class_of<Constructor<Quota>>());
variable("SharedMap", class_of<Constructor<SharedMap>>());
variable("URLRouter", class_of<Constructor<URLRouter>>());
variable("LoadBalancer", class_of<Constructor<LoadBalancer>>());
variable("HashingLoadBalancer", class_of<Constructor<HashingLoadBalancer>>());
Expand Down
58 changes: 58 additions & 0 deletions src/api/algo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,64 @@ class Quota : public pjs::ObjectTemplate<Quota> {
friend class pjs::ObjectTemplate<Quota>;
};

//
// SharedMap
//

class SharedMap : public pjs::ObjectTemplate<SharedMap> {
public:
SharedMap(pjs::Str *name);

auto size() -> size_t;
void clear();
bool erase(pjs::Str *key);
bool has(pjs::Str *key);
bool get(pjs::Str *key, pjs::Value &value);
void set(pjs::Str *key, const pjs::Value &value);

private:

//
// SharedMap::Map
//

class Map : public pjs::RefCountMT<Map> {
public:
static auto get(const std::string &name) -> Map*;

auto size() -> size_t;
void clear();
bool erase(pjs::Str::CharData *key);
bool has(pjs::Str::CharData *key);
bool get(pjs::Str::CharData *key, pjs::SharedValue &value);
void set(pjs::Str::CharData *key, const pjs::SharedValue &value);

private:
typedef pjs::Ref<pjs::Str::CharData> Key;

struct Hash {
size_t operator()(const Key &k) const {
std::hash<std::string> h;
return h(k->str());
}
};

struct EqualTo {
bool operator()(const Key &a, const Key &b) const {
return a->str() == b->str();
}
};

std::unordered_map<Key, pjs::SharedValue, Hash, EqualTo> m_map;
std::mutex m_mutex;

static std::map<std::string, Map*> m_maps;
static std::mutex m_maps_mutex;
};

pjs::Ref<Map> m_map;
};

//
// ResourcePool
//
Expand Down
15 changes: 13 additions & 2 deletions src/pjs/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,17 @@ void SharedValue::to_value(Value &v) const {
}
}

void SharedValue::from_value(const Value &v) {
void SharedValue::assign(const SharedValue &v) {
switch (m_t = v.m_t) {
case Value::Type::Boolean: m_v.b = v.m_v.b; break;
case Value::Type::Number: m_v.n = v.m_v.n; break;
case Value::Type::String: m_v.s = v.m_v.s->retain(); break;
case Value::Type::Object: if (auto o = m_v.o = v.m_v.o) o->retain(); break;
default: break;
}
}

void SharedValue::assign(const Value &v) {
switch (m_t = v.type()) {
case Value::Type::Boolean: m_v.b = v.b(); break;
case Value::Type::Number: m_v.n = v.n(); break;
Expand Down Expand Up @@ -930,8 +940,9 @@ auto SharedObject::to_object() -> Object* {
for (auto i = 0, n = b->length; i < n; i++) {
const auto &e = b->entries[i];
if (e.k) {
Ref<Str> k(Str::make(e.k));
Value v; e.v.to_value(v);
obj->set(Str::make(e.k), v);
obj->set(k, v);
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/pjs/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1913,10 +1913,12 @@ inline auto Value::value_of() const -> double {
class SharedValue {
public:
SharedValue() : m_t(Value::Type::Empty) {}
SharedValue(const Value &v) { from_value(v); }
SharedValue(const SharedValue &v) { assign(v); }
SharedValue(const Value &v) { assign(v); }
~SharedValue() { release(); }

auto operator=(const Value &v) -> SharedValue& { release(); from_value(v); return *this; }
auto operator=(const SharedValue &v) -> SharedValue& { release(); assign(v); return *this; }
auto operator=(const Value &v) -> SharedValue& { release(); assign(v); return *this; }
void to_value(Value &v) const;

private:
Expand All @@ -1928,7 +1930,8 @@ class SharedValue {
SharedObject* o;
} m_v;

void from_value(const Value &v);
void assign(const SharedValue &v);
void assign(const Value &v);
void release();
};

Expand Down
2 changes: 0 additions & 2 deletions src/thread.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@

namespace pipy {

class WorkerThread;

//
// Thread
//
Expand Down

0 comments on commit adbcaf0

Please sign in to comment.