diff --git a/include/dwarfs/zstd_context_manager.h b/include/dwarfs/zstd_context_manager.h
new file mode 100644
index 00000000..943d2b6f
--- /dev/null
+++ b/include/dwarfs/zstd_context_manager.h
@@ -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 .
+ */
+
+#pragma once
+
+#include
+#include
+
+#include
+
+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 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
diff --git a/src/dwarfs/compression/zstd.cpp b/src/dwarfs/compression/zstd.cpp
index a6634e5b..89220319 100644
--- a/src/dwarfs/compression/zstd.cpp
+++ b/src/dwarfs/compression/zstd.cpp
@@ -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 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 get_context_manager() {
+ static std::shared_ptr get_context_manager() {
std::lock_guard lock(s_mx);
if (auto mgr = s_ctxmgr.lock()) {
return mgr;
}
- auto mgr = std::make_shared();
+ auto mgr = std::make_shared();
s_ctxmgr = mgr;
return mgr;
}
- static std::mutex s_mx;
- static std::weak_ptr s_ctxmgr;
+ static inline std::mutex s_mx;
+ static inline std::weak_ptr s_ctxmgr;
- std::shared_ptr ctxmgr_;
+ std::shared_ptr ctxmgr_;
const int level_;
};
-std::mutex zstd_block_compressor::s_mx;
-std::weak_ptr
- zstd_block_compressor::s_ctxmgr;
-
std::vector
zstd_block_compressor::compress(const std::vector& data,
std::string const* /*metadata*/) const {
std::vector 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)) {