2 |
- |
1 |
/* Copyright (C) 1998, 1999 Aladdin Enterprises. All rights reserved.
|
|
|
2 |
|
|
|
3 |
This software is provided AS-IS with no warranty, either express or
|
|
|
4 |
implied.
|
|
|
5 |
|
|
|
6 |
This software is distributed under license and may not be copied,
|
|
|
7 |
modified or distributed except as expressly authorized under the terms
|
|
|
8 |
of the license contained in the file LICENSE in this distribution.
|
|
|
9 |
|
|
|
10 |
For more information about licensing, please refer to
|
|
|
11 |
http://www.ghostscript.com/licensing/. For information on
|
|
|
12 |
commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
|
13 |
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
|
14 |
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
/* $Id: gxpageq.h,v 1.5 2002/06/16 08:45:43 lpd Exp $ */
|
|
|
18 |
/* Page queue implementation */
|
|
|
19 |
|
|
|
20 |
/* Initial version 2/1/98 by John Desrosiers (soho@crl.com) */
|
|
|
21 |
/* 7/17/98 L. Peter Deutsch (ghost@aladdin.com) edited to conform to
|
|
|
22 |
Ghostscript coding standards */
|
|
|
23 |
/* 8/7/98 ghost@aladdin.com fixed bugs in #define st_... statements */
|
|
|
24 |
/* 11/3/98 ghost@aladdin.com further updates for coding standards,
|
|
|
25 |
moves definition of page queue structure to gxpageq.c */
|
|
|
26 |
/* 12/1/98 soho@crl.com - Upgraded gx_page_queue_action_t comments */
|
|
|
27 |
|
|
|
28 |
#ifndef gxpageq_INCLUDED
|
|
|
29 |
# define gxpageq_INCLUDED
|
|
|
30 |
|
|
|
31 |
#include "gsmemory.h"
|
|
|
32 |
#include "gxband.h"
|
|
|
33 |
#include "gxsync.h"
|
|
|
34 |
|
|
|
35 |
/* --------------- Data type definitions --------------------- */
|
|
|
36 |
|
|
|
37 |
/* Action codes for each page queue entry. Each page that the interpreter
|
|
|
38 |
emits to the page queue can actually be broken down into a sequence of
|
|
|
39 |
one or more page queue entries. The general form for a given page's
|
|
|
40 |
sequence of page queue entries can be expressed as:
|
|
|
41 |
[PARTIAL_PAGE]... [COPY_PAGE [PARTIAL_PAGE]...]... FULL_PAGE
|
|
|
42 |
where elements in square brackets are optional, and ellipses show
|
|
|
43 |
repetition. NOTE that a single ACTION_TERMINATE (followed by nothing) can
|
|
|
44 |
also show up at any point in the page queue in lieu of page descriptions.
|
|
|
45 |
|
|
|
46 |
|
|
|
47 |
PARTIAL_PAGE: The interpreter emits a partial page when the bandlist is
|
|
|
48 |
too small to contain a page's full representation. Partial pages will
|
|
|
49 |
be emitted in out-of-memory situations *only* after the interpreter
|
|
|
50 |
has determined that no further page queue entries are in the page
|
|
|
51 |
queue, indicating that no further memory can be reclaimed by merely
|
|
|
52 |
waiting for queued pages to render and free their associated bandlist.
|
|
|
53 |
|
|
|
54 |
Note that num_copies is undefined for partial pages: the actual
|
|
|
55 |
number of pages to render will only be known when ...COPY_PAGE
|
|
|
56 |
or FULL_PAGE is emitted.
|
|
|
57 |
|
|
|
58 |
Partial pages are never imaged.
|
|
|
59 |
|
|
|
60 |
|
|
|
61 |
FULL_PAGE: The interpreter emits a full page when a page description
|
|
|
62 |
is complete (e.g. showpage), or trashed (e.g. setpagedevice). The
|
|
|
63 |
page's complete description consists of the FULL_PAGE plus all
|
|
|
64 |
PARTIAL_PAGEs that immediately precede it in the page queue (and
|
|
|
65 |
possibly preceding COPY_PAGEs) all the way back to the previous
|
|
|
66 |
FULL_PAGE (or up to the beginning of queue entries).
|
|
|
67 |
|
|
|
68 |
In the case of a trashed page, the page count will be 0. The page
|
|
|
69 |
queue may choose to not render the 0-count FULL_PAGE queue entry
|
|
|
70 |
for efficiency. If they have not been rendered, the page queue
|
|
|
71 |
may choose to also discard (and/or not render) any PARTIAL_PAGEs
|
|
|
72 |
leading up to the trashed page. The page queue must however take
|
|
|
73 |
care to not discard any entries leading up to a COPY_PAGE with
|
|
|
74 |
a non-0 page count that may precede the FULL_PAGE, since COPY_PAGE
|
|
|
75 |
must be rendered in that case. In any event, a 0-count page will
|
|
|
76 |
not be imaged.
|
|
|
77 |
|
|
|
78 |
In the case of a complete page, the page count will be 0 or greater.
|
|
|
79 |
The 0-count page is equivalent to a trashed page -- see above. The
|
|
|
80 |
renderer must ensure that all PARTIAL_PAGEs and COPY_PAGEs leading
|
|
|
81 |
up to the FULL_PAGE are rendered sequentially before rendering
|
|
|
82 |
and imaging the FULL_PAGE.
|
|
|
83 |
|
|
|
84 |
|
|
|
85 |
COPY_PAGE: is similar to FULL_PAGE above, except that COPY_PAGE must
|
|
|
86 |
keep the rendered results, instead of clearing them. COPY_PAGE
|
|
|
87 |
differs from a partial page in that the page must be imaged, as well
|
|
|
88 |
as rasterized. This is to support PostScript language "copypage"
|
|
|
89 |
semantics.
|
|
|
90 |
|
|
|
91 |
Note that a 0 page count here does not absolve the renderer from
|
|
|
92 |
rendering the page queue entries (unless all subsequent COPY_PAGEs
|
|
|
93 |
the the FULL_PAGE for this page also have a 0 page count), since
|
|
|
94 |
the results of COPY_PAGE must be available for subsequent pages.
|
|
|
95 |
|
|
|
96 |
|
|
|
97 |
TERMINATE: This entry can appear at any time in the page queue. It
|
|
|
98 |
will be the last entry to ever appear in the queue. The semantics
|
|
|
99 |
of this entry require all prior non-zero-count COPY_PAGEs and
|
|
|
100 |
FULL_PAGEs to be imaged. Any trailing PARTIAL_PAGEs may optionally
|
|
|
101 |
be rendered, but should not be imaged.
|
|
|
102 |
*/
|
|
|
103 |
typedef enum {
|
|
|
104 |
GX_PAGE_QUEUE_ACTION_PARTIAL_PAGE,
|
|
|
105 |
GX_PAGE_QUEUE_ACTION_FULL_PAGE,
|
|
|
106 |
GX_PAGE_QUEUE_ACTION_COPY_PAGE,
|
|
|
107 |
GX_PAGE_QUEUE_ACTION_TERMINATE
|
|
|
108 |
} gx_page_queue_action_t;
|
|
|
109 |
|
|
|
110 |
/*
|
|
|
111 |
* Define the structure used to manage a page queue.
|
|
|
112 |
* A page queue is a monitor-locked FIFO which holds completed command
|
|
|
113 |
* list files ready for rendering.
|
|
|
114 |
*/
|
|
|
115 |
#ifndef gx_page_queue_DEFINED
|
|
|
116 |
# define gx_page_queue_DEFINED
|
|
|
117 |
typedef struct gx_page_queue_s gx_page_queue_t;
|
|
|
118 |
#endif
|
|
|
119 |
|
|
|
120 |
/*
|
|
|
121 |
* Define a page queue entry object.
|
|
|
122 |
*/
|
|
|
123 |
typedef struct gx_page_queue_entry_s gx_page_queue_entry_t;
|
|
|
124 |
struct gx_page_queue_entry_s {
|
|
|
125 |
gx_band_page_info_t page_info;
|
|
|
126 |
gx_page_queue_action_t action; /* action code */
|
|
|
127 |
int num_copies; /* number of copies to render, only defined */
|
|
|
128 |
/* if action == ...FULL_PAGE or ...COPY_PAGE */
|
|
|
129 |
gx_page_queue_entry_t *next; /* link to next in queue */
|
|
|
130 |
gx_page_queue_t *queue; /* link to queue the entry is in */
|
|
|
131 |
};
|
|
|
132 |
|
|
|
133 |
#define private_st_gx_page_queue_entry()\
|
|
|
134 |
gs_private_st_ptrs2(st_gx_page_queue_entry, gx_page_queue_entry_t,\
|
|
|
135 |
"gx_page_queue_entry",\
|
|
|
136 |
gx_page_queue_entry_enum_ptrs, gx_page_queue_entry_reloc_ptrs,\
|
|
|
137 |
next, queue)
|
|
|
138 |
|
|
|
139 |
/* -------------- Public Procedure Declaraions --------------------- */
|
|
|
140 |
|
|
|
141 |
/* Allocate a page queue. */
|
|
|
142 |
gx_page_queue_t *gx_page_queue_alloc(gs_memory_t *mem);
|
|
|
143 |
|
|
|
144 |
/*
|
|
|
145 |
* Allocate and initialize a page queue entry.
|
|
|
146 |
* All page queue entries must be allocated by this routine.
|
|
|
147 |
*/
|
|
|
148 |
/* rets ptr to allocated object, 0 if VM error */
|
|
|
149 |
gx_page_queue_entry_t *
|
|
|
150 |
gx_page_queue_entry_alloc(
|
|
|
151 |
gx_page_queue_t * queue /* queue that entry is being alloc'd for */
|
|
|
152 |
);
|
|
|
153 |
|
|
|
154 |
/*
|
|
|
155 |
* Free a page queue entry.
|
|
|
156 |
* All page queue entries must be destroyed by this routine.
|
|
|
157 |
*/
|
|
|
158 |
void gx_page_queue_entry_free(
|
|
|
159 |
gx_page_queue_entry_t * entry /* entry to free up */
|
|
|
160 |
);
|
|
|
161 |
|
|
|
162 |
/*
|
|
|
163 |
* Free the page_info resources held by the pageq entry. Used to free
|
|
|
164 |
* pages' clist, typically after rendering. Note that this routine is NOT
|
|
|
165 |
* called implicitly by gx_page_queue_entry_free, since page clist may be
|
|
|
166 |
* managed separately from page queue entries. However, unless you are
|
|
|
167 |
* managing clist separately, you must call this routine before freeing the
|
|
|
168 |
* pageq entry itself (via gx_page_queue_entry_free), or you will leak
|
|
|
169 |
* memory (lots).
|
|
|
170 |
*/
|
|
|
171 |
void gx_page_queue_entry_free_page_info(
|
|
|
172 |
gx_page_queue_entry_t * entry /* entry to free up */
|
|
|
173 |
);
|
|
|
174 |
|
|
|
175 |
/*
|
|
|
176 |
* Initialize a page queue; this must be done before it can be used.
|
|
|
177 |
* This routine allocates & inits various necessary structures and will
|
|
|
178 |
* fail if insufficient memory is available.
|
|
|
179 |
*/
|
|
|
180 |
/* -ve error code, or 0 */
|
|
|
181 |
int gx_page_queue_init(
|
|
|
182 |
gx_page_queue_t * queue, /* page queue to init */
|
|
|
183 |
gs_memory_t * memory /* allocator for dynamic memory */
|
|
|
184 |
);
|
|
|
185 |
|
|
|
186 |
/*
|
|
|
187 |
* Destroy a page queue which was initialized by gx_page_queue_init.
|
|
|
188 |
* Any page queue entries in the queue are released and destroyed;
|
|
|
189 |
* dynamic allocations are released.
|
|
|
190 |
*/
|
|
|
191 |
void gx_page_queue_dnit(
|
|
|
192 |
gx_page_queue_t * queue /* page queue to dnit */
|
|
|
193 |
);
|
|
|
194 |
|
|
|
195 |
/*
|
|
|
196 |
* If there are any pages in queue, wait until one of them finishes
|
|
|
197 |
* rendering. Typically called by writer's out-of-memory error handlers
|
|
|
198 |
* that want to wait until some memory has been freed.
|
|
|
199 |
*/
|
|
|
200 |
/* rets 0 if no pages were waiting for rendering, 1 if actually waited */
|
|
|
201 |
int gx_page_queue_wait_one_page(
|
|
|
202 |
gx_page_queue_t * queue /* queue to wait on */
|
|
|
203 |
);
|
|
|
204 |
|
|
|
205 |
/*
|
|
|
206 |
* Wait until all (if any) pages in queue have finished rendering. Typically
|
|
|
207 |
* called by writer operations which need to drain the page queue before
|
|
|
208 |
* continuing.
|
|
|
209 |
*/
|
|
|
210 |
void gx_page_queue_wait_until_empty(
|
|
|
211 |
gx_page_queue_t * queue /* page queue to wait on */
|
|
|
212 |
);
|
|
|
213 |
|
|
|
214 |
/*
|
|
|
215 |
* Add a pageq queue entry to the end of the page queue. If an unsatisfied
|
|
|
216 |
* reader thread has an outstanding gx_page_queue_start_deque(), wake it up.
|
|
|
217 |
*/
|
|
|
218 |
void gx_page_queue_enqueue(
|
|
|
219 |
gx_page_queue_entry_t * entry /* entry to add */
|
|
|
220 |
);
|
|
|
221 |
|
|
|
222 |
/*
|
|
|
223 |
* Allocate & construct a pageq entry, then add to the end of the pageq as
|
|
|
224 |
* in gx_page_queue_enqueue. If unable to allocate a new pageq entry, uses
|
|
|
225 |
* the pre-allocated reserve entry held in the pageq. When using the reserve
|
|
|
226 |
* pageq entry, wait until enough pages have been rendered to allocate a new
|
|
|
227 |
* reserve for next time -- this should always succeed & returns eFatal if not.
|
|
|
228 |
* Unless the reserve was used, does not wait for any rendering to complete.
|
|
|
229 |
* Typically called by writer when it has a (partial) page ready for rendering.
|
|
|
230 |
*/
|
|
|
231 |
/* rets 0 ok, gs_error_Fatal if error */
|
|
|
232 |
int gx_page_queue_add_page(
|
|
|
233 |
gx_page_queue_t * queue, /* page queue to add to */
|
|
|
234 |
gx_page_queue_action_t action, /* action code to queue */
|
|
|
235 |
const gx_band_page_info_t * page_info, /* bandinfo incl. bandlist */
|
|
|
236 |
int page_count /* # of copies to print if final "print," */
|
|
|
237 |
/* 0 if partial page, -1 if cancel */
|
|
|
238 |
);
|
|
|
239 |
|
|
|
240 |
/*
|
|
|
241 |
* Retrieve the least-recently added queue entry from the pageq. If no
|
|
|
242 |
* entry is available, waits on a signal from gx_page_queue_enqueue. Must
|
|
|
243 |
* eventually be followed by a call to gx_page_queue_finish_dequeue for the
|
|
|
244 |
* same pageq entry.
|
|
|
245 |
* Even though the pageq is actually removed from the pageq, a mark is made in
|
|
|
246 |
* the pageq to indicate that the pageq is not "empty" until the
|
|
|
247 |
* gx_page_queue_finish_dequeue; this is for the benefit of
|
|
|
248 |
* gx_page_queue_wait_???, since the completing the current page's rendering
|
|
|
249 |
* may free more memory.
|
|
|
250 |
* Typically called by renderer thread loop, which looks like:
|
|
|
251 |
do {
|
|
|
252 |
gx_page_queue_start_deqeueue(...);
|
|
|
253 |
render_retrieved_entry(...);
|
|
|
254 |
gx_page_queue_finish_dequeue(...);
|
|
|
255 |
} while (some condition);
|
|
|
256 |
*/
|
|
|
257 |
gx_page_queue_entry_t * /* removed entry */
|
|
|
258 |
gx_page_queue_start_dequeue(
|
|
|
259 |
gx_page_queue_t * queue /* page queue to retrieve from */
|
|
|
260 |
);
|
|
|
261 |
|
|
|
262 |
/*
|
|
|
263 |
* Free the pageq entry and its associated band list data, then signal any
|
|
|
264 |
* waiting threads. Typically used to indicate completion of rendering the
|
|
|
265 |
* pageq entry. Note that this is different from gx_page_queue_entry_free,
|
|
|
266 |
* which does not free the band list data (a separate call of
|
|
|
267 |
* gx_page_queue_entry_free_page_info is required).
|
|
|
268 |
*/
|
|
|
269 |
void gx_page_queue_finish_dequeue(
|
|
|
270 |
gx_page_queue_entry_t * entry /* entry that was retrieved to delete */
|
|
|
271 |
);
|
|
|
272 |
|
|
|
273 |
#endif /*!defined(gxpageq_INCLUDED) */
|