Skip to content

Commit

Permalink
add new file ...
Browse files Browse the repository at this point in the history
  • Loading branch information
Dueplay committed Sep 23, 2023
1 parent 41eb174 commit f7c4c77
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 0 deletions.
Empty file added .clang-format
Empty file.
117 changes: 117 additions & 0 deletions src/core/cache.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include "core/cache.h"
#include <cassert>
#include <chrono>
#include <utility>

namespace Next {

auto GetTimeUtc() noexcept -> uint64_t {
auto mill_since_epoch =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
return mill_since_epoch;
}
Cache::CacheNode::CacheNode() noexcept { UpdataTimeStamp(); }
Cache::CacheNode::CacheNode(std::string identifier,
const std::vector<unsigned char> &data)
: identifier_(std::move(identifier)), data_(data) {
UpdataTimeStamp();
}
void Cache::CacheNode::SetIdentifier(const std::string &identifier) {
identifier_ = identifier;
}
void Cache::CacheNode::SetData(const std::vector<unsigned char> &data) {
data_ = data;
}
void Cache::CacheNode::Serialize(std::vector<unsigned char> &destination) {
size_t resource_size = data_.size();
size_t buffer_old_size = destination.size();
destination.reserve(resource_size + buffer_old_size);
destination.insert(destination.end(), data_.begin(), data_.end());
}
auto Cache::CacheNode::Size() const noexcept -> size_t { return data_.size(); }
void Cache::CacheNode::UpdataTimeStamp() noexcept {
last_access_ = GetTimeUtc();
}
auto Cache::CacheNode::GetTimeStamp() const noexcept -> uint64_t {
return last_access_;
}

Cache::Cache(size_t capacity = DEFAULT_CACHE_CAPACITY) noexcept
: capacity_(capacity), header_(std::make_unique<CacheNode>()),
tailer_(std::make_unique<CacheNode>()) {
header_->next_ = tailer_.get();
tailer_->prev_ = header_.get();
}

auto Cache::GetOccupancy() const noexcept -> size_t { return occupancy_; }
auto Cache::GetCapacity() const noexcept -> size_t { return capacity_; }

auto Cache::TryLoad(const std::string &resource_url,
std::vector<unsigned char> &destination) -> bool {
std::shared_lock<std::shared_mutex> lock(mtx_);
auto iter = mapping_.find(resource_url);
if (iter != mapping_.end()) {
iter->second->Serialize(destination);
RemoveFromList(iter->second);
AppendToListTail(iter->second);
iter->second->UpdataTimeStamp();
return true;
}
return false;
}

auto Cache::TryInsert(const std::string &resource_url,
const std::vector<unsigned char> &source) -> bool {
std::shared_lock<std::shared_mutex> lock(mtx_);
auto iter = mapping_.find(resource_url);
if (iter != mapping_.end()) {
return false;
}
auto source_size = source.size();
if (source_size > capacity_) {
return false;
}
while (!mapping_.empty() && (capacity_ - occupancy_) < source_size) {
EvictOne();
}
auto node = std::make_shared<CacheNode>(resource_url, source);
AppendToListTail(node);
occupancy_ += source_size;
mapping_.emplace(resource_url, node);
return true;
}

void Cache::Clear() {
header_->next_ = tailer_.get();
tailer_->prev_ = header_.get();
mapping_.clear();
occupancy_ = 0;
}

void Cache::EvictOne() noexcept {
auto *first_node = header_->next_;
auto resource_size = first_node->Size();
auto iter = mapping_.find(first_node->identifier_); // friend
assert(iter != mapping_.end());
RemoveFromList(iter->second);
mapping_.erase(iter);
occupancy_ -= resource_size;
}
void Cache::RemoveFromList(const std::shared_ptr<CacheNode> &node) noexcept {
auto *node_ptr = node.get();
auto *node_prev = node_ptr->prev_;
auto *node_next = node_ptr->next_;
node_prev->next_ = node_next;
node_next->prev_ = node_prev;
}
void Cache::AppendToListTail(const std::shared_ptr<CacheNode> &node) noexcept {
auto *node_ptr = node.get();
auto *node_prev = tailer_->prev_;
node_prev->next_ = node_ptr;
tailer_->prev_ = node_ptr;
node_ptr->prev_ = node_prev;
node_ptr->next_ = tailer_.get();
}
} // namespace Next
69 changes: 69 additions & 0 deletions src/include/core/cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#ifndef NEXT_CACHE_H
#define NEXT_CACHE_H

