mirror of
https://github.com/mhx/dwarfs.git
synced 2025-09-08 11:59:48 -04:00
Factor out zstd context manager
This commit is contained in:
parent
9ac06fe40d
commit
bad2c5e057
91
include/dwarfs/zstd_context_manager.h
Normal file
91
include/dwarfs/zstd_context_manager.h
Normal file
@ -0,0 +1,91 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/**
|
||||
* \author Marcus Holland-Moritz (github@mhxnet.de)
|
||||
* \copyright Copyright (c) Marcus Holland-Moritz
|
||||
*
|
||||
* This file is part of dwarfs.
|
||||
*
|
||||
* dwarfs is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dwarfs is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <zstd.h>
|
||||
|
||||
namespace dwarfs {
|
||||
|
||||
class zstd_context_manager;
|
||||
|
||||
class zstd_scoped_context {
|
||||
friend class zstd_context_manager;
|
||||
|
||||
public:
|
||||
~zstd_scoped_context();
|
||||
|
||||
zstd_scoped_context(zstd_scoped_context&&) = default;
|
||||
zstd_scoped_context& operator=(zstd_scoped_context&&) = default;
|
||||
|
||||
ZSTD_CCtx* get() const { return ctx_; }
|
||||
|
||||
private:
|
||||
explicit zstd_scoped_context(zstd_context_manager* mgr);
|
||||
|
||||
zstd_context_manager* mgr_;
|
||||
ZSTD_CCtx* ctx_;
|
||||
};
|
||||
|
||||
class zstd_context_manager {
|
||||
friend class zstd_scoped_context;
|
||||
|
||||
public:
|
||||
zstd_context_manager() = default;
|
||||
|
||||
~zstd_context_manager() {
|
||||
for (auto ctx : ctx_) {
|
||||
ZSTD_freeCCtx(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
zstd_scoped_context make_context() { return zstd_scoped_context(this); }
|
||||
|
||||
private:
|
||||
ZSTD_CCtx* acquire() {
|
||||
std::lock_guard lock(mx_);
|
||||
if (ctx_.empty()) {
|
||||
return ZSTD_createCCtx();
|
||||
}
|
||||
auto ctx = ctx_.back();
|
||||
ctx_.pop_back();
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void release(ZSTD_CCtx* ctx) {
|
||||
std::lock_guard lock(mx_);
|
||||
ctx_.push_back(ctx);
|
||||
}
|
||||
|
||||
std::mutex mx_;
|
||||
std::vector<ZSTD_CCtx*> ctx_;
|
||||
};
|
||||
|
||||
inline zstd_scoped_context::zstd_scoped_context(zstd_context_manager* mgr)
|
||||
: mgr_{mgr}
|
||||
, ctx_{mgr_->acquire()} {}
|
||||
|
||||
inline zstd_scoped_context::~zstd_scoped_context() { mgr_->release(ctx_); }
|
||||
|
||||
} // namespace dwarfs
|
@ -29,6 +29,7 @@
|
||||
#include "dwarfs/error.h"
|
||||
#include "dwarfs/fstypes.h"
|
||||
#include "dwarfs/option_map.h"
|
||||
#include "dwarfs/zstd_context_manager.h"
|
||||
|
||||
#if ZSTD_VERSION_MAJOR > 1 || \
|
||||
(ZSTD_VERSION_MAJOR == 1 && ZSTD_VERSION_MINOR >= 4)
|
||||
@ -75,85 +76,28 @@ class zstd_block_compressor final : public block_compressor::impl {
|
||||
}
|
||||
|
||||
private:
|
||||
class scoped_context;
|
||||
|
||||
class context_manager {
|
||||
public:
|
||||
context_manager() = default;
|
||||
|
||||
~context_manager() {
|
||||
for (auto ctx : ctx_) {
|
||||
ZSTD_freeCCtx(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class scoped_context;
|
||||
|
||||
ZSTD_CCtx* acquire() {
|
||||
std::lock_guard lock(mx_);
|
||||
if (ctx_.empty()) {
|
||||
return ZSTD_createCCtx();
|
||||
}
|
||||
auto ctx = ctx_.back();
|
||||
ctx_.pop_back();
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void release(ZSTD_CCtx* ctx) {
|
||||
std::lock_guard lock(mx_);
|
||||
ctx_.push_back(ctx);
|
||||
}
|
||||
|
||||
std::mutex mx_;
|
||||
std::vector<ZSTD_CCtx*> ctx_;
|
||||
};
|
||||
|
||||
class scoped_context {
|
||||
public:
|
||||
explicit scoped_context(context_manager& mgr)
|
||||
: mgr_{&mgr}
|
||||
, ctx_{mgr_->acquire()} {}
|
||||
~scoped_context() { mgr_->release(ctx_); }
|
||||
|
||||
scoped_context(scoped_context const&) = delete;
|
||||
scoped_context(scoped_context&&) = default;
|
||||
scoped_context& operator=(scoped_context const&) = delete;
|
||||
scoped_context& operator=(scoped_context&&) = default;
|
||||
|
||||
ZSTD_CCtx* get() const { return ctx_; }
|
||||
|
||||
private:
|
||||
context_manager* mgr_;
|
||||
ZSTD_CCtx* ctx_;
|
||||
};
|
||||
|
||||
static std::shared_ptr<context_manager> get_context_manager() {
|
||||
static std::shared_ptr<zstd_context_manager> get_context_manager() {
|
||||
std::lock_guard lock(s_mx);
|
||||
if (auto mgr = s_ctxmgr.lock()) {
|
||||
return mgr;
|
||||
}
|
||||
auto mgr = std::make_shared<context_manager>();
|
||||
auto mgr = std::make_shared<zstd_context_manager>();
|
||||
s_ctxmgr = mgr;
|
||||
return mgr;
|
||||
}
|
||||
|
||||
static std::mutex s_mx;
|
||||
static std::weak_ptr<context_manager> s_ctxmgr;
|
||||
static inline std::mutex s_mx;
|
||||
static inline std::weak_ptr<zstd_context_manager> s_ctxmgr;
|
||||
|
||||
std::shared_ptr<context_manager> ctxmgr_;
|
||||
std::shared_ptr<zstd_context_manager> ctxmgr_;
|
||||
const int level_;
|
||||
};
|
||||
|
||||
std::mutex zstd_block_compressor::s_mx;
|
||||
std::weak_ptr<zstd_block_compressor::context_manager>
|
||||
zstd_block_compressor::s_ctxmgr;
|
||||
|
||||
std::vector<uint8_t>
|
||||
zstd_block_compressor::compress(const std::vector<uint8_t>& data,
|
||||
std::string const* /*metadata*/) const {
|
||||
std::vector<uint8_t> compressed(ZSTD_compressBound(data.size()));
|
||||
scoped_context ctx(*ctxmgr_);
|
||||
auto ctx = ctxmgr_->make_context();
|
||||
auto size = ZSTD_compressCCtx(ctx.get(), compressed.data(), compressed.size(),
|
||||
data.data(), data.size(), level_);
|
||||
if (ZSTD_isError(size)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user