1 //C-  -*- C++ -*-
2 //C- -------------------------------------------------------------------
3 //C- DjVuLibre-3.5
4 //C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
5 //C- Copyright (c) 2001  AT&T
6 //C-
7 //C- This software is subject to, and may be distributed under, the
8 //C- GNU General Public License, either Version 2 of the license,
9 //C- or (at your option) any later version. The license should have
10 //C- accompanied the software or you may obtain a copy of the license
11 //C- from the Free Software Foundation at http://www.fsf.org .
12 //C-
13 //C- This program is distributed in the hope that it will be useful,
14 //C- but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //C- GNU General Public License for more details.
17 //C-
18 //C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
19 //C- Lizardtech Software.  Lizardtech Software has authorized us to
20 //C- replace the original DjVu(r) Reference Library notice by the following
21 //C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
22 //C-
23 //C-  ------------------------------------------------------------------
24 //C- | DjVu (r) Reference Library (v. 3.5)
25 //C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
26 //C- | The DjVu Reference Library is protected by U.S. Pat. No.
27 //C- | 6,058,214 and patents pending.
28 //C- |
29 //C- | This software is subject to, and may be distributed under, the
30 //C- | GNU General Public License, either Version 2 of the license,
31 //C- | or (at your option) any later version. The license should have
32 //C- | accompanied the software or you may obtain a copy of the license
33 //C- | from the Free Software Foundation at http://www.fsf.org .
34 //C- |
35 //C- | The computer code originally released by LizardTech under this
36 //C- | license and unmodified by other parties is deemed "the LIZARDTECH
37 //C- | ORIGINAL CODE."  Subject to any third party intellectual property
38 //C- | claims, LizardTech grants recipient a worldwide, royalty-free,
39 //C- | non-exclusive license to make, use, sell, or otherwise dispose of
40 //C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
41 //C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
42 //C- | General Public License.   This grant only confers the right to
43 //C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
44 //C- | the extent such infringement is reasonably necessary to enable
45 //C- | recipient to make, have made, practice, sell, or otherwise dispose
46 //C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
47 //C- | any greater extent that may be necessary to utilize further
48 //C- | modifications or combinations.
49 //C- |
50 //C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
51 //C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
52 //C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
53 //C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
54 //C- +------------------------------------------------------------------
55 
56 #ifndef _DATAPOOL_H
57 #define _DATAPOOL_H
58 #ifdef HAVE_CONFIG_H
59 #include "config.h"
60 #endif
61 #if NEED_GNUG_PRAGMAS
62 # pragma interface
63 #endif
64 
65 
66 #include "GThreads.h"
67 #include "GString.h"
68 #include "GURL.h"
69 
70 #ifdef HAVE_NAMESPACES
71 namespace DJVU {
72 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
73 }
74 #endif
75 #endif
76 
77 class ByteStream;
78 
79 /** @name DataPool.h
80     Files #"DataPool.h"# and #"DataPool.cpp"# implement classes \Ref{DataPool}
81     and \Ref{DataRange} used by DjVu decoder to access data.
82 
83     The main goal of class \Ref{DataPool} is to provide concurrent access
84     to the same data from many threads with a possibility to add data
85     from yet another thread. It is especially important in the case of the
86     Netscape plugin when data is not immediately available, but decoding
87     should be started as soon as possible. In this situation it is vital
88     to provide transparent access to the data from many threads possibly
89     blocking readers that try to access information that has not been
90     received yet.
91 
92     When the data is local though, it can be accessed directly using
93     standard IO mechanism. To provide a uniform interface for decoding
94     routines, \Ref{DataPool} supports file mode as well.
95 
96     @memo Thread safe data storage
97     @author Andrei Erofeev <eaf@geocities.com>
98 */
99 
100 //@{
101 
102 /** Thread safe data storage.
103     The purpose of #DataPool# is to provide a uniform interface for
104     accessing data from decoding routines running in a multi-threaded
105     environment. Depending on the mode of operation it may contain the
106     actual data, may be connected to another #DataPool# or may be mapped
107     to a file. Regardless of the mode, the class returns data in a
108     thread-safe way, blocking reading threads if there is no data of
109     interest available. This blocking is especially useful in the
110     networking environment (plugin) when there is a running decoding thread,
111     which wants to start decoding as soon as there is just one byte available
112     blocking if necessary.
113 
114     Access to data in a #DataPool# may be direct (Using \Ref{get_data}()
115     function) or sequential (See \Ref{get_stream}() function).
116 
117     If the #DataPool# is not connected to anything, that is it contains
118     some real data, this data can be added to it by means of two
119     \Ref{add_data}() functions. One of them adds data sequentially maintaining
120     the offset of the last block of data added by it. The other can store
121     data anywhere. Thus it's important to realize, that there may be "white
122     spots" in the data storage.
123 
124     There is also a way to test if data is available for some given data
125     range (See \Ref{has_data}()). In addition to this mechanism, there are
126     so-called {\em trigger callbacks}, which are called, when there is
127     all data available for a given data range.
128 
129     Let us consider all modes of operation in details:
130 
131     \begin{enumerate}
132        \item {\bf Not connected #DataPool#}. In this mode the #DataPool#
133              contains some real data. As mentioned above, it may be added
134              by means of two functions \Ref{add_data}() operating independent
135 	     of each other and allowing to add data sequentially and
136 	     directly to any place of data storage. It's important to call
137 	     function \Ref{set_eof}() after all data has been added.
138 
139 	     Functions like \Ref{get_data}() or \Ref{get_stream}() can
140 	     be used to obtain direct or sequential access to the data. As
141 	     long as \Ref{is_eof}() is #FALSE#, #DataPool# will block every
142 	     reader, which is trying to read unavailable data until it
143 	     really becomes available. But as soon as \Ref{is_eof}() is
144 	     #TRUE#, any attempt to read non-existing data will read #0# bytes.
145 
146 	     Taking into account the fact, that #DataPool# was designed to
147 	     store DjVu files, which are in IFF formats, it becomes possible
148 	     to predict the size of the #DataPool# as soon as the first
149 	     #32# bytes have been added. This is invaluable for estimating
150 	     download progress. See function \Ref{get_length}() for details.
151 	     If this estimate fails (which means, that stored data is not
152 	     in IFF format), \Ref{get_length}() returns #-1#.
153 
154 	     Triggers may be added and removed by means of \Ref{add_trigger}()
155 	     and \Ref{del_trigger}() functions. \Ref{add_trigger}() takes
156 	     a data range. As soon as all data in that data range is
157 	     available, the trigger callback will be called.
158 
159 	     All trigger callbacks will be called when #EOF# condition
160 	     has been set.
161 
162        \item {\bf #DataPool# connected to another #DataPool#}. In this
163              {\em slave} mode you can map a given #DataPool# to any offsets
164 	     range inside another #DataPool#. You can connect the slave
165 	     #DataPool# even if there is no data in the master #DataPool#.
166 	     Any \Ref{get_data}() request will be forwarded to the master
167 	     #DataPool#, and it will be responsible for blocking readers
168 	     trying to access unavailable data.
169 
170 	     The usage of \Ref{add_data}() functions is prohibited for
171 	     connected #DataPool#s.
172 
173 	     The offsets range used to map a slave #DataPool# can be fully
174 	     specified (both start offset and length are positive numbers)
175 	     or partially specified (the length is negative). In this mode
176 	     the slave #DataPool# is assumed to extend up to the end
177 	     of the master #DataPool#.
178 
179 	     Triggers may be used with slave #DataPool#s as well as with
180 	     the master ones.
181 
182 	     Calling \Ref{stop}() function of a slave will stop only the slave
183 	     (and any other slave connected to it), but not the master.
184 
185 	     \Ref{set_eof}() function is meaningless for slaves. They obtain
186 	     the #ByteStream::EndOfFile# status from their master.
187 
188 	     Depending on the offsets range passed to the constructor,
189 	     \Ref{get_length}() returns different values. If the length
190 	     passed to the constructor was positive, then it is returned
191 	     by \Ref{get_length}() all the time. Otherwise the value returned
192 	     is either #-1# if master's length is still unknown (it didn't
193 	     manage to parse IFF data yet) or it is calculated as
194 	     #masters_length-slave_start#.
195 
196        \item {\bf #DataPool# connected to a file}. This mode is quite similar
197              to the case, when the #DataPool# is connected to another
198 	     #DataPool#. Similarly, the #DataPool# stores no data inside.
199 	     It just forwards all \Ref{get_data}() requests to the underlying
200 	     source (a file in this case). Thus these requests will never
201 	     block the reader. But they may return #0# if there is no data
202 	     available at the requested offset.
203 
204 	     The usage of \Ref{add_data}() functions is meaningless and
205 	     is prohibited.
206 
207 	     \Ref{is_eof}() function always returns #TRUE#. Thus \Ref{set_eof}()
208 	     us meaningless and does nothing.
209 
210 	     \Ref{get_length}() function always returns the file size.
211 
212 	     Calling \Ref{stop}() function will stop this #DataPool# and
213 	     any other slave connected to it.
214 
215 	     Trigger callbacks passed through \Ref{add_trigger}() function
216 	     are called immediately.
217 
218 	     This mode is useful to read and decode DjVu files without reading
219 	     and storing them in full in memory.
220     \end{enumerate}
221 */
222 
223 class DJVUAPI DataPool : public GPEnabled
224 {
225 public: // Classes used internally by DataPool
226 	// These are declared public to support buggy C++ compilers.
227    class Incrementor;
228    class Reader;
229    class Trigger;
230    class OpenFiles;
231    class OpenFiles_File;
232    class BlockList;
233    class Counter;
234 protected:
235    DataPool(void);
236 
237 public:
238       /** @name Initialization */
239       //@{
240       /** Default creator. Will prepare #DataPool# for accepting data
241 	  added through functions \Ref{add_data}(). Use \Ref{connect}()
242 	  functions if you want to map this #DataPool# to another or
243 	  to a file. */
244    static GP<DataPool> create(void);
245 
246       /** Creates and initialized the #DataPool# with data from stream #str#.
247 	  The constructor will read the stream's contents and add them
248 	  to the pool using the \Ref{add_data}() function. Afterwards it
249 	  will call \Ref{set_eof}() function, and no other data will be
250 	  allowed to be added to the pool. */
251    static GP<DataPool> create(const GP<ByteStream> & str);
252 
253       /** Initializes the #DataPool# in slave mode and connects it
254 	  to the specified offsets range of the specified master #DataPool#.
255 	  It is equivalent to calling default constructor and function
256 	  \Ref{connect}().
257 
258 	  @param master_pool Master #DataPool# providing data for this slave
259 	  @param start Beginning of the offsets range which the slave is
260 	         mapped into
261           @param length Length of the offsets range. If negative, the range
262 	         is assumed to extend up to the end of the master #DataPool#.
263       */
264    static GP<DataPool> create(const GP<DataPool> & master_pool, int start=0, int length=-1);
265 
266       /** Initializes the #DataPool# in slave mode and connects it
267 	  to the specified offsets range of the specified file.
268 	  It is equivalent to calling default constructor and function
269 	  \Ref{connect}().
270 	  @param url Name of the file to connect to.
271 	  @param start Beginning of the offsets range which the #DataPool# is
272 	         mapped into
273           @param length Length of the offsets range. If negative, the range
274 	         is assumed to extend up to the end of the file.
275       */
276    static GP<DataPool> create(const GURL &url, int start=0, int length=-1);
277 
278    virtual ~DataPool();
279 
280       /** Switches the #DataPool# to slave mode and connects it to the
281 	  specified offsets range of the master #DataPool#.
282 	  @param master_pool Master #DataPool# providing data for this slave
283 	  @param start Beginning of the offsets range which the slave is
284 	         mapped into
285           @param length Length of the offsets range. If negative, the range
286 	         is assumed to extend up to the end of the master #DataPool#.
287       */
288    void		connect(const GP<DataPool> & master_pool, int start=0, int length=-1);
289       /** Connects the #DataPool# to the specified offsets range of
290 	  the named #url#.
291 	  @param url Name of the file to connect to.
292 	  @param start Beginning of the offsets range which the #DataPool# is
293 	         mapped into
294           @param length Length of the offsets range. If negative, the range
295 	         is assumed to extend up to the end of the file.
296       */
297    void		connect(const GURL &url, int start=0, int length=-1);
298       //@}
299 
300       /** Tells the #DataPool# to stop serving readers.
301 
302 	  If #only_blocked# flag is #TRUE# then only those requests will
303 	  be processed, which would not block. Any attempt to get non-existing
304 	  data would result in a #STOP# exception (instead of blocking until
305 	  data is available).
306 
307 	  If #only_blocked# flag is #FALSE# then any further attempt to read
308 	  from this #DataPool# (as well as from any #DataPool# connected
309 	  to this one) will result in a #STOP# exception. */
310    void		stop(bool only_blocked=false);
311 
312       /** @name Adding data.
313 	  Please note, that these functions are for not connected #DataPool#s
314 	  only. You can not add data to a #DataPool#, which is connected
315 	  to another #DataPool# or to a file.
316 	*/
317       //@{
318       /** Appends the new block of data to the #DataPool#. There are two
319 	  \Ref{add_data}() functions available. One is for adding data
320 	  sequentially. It keeps track of the last byte position, which has
321 	  been stored {\bf by it} and always appends the next block after
322 	  this position. The other \Ref{add_data}() can store data anywhere.
323 
324 	  The function will unblock readers waiting for data if this data
325 	  arrives with this block. It may also trigger some {\em trigger
326 	  callbacks}, which may have been added by means of \Ref{add_trigger}()
327 	  function.
328 
329 	  {\bf Note:} After all the data has been added, it's necessary
330 	  to call \Ref{set_eof}() to tell the #DataPool# that nothing else
331 	  is expected.
332 
333 	  {\bf Note:} This function may not be called if the #DataPool#
334 	  has been connected to something.
335 
336 	  @param buffer data to append
337 	  @param size length of the {\em buffer}
338       */
339    void		add_data(const void * buffer, int size);
340 
341       /** Stores the specified block of data at the specified offset.
342 	  Like the function above this one can also unblock readers
343 	  waiting for data and engage trigger callbacks. The difference
344 	  is that {\bf this} function can store data anywhere.
345 
346 	  {\bf Note:} After all the data has been added, it's necessary
347 	  to call \Ref{set_eof}() to tell the #DataPool# that nothing else
348 	  is expected.
349 
350 	  {\bf Note:} This function may not be called if the #DataPool#
351 	  has been connected to something.
352 
353 	  @param buffer data to store
354 	  @param offset where to store the data
355 	  @param size length of the {\em buffer} */
356    void		add_data(const void * buffer, int offset, int size);
357 
358       /** Tells the #DataPool# that all data has been added and nothing else
359 	  is anticipated. When #EOF# is true, any reader attempting to read
360 	  non existing data will not be blocked. It will either read #ZERO#
361 	  bytes or will get an #ByteStream::EndOfFile# exception (see \Ref{get_data}()).
362 	  Calling this function will also activate all registered trigger
363 	  callbacks.
364 
365 	  {\bf Note:} This function is meaningless and does nothing
366 	  when the #DataPool# is connected to another #DataPool# or to
367 	  a file. */
368    void		set_eof(void);
369       //@}
370 
371       /** @name Accessing data.
372 	  These functions provide direct and sequential access to the
373 	  data of the #DataPool#. If the #DataPool# is not connected
374 	  (contains some real data) then it handles the requests itself.
375 	  Otherwise they are forwarded to the master #DataPool# or the file.
376 	*/
377       //@{
378       /** Attempts to return a block of data at the given #offset#
379 	  of the given #size#.
380 
381 	  \begin{enumerate}
382 	     \item If the #DataPool# is connected to another #DataPool# or
383 	           to a file, the request will just be forwarded to them.
384 	     \item If the #DataPool# is not connected to anything and
385 	           some of the data requested is in the internal buffer,
386 		   the function copies available data to #buffer# and returns
387 		   immediately.
388 
389 		   If there is no data available, and \Ref{is_eof}() returns
390 		   #FALSE#, the reader (and the thread) will be {\bf blocked}
391 		   until the data actually arrives. Please note, that since
392 		   the reader is blocked, it should run in a separate thread
393 		   so that other threads have a chance to call \Ref{add_data}().
394 		   If there is no data available, but \Ref{is_eof}() is #TRUE#
395 		   the behavior is different and depends on the #DataPool#'s
396 		   estimate of the file size:
397 		   \begin{itemize}
398 		      \item If #DataPool# learns from the IFF structure of the
399 		            data, that its size should be greater than it
400 			    really is, then any attempt to read non-existing
401 			    data in the range of {\em valid} offsets will
402 			    result in an #ByteStream::EndOfFile# exception. This is done to
403 			    indicate, that there was an error in adding data,
404 			    and the data requested is {\bf supposed} to be
405 			    there, but has actually not been added.
406 		      \item If #DataPool#'s expectations about the data size
407 		            coincide with the reality then any attempt to
408 			    read data beyond the legal range of offsets will
409 			    result in #ZERO# bytes returned.
410 		   \end{itemize}.
411           \end{enumerate}.
412 
413 	  @param buffer Buffer to be filled with data
414 	  @param offset Offset in the #DataPool# to read data at
415 	  @param size Size of the {\em buffer}
416 	  @return The number of bytes actually read
417 	  @exception STOP The stream has been stopped
418 	  @exception EOF The requested data is not there and will not be added,
419 	             although it should have been.
420       */
421    int		get_data(void * buffer, int offset, int size);
422 
423       /** Returns a \Ref{ByteStream} to access contents of the #DataPool#
424 	  sequentially. By reading from the returned stream you basically
425           call \Ref{get_data}() function. Thus, everything said for it
426 	  remains true for the stream too. */
427    GP<ByteStream>	get_stream(void);
428       //@}
429 
430       /** @name State querying functions. */
431       //@{
432       /** Returns #TRUE# if this #DataPool# is connected to another #DataPool#
433 	  or to a file. */
434    bool		is_connected(void) const;
435 
436       /** Returns #TRUE# if all data available for offsets from
437 	  #start# till #start+length-1#. If #length# is negative, the
438           range is assumed to extend up to the end of the #DataPool#.
439 	  This function works both for connected and not connected #DataPool#s.
440 	  Once it returned #TRUE# for some offsets range, you can be
441 	  sure that the subsequent \Ref{get_data}() request will not block.
442       */
443    bool		has_data(int start, int length);
444 
445       /* Returns #TRUE# if no more data is planned to be added.
446 
447 	 {\bf Note:} This function always returns #TRUE# when the #DataPool#
448 	 has been initialized with a file name. */
is_eof(void)449    bool		is_eof(void) const {return eof_flag;}
450 
451       /** Returns the {\em length} of data in the #DataPool#. The value
452 	  returned depends on the mode of operation:
453 	  \begin{itemize}
454 	     \item If the #DataPool# is not connected to anything then
455 	           the length returned is either calculated by interpreting
456 		   the IFF structure of stored data (if successful) or
457 		   by calculating the real size of data after \Ref{set_eof}()
458 		   has been called. Otherwise it is #-1#.
459 	     \item If the #DataPool# is connected to a file, the length
460 	           is calculated basing on the length passed to the
461 		   \Ref{connect}() function and the file size.
462 	     \item If the #DataPool# is connected to a master #DataPool#,
463 	           the length is calculated basing on the value returned
464 		   by the master's #get_length()# function and the length
465 		   passed to the \Ref{connect}() function.
466 	  \end{itemize}. */
467    int		get_length(void) const;
468       /** Returns the number of bytes of data available in this #DataPool#.
469 	  Contrary to the \Ref{get_length}() function, this one doesn't try
470 	  to interpret the IFF structure and predict the file length.
471 	  It just returns the number of bytes of data really available inside
472 	  the #DataPool#, if it contains data, or inside its range, if it's
473 	  connected to another #DataPool# or a file. */
get_size(void)474    int		get_size(void) const {return get_size(0, -1);}
475       //@}
476 
477       /** @name Trigger callbacks.
478 	  {\em Trigger callbacks} are special callbacks called when
479 	  all data for the given range of offsets has been made available.
480 	  Since reading unavailable data may result in a thread block,
481 	  which may be bad, the usage of {\em trigger callbacks} appears
482 	  to be a convenient way to signal availability of data.
483 
484 	  You can add a trigger callback in two ways:
485 	  \begin{enumerate}
486 	     \item By specifying a range. This is the most general case
487 	     \item By providing just one {\em threshold}. In this case
488 	           the range is assumed to start from offset #ZERO# and
489 		   last for {\em threshold}+1 bytes.
490 	  \end{enumerate}
491 	*/
492       //@{
493       /** Associates the specified {\em trigger callback} with the
494 	  given data range.
495 
496 	  {\bf Note:} The callback may be called immediately if all
497 	  data for the given range is already available or #EOF# is #TRUE#.
498 
499 	  @param start The beginning of the range for which all data
500 	         should be available
501 	  @param length If the {\em length} is not negative then the callback
502 	         will be called when there is data available for every
503 		 offset from {\em start} to {\em start+length-1}.
504 	         If {\em thresh} is negative, the callback is called after
505 		 #EOF# condition has been set.
506 	  @param callback Function to call
507 	  @param cl_data Argument to pass to the callback when it's called. */
508    void		add_trigger(int start, int length,
509 			    void (* callback)(void *), void * cl_data);
510 
511       /** Associates the specified {\em trigger callback} with the
512 	  specified threshold.
513 
514 	  This function is a simplified version of the function above.
515 	  The callback will be called when there is data available for
516 	  every offset from #0# to #thresh#, if #thresh# is positive, or
517 	  when #EOF# condition has been set otherwise. */
518 
519    void		add_trigger(int thresh,
520                             void (* callback)(void *), void * cl_data);
521 
522       /** Use this function to unregister callbacks, which are no longer
523 	  needed. {\bf Note!} It's important to do it when the client
524 	  is about to be destroyed. */
525    void		del_trigger(void (* callback)(void *), void *  cl_data);
526 
527       //@}
528 
529       /** Loads data from the file into memory. This function is only useful
530 	  for #DataPool#s getting data from a file. It descends the #DataPool#s
531 	  hierarchy until it either reaches a file-connected #DataPool#
532 	  or #DataPool# containing the real data. In the latter case it
533 	  does nothing, in the first case it makes the #DataPool# read all
534 	  data from the file into memory and stop using the file.
535 
536 	  This may be useful when you want to overwrite the file and leave
537 	  existing #DataPool#s with valid data. */
538    void		load_file(void);
539       /** This function will make every #DataPool# in the program, which
540 	  is connected to a file, to load the file contents to the main
541 	  memory and close the file. This feature is important when you
542 	  want to do something with the file like remove or overwrite it
543 	  not affecting the rest of the program. */
544    static void	load_file(const GURL &url);
545 
546       /** This function will remove OpenFiles filelist. */
547    static void	close_all(void);
548 
549       // Internal. Used by 'OpenFiles'
550    void		clear_stream(const bool release = true);
551 
552       /** Useful in comparing data pools.  Returns true if dirived from
553           same URL or bytestream. */
554    bool simple_compare(DataPool &pool) const;
555 
556 
557 private:
558    bool		eof_flag;
559    bool		stop_flag;
560    bool		stop_blocked_flag;
561 
562    Counter	*active_readers;
563 
564       // Source or storage of data
565    GP<DataPool>		pool;
566    GURL		furl;
567    GP<OpenFiles_File>   fstream;
568    GCriticalSection	class_stream_lock;
569    GP<ByteStream>	data;
570    GCriticalSection	data_lock;
571    BlockList		*block_list;
572    int			add_at;
573    int			start, length;
574 
575       // List of readers waiting for data
576    GPList<Reader>	readers_list;
577    GCriticalSection	readers_lock;
578 
579       // Triggers
580    GPList<Trigger>	triggers_list;		// List of passed or our triggers
581    GCriticalSection	triggers_lock;		// Lock for the list above
582    GCriticalSection	trigger_lock;		// Lock for static_trigger_cb()
583 
584    void		init(void);
585    void		wait_for_data(const GP<Reader> & reader);
586    void		wake_up_all_readers(void);
587    void		check_triggers(void);
588    int		get_data(void * buffer, int offset, int size, int level);
589    int		get_size(int start, int length) const;
590    void		restart_readers(void);
591 
592 //   static void	static_trigger_cb(GP<GPEnabled> &);
593    static void	static_trigger_cb(void *);
594    void		trigger_cb(void);
595    void		analyze_iff(void);
596    void		added_data(const int offset, const int size);
597 public:
598   static const char *Stop;
599   friend class FCPools;
600 };
601 
602 inline bool
simple_compare(DataPool & pool)603 DataPool::simple_compare(DataPool &pool) const
604 {
605   // return true if these pools are identical.  False means they may or may
606   // not be identical.
607   return (this == &pool)
608     ||(furl.is_valid()&&!furl.is_empty()&&pool.furl.is_valid()&&(furl == pool.furl))
609     ||(data && (data == pool.data));
610 }
611 
612 inline bool
is_connected(void)613 DataPool::is_connected(void) const
614 {
615    return furl.is_local_file_url() || pool!=0;
616 }
617 
618 //@}
619 
620 
621 #ifdef HAVE_NAMESPACES
622 }
623 # ifndef NOT_USING_DJVU_NAMESPACE
624 using namespace DJVU;
625 # endif
626 #endif
627 #endif
628