mirror of
https://github.com/mhx/dwarfs.git
synced 2025-09-10 04:50:31 -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/error.h"
|
||||||
#include "dwarfs/fstypes.h"
|
#include "dwarfs/fstypes.h"
|
||||||
#include "dwarfs/option_map.h"
|
#include "dwarfs/option_map.h"
|
||||||
|
#include "dwarfs/zstd_context_manager.h"
|
||||||
|
|
||||||
#if ZSTD_VERSION_MAJOR > 1 || \
|
#if ZSTD_VERSION_MAJOR > 1 || \
|
||||||
(ZSTD_VERSION_MAJOR == 1 && ZSTD_VERSION_MINOR >= 4)
|
(ZSTD_VERSION_MAJOR == 1 && ZSTD_VERSION_MINOR >= 4)
|
||||||
@ -75,85 +76,28 @@ class zstd_block_compressor final : public block_compressor::impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class scoped_context;
|
static std::shared_ptr<zstd_context_manager> get_context_manager() {
|
||||||
|
|
||||||
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() {
|
|
||||||
std::lock_guard lock(s_mx);
|
std::lock_guard lock(s_mx);
|
||||||
if (auto mgr = s_ctxmgr.lock()) {
|
if (auto mgr = s_ctxmgr.lock()) {
|
||||||
return mgr;
|
return mgr;
|
||||||
}
|
}
|
||||||
auto mgr = std::make_shared<context_manager>();
|
auto mgr = std::make_shared<zstd_context_manager>();
|
||||||
s_ctxmgr = mgr;
|
s_ctxmgr = mgr;
|
||||||
return mgr;
|
return mgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::mutex s_mx;
|
static inline std::mutex s_mx;
|
||||||
static std::weak_ptr<context_manager> s_ctxmgr;
|
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_;
|
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>
|
std::vector<uint8_t>
|
||||||
zstd_block_compressor::compress(const std::vector<uint8_t>& data,
|
zstd_block_compressor::compress(const std::vector<uint8_t>& data,
|
||||||
std::string const* /*metadata*/) const {
|
std::string const* /*metadata*/) const {
|
||||||
std::vector<uint8_t> compressed(ZSTD_compressBound(data.size()));
|
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(),
|
auto size = ZSTD_compressCCtx(ctx.get(), compressed.data(), compressed.size(),
|
||||||
data.data(), data.size(), level_);
|
data.data(), data.size(), level_);
|
||||||
if (ZSTD_isError(size)) {
|
if (ZSTD_isError(size)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user