org-howto/articles/2024/01/zstream-isnt-moveable.org

83 lines
2.5 KiB
Org Mode

#+title: [2024] zlib z_stream isn't moveable
# ----------------------------------------------------------------
#+tags: @c++ @zlib @zstreambuf
# ----------------------------------------------------------------
#+description: Zlib's z_stream isn't moveable
#
# org-publish options
#
# ^:{} require a_{b} before assuming that b should be subscripted.
# without this option a_b will automatically subscript b.
#+options: ^:{}
#
# emacs-specific options
#+startup: showall
#
# html exporter options
#+language: en
#+keywords: c++ gcc preprocessor
#+setupfile: ../../../ext/fniessen/theme-readtheorg.setup
#
#+html_head: <link rel="shortcut icon" type="image/x-icon" href="/web/img/favicon.ico" />
#+html_link_home: ../../../index.html
#
# not using: prefer theme-readtheorg
# +infojs_opt: view:showall mouse:#ffc0c0 toc:nil ltoc:nil path:/web/ext/orginfo/org-info.js
# +html_head: <link rel="stylesheet" type="text/css" href="/web/css/primary.css" />
* TL;DR
Be aware that =zlib='s =z_stream= struct cannot be moved.
Presume it contains internal pointers to itself.
* Setup
- Using =zstreambuf= (provided as byproduct of my [[https://github.com/Rconybea/cmake-examples][cmake-examples]] project)
I ran into errors after move assignment.
- Making =zstreambuf.open()= work with a =zstreambuf= that's already been used for i/o.
- Attempted to cleanup state within =zstreambuf.close()=, using move assignment on
=buffered_inflate_zstream= and =buffered_deflate_zstream=.
* Problem + Diagnosis
- Unit testing revealed that uncompress failed after second =zstreambuf.open()=.
- It turns out that although zlib's =z_stream= struct is fully exposed
(to work with zlib, application code should declare a variable with type =z_stream=),
the =z_stream= struct can't be moved to another location.
Presumably at least one of (=::deflateInit2()=, =::inflateInit2()=) does some
address-dependent computation involving one or more =z_stream= members.
* Solution
- Replace =z_stream= member with a pointer:
Instead of:
#+begin_src C++
// compression/include/compression/base_zstream.hpp
#include <zlib.h>
struct base_zstream {
// ...omitted...
z_stream zstream_;
};
#+end_src
write:
#+begin_src C++
// compression/include/compression/base_zstream.hpp
#include <utility>
struct base_zstream {
// ...omitted...
std::unique_ptr<z_stream> p_native_zs_;
};
#+end_src
Then implement =::swap()= etc by swapping pointers.