#include "core/utils.h"
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <string>
#include <unordered_map>
#include <vector>

namespace Next {
static constexpr size_t DEFAULT_CACHE_CAPACITY = 10 * 1024 * 1024;
auto GetTimeUtc() noexcept -> uint64_t;

class Cache {
public:
class CacheNode {
friend class Cache;

public:
CacheNode() noexcept;
CacheNode(std::string identifier, const std::vector<unsigned char> &data);
void SetIdentifier(const std::string &identifier);
void SetData(const std::vector<unsigned char> &data);
void Serialize(std::vector<unsigned char> &destination);
auto Size() const noexcept -> size_t;
void UpdataTimeStamp() noexcept;
auto GetTimeStamp() const noexcept -> uint64_t;

private:
std::string identifier_;
std::vector<unsigned char> data_;
uint64_t last_access_{0};
CacheNode *prev_{nullptr};
CacheNode *next_{nullptr};
};

explicit Cache(size_t capacity = DEFAULT_CACHE_CAPACITY) noexcept;
NON_MOVE_AND_COPYABLE(Cache);

auto GetOccupancy() const noexcept -> size_t;
auto GetCapacity() const noexcept -> size_t;

auto TryLoad(const std::string &resource_url,
std::vector<unsigned char> &destination) -> bool;

auto TryInsert(const std::string &resource_url,
const std::vector<unsigned char> &source) -> bool;

void Clear();

private:
void EvictOne() noexcept;
void RemoveFromList(const std::shared_ptr<CacheNode> &node) noexcept;
void AppendToListTail(const std::shared_ptr<CacheNode> &node) noexcept;

// shared_mutex to implement read/write lock
std::shared_mutex mtx_;
// use map to fast find ptr pos
std::unordered_map<std::string, std::shared_ptr<CacheNode>> mapping_;
const size_t capacity_{0};
size_t occupancy_{0};
const std::shared_ptr<CacheNode> header_;
const std::shared_ptr<CacheNode> tailer_;
};

} // namespace Next
#endif
75 changes: 75 additions & 0 deletions src/include/core/next_server.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <algorithm>
#include <functional>
#include <memory>
#include <stdexcept>
#include <utility>
#include <vector>
/* all header files included */
#include "core/acceptor.h"
#include "core/buffer.h"
#include "core/cache.h"
#include "core/connection.h"
#include "core/looper.h"
#include "core/net_addr.h"
#include "core/poller.h"
#include "core/socket.h"
#include "core/thread_pool.h"
#include "core/utils.h"

#ifndef NEXT_SERVER_H_
#define NEXT_SERVER_H_

namespace Next {
class NextServer {
public:
NextServer(NetAddress server_address,
int concurrency =
static_cast<int>(std::thread::hardware_concurrency()) - 1)
: pool_(std::make_unique<ThreadPool>(concurrency)),
listener_(std::make_unique<Looper>()) {
for (size_t i = 0; i < pool_->GetSize(); i++) {
reactors_.push_back(std::make_unique<Looper>(TIMER_EXPIRATION))
}
for (auto &reactor : reactors_) {
pool_->SubmitTask([capture0 = reactor.get()]() { capture0->Loop(); });
}
std::vector<Looper *> raw_reactors;
raw_reactors.reserve(reactors_.size());

std::transform(reactors_.begin(), reactors_.end(),
std::back_inserter(raw_reactors),
[](auto &uni_ptr) { return uni_ptr.get(); });
acceptor_ = std::make_unique<Acceptor>(listener_.get(), raw_reactors,
server_address);
}

~NextServer() = default;

auto OnAccept(std::function<void(Connection *)> on_accept) -> NextServer & {
acceptor_->SetCustomAcceptCallback(std::move(on_accept));
return *this;
}

auto OnHandle(std::function<void(Connection *)> on_handle) -> NextServer & {
acceptor_->SetCustomHandleCallback(std::move(on_handle));
on_handle_set_ = true;
return *this;
}

void Begin() {
if (!on_handle_set_) {
throw std::logic_error(
"Please specify OnHandle callback function before starts");
}
listener_->Loop();
}

private:
bool on_handle_set_{false};
std::unique_ptr<Acceptor> acceptor_;
std::vector<std::unique_ptr<Looper>> reactors_;
std::unique_ptr<ThreadPool> pool_;
std::unique_ptr<Looper> listener_;
}
} // namespace Next
#endif

0 comments on commit f7c4c77

Please sign in to comment.