summaryrefslogtreecommitdiffstats
path: root/client/glz_decoder_window.h
diff options
context:
space:
mode:
authorYaniv Kamay <ykamay@redhat.com>2009-09-19 21:25:46 +0300
committerYaniv Kamay <ykamay@redhat.com>2009-10-14 15:06:41 +0200
commitc1b79eb035fa158fb2ac3bc8e559809611070016 (patch)
tree3348dd749a700dedf87c9b16fe8be77c62928df8 /client/glz_decoder_window.h
downloadspice-c1b79eb035fa158fb2ac3bc8e559809611070016.tar.gz
spice-c1b79eb035fa158fb2ac3bc8e559809611070016.tar.xz
spice-c1b79eb035fa158fb2ac3bc8e559809611070016.zip
fresh start
Diffstat (limited to 'client/glz_decoder_window.h')
-rw-r--r--client/glz_decoder_window.h127
1 files changed, 127 insertions, 0 deletions
diff --git a/client/glz_decoder_window.h b/client/glz_decoder_window.h
new file mode 100644
index 00000000..831f2d56
--- /dev/null
+++ b/client/glz_decoder_window.h
@@ -0,0 +1,127 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ This program 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 2 of
+ the License, or (at your option) any later version.
+
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_GLZ_DECODER_WINDOW
+#define _H_GLZ_DECODER_WINDOW
+
+#include "glz_decoder_config.h"
+#include "glz_decoded_image.h"
+
+#include <list>
+
+#include "read_write_mutex.h"
+
+typedef int DecodedImageWinId;
+
+/*
+ The class represents the lz window of images, which is shared among the glz decoders
+*/
+
+class GlzDecoderWindow {
+public:
+ GlzDecoderWindow(int pixels_capacity, GlzDecoderDebug &debug_calls);
+ virtual ~GlzDecoderWindow();
+
+ DecodedImageWinId pre_decode(uint64_t image_id, uint64_t relative_head_id);
+
+ void post_decode(GlzDecodedImage *image);
+
+ /* NOTE - get_ref_pixel should be called only after pre_decode was called and
+ before post decode was called */
+ uint8_t *get_ref_pixel(DecodedImageWinId decoded_image_win_id, int dist_from_ref_image,
+ int pixel_offset);
+
+ void abort();
+
+ /* NOTE - clear mustn't be called if the window is currently used by a decoder*/
+ void clear();
+
+ void set_pixels_capacity(int pixels_capacity);
+
+private:
+ void wait_for_image(int index);
+ void add_image(GlzDecodedImage *image);
+ uint8_t* get_pixel_after_image_entered(int image_index, int pixel_offset);
+
+ bool will_overflow(uint64_t image_id, uint64_t relative_head_id);
+ bool is_empty();
+
+ DecodedImageWinId pre_decode_update_window(uint64_t image_id, uint64_t relative_head_id);
+ void pre_decode_finalize();
+ void post_decode_intialize();
+ void post_decode_update_window(GlzDecodedImage *image);
+ void add_pre_decoded_image(uint64_t image_id);
+ void add_decoded_image(GlzDecodedImage *image);
+ void narrow_window(GlzDecodedImage *last_added);
+ void remove_head(uint64_t new_head_image_id);
+ int calc_image_win_idx(uint64_t image_id);
+ int calc_realloc_size(uint64_t new_tail_image_id);
+ void realloc(int size);
+ void init();
+ void release_images();
+
+private:
+ int _pixels_capacity;
+ GlzDecodedImage **_images; // cyclic window
+ int _head_idx; // index in images array (not image id)
+ uint64_t _tail_image_id;
+ int _images_capacity;
+ int _n_images; // _n_images counts all the images in
+ // the window, including the missing ones
+ uint64_t _n_pixels;
+
+ std::list<uint64_t> _missing_list;
+
+ Mutex _win_modifiers_mutex;
+ ReadWriteMutex _win_alloc_rw_mutex;
+ Mutex _new_image_mutex;
+
+ Condition _new_image_cond; // when get_pixel_ref waits for an image
+ Condition _release_image_cond; // when waiting for the window to narrow.
+ Condition _win_alloc_cond;
+
+ bool _aborting;
+
+ GlzDecoderDebug &_debug_calls;
+};
+
+inline uint8_t* GlzDecoderWindow::get_pixel_after_image_entered(int image_index,
+ int pixel_offset)
+{
+ return _images[image_index]->get_pixel_ref(pixel_offset);
+}
+
+/* should be called only between pre and post (when realloc mutex is write-locked).
+ Note that it can't use calc_image_win_idx, since the window is not locked for changes
+ (that are not reallocation) during decoding.*/
+inline uint8_t *GlzDecoderWindow::get_ref_pixel(DecodedImageWinId decoded_image_win_id,
+ int dist_from_ref_image, int pixel_offset)
+{
+ int ref_image_index = (dist_from_ref_image <= decoded_image_win_id) ?
+ (decoded_image_win_id - dist_from_ref_image) :
+ _images_capacity + (decoded_image_win_id - dist_from_ref_image);
+
+ if (_images[ref_image_index] == NULL) { // reading image is atomic
+ wait_for_image(ref_image_index);
+ }
+
+ // after image entered - it won't leave the window till no decoder needs it
+ return get_pixel_after_image_entered(ref_image_index, pixel_offset);
+}
+
+#endif // _H_GLZ_DECODER_WINDOW
+