source: trunk/libdjvu/GThreads.h @ 209

Last change on this file since 209 was 206, checked in by Eugene Romanenko, 14 years ago

DJVU plugin: djvulibre updated to version 3.5.19

File size: 23.4 KB
Line 
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// $Id: GThreads.h,v 1.11 2007/03/25 20:48:32 leonb Exp $
57// $Name: release_3_5_19 $
58
59#ifndef _GTHREADS_H_
60#define _GTHREADS_H_
61#ifdef HAVE_CONFIG_H
62#include "config.h"
63#endif
64#if NEED_GNUG_PRAGMAS
65# pragma interface
66#endif
67
68
69/** @name GThreads.h
70
71    Files #"GThreads.h"# and #"GThreads.cpp"# implement common entry points
72    for multithreading on multiple platforms.  Each execution thread is
73    represented by an instance of class \Ref{GThread}.  Synchronization is
74    provided by class \Ref{GMonitor} which implements a monitor (C.A.R Hoare,
75    Communications of the ACM, 17(10), 1974).
76
77    The value of compiler symbol #THREADMODEL# selects an appropriate
78    implementation for these classes. The current implementation supports
79    the following values:
80    \begin{description}
81    \item[-DTHREADMODEL=NOTHREADS] Dummy implementation.  This is a
82          good choice when the multithreading features are not required,
83          because it minimizes the portability problems.  This is currently
84          the default when compiling under Unix.
85    \item[-DTHREADMODEL=WINTHREADS] Windows implementation.
86          This is the default when compiling under Windows.
87    \item[-DTHREADMODEL=MACTHREADS] Macintosh implementation,
88          which is based on the MacOS cooperative model. The current
89          implementation does not yet fully support synchronization.
90          This is the default when compiling under MacOS.
91    \item[-DTHREADMODEL=POSIXTHREADS] Posix implementation.
92          This implementation also supports DCE threads. The behavior of
93          the code is subject to the quality of the system implementation of
94          Posix threads.
95    \item[-DTHREADMODEL=COTHREADS] Custom cooperative threads.
96          These custom threads do not redefine system calls. Before executing
97          a potentially blocking system function, each thread must explicitly
98          check whether it is going to block and yield control explicitly if
99          this is the case.  This code must be compiled with a patched version
100          of egcs-1.1.1 \URL{http://egcs.cygnus.com}. The patch addresses
101          exception thread-safety and is provided in #"@Tools/libgcc2.c.diff"#.
102          Once you get the right compiler, this implementation is remarkably
103          compact and portable. A variety of processors are supported,
104          including mips, intel, sparc, hppa, and alpha.
105    \item[-DTHREADMODEL=JRITHREADS] Java implementation hooks.
106          Multi-threading within a Netscape plugin can be tricky.  A simple
107          idea however consists of implementing the threading primitives in
108          Java and to access them using JRI.  The classes just contain a
109          JRIGlobalRef.  This is not a real implementation since everything
110          (Java code, native functions, stubs, exception thread safety) must
111          be addressed by the plugin source code. Performance may be a serious
112          issue.
113    \end{description}
114   
115    {\bf Portability}: The simultaneous use of threads and exceptions caused a
116    lot of portability headaches under Unix.  We eventually decided to
117    implement the COTHREADS cooperative threads (because preemptive threads
118    have more problems) and to patch EGCS in order to make exception handling
119    COTHREAD-safe.
120
121    @memo
122    Portable threads
123    @author
124    L\'eon Bottou <leonb@research.att.com> -- initial implementation.\\
125    Praveen Guduru <praveen@sanskrit.lz.att.com> -- mac implementation.
126
127// From: Leon Bottou, 1/31/2002
128// Almost unchanged by Lizardtech.
129// GSafeFlags should go because it not as safe as it claims.
130
131    @version
132    #$Id: GThreads.h,v 1.11 2007/03/25 20:48:32 leonb Exp $# */
133//@{
134
135
136#include "DjVuGlobal.h"
137#include "GException.h"
138
139#define NOTHREADS     0
140#define COTHREADS     1
141#define JRITHREADS    2
142#define POSIXTHREADS  10
143#define WINTHREADS    11
144#define MACTHREADS    12
145
146// Known platforms
147#ifndef THREADMODEL
148#if defined(WIN32)
149#define THREADMODEL WINTHREADS
150#endif
151#if defined(macintosh)
152#define THREADMODEL MACTHREADS
153#endif
154#endif
155
156// Exception emulation is not thread safe
157#ifdef USE_EXCEPTION_EMULATION
158#undef  THREADMODEL
159#define THREADMODEL NOTHREADS
160#endif
161// Default is nothreads
162#ifndef THREADMODEL
163#define THREADMODEL NOTHREADS
164#endif
165
166// ----------------------------------------
167// INCLUDES
168
169#if THREADMODEL==WINTHREADS
170#ifndef _WINDOWS_
171#define WIN32_LEAN_AND_MEAN
172#include "windows.h"
173#endif
174#endif
175
176#if THREADMODEL==MACTHREADS
177#include <threads.h>
178#endif
179
180#if THREADMODEL==POSIXTHREADS
181#include <sys/types.h>
182#include <sys/time.h>
183#include <unistd.h>
184#undef TRY
185#undef CATCH
186#define _CMA_NOWRAPPERS_
187#include <pthread.h>
188#endif
189
190#if THREADMODEL==JRITHREADS
191#include "jri.h"
192#endif
193
194#if THREADMODEL==COTHREADS
195#include <sys/types.h>
196#include <sys/time.h>
197#include <unistd.h>
198#endif
199
200
201// ----------------------------------------
202// PORTABLE CLASSES
203
204
205#ifdef HAVE_NAMESPACES
206namespace DJVU {
207# ifdef NOT_DEFINED // Just to fool emacs c++ mode
208}
209#endif
210#endif
211
212
213
214/** Thread class.  A multithreaded process is composed of a main execution
215    thread and of several secondary threads.  Each secondary thread is
216    represented by a #GThread# object.  The amount of memory required for the
217    stack of a secondary thread is defined when the #GThread# object is
218    constructed.  The execution thread is started when function
219    \Ref{GThread::create} is called.  The destructor of class GThread waits
220    until the thread terminanes.  Note that the execution can be terminated at
221    any time (with possible prejudice) by calling \Ref{GThread::terminate}.
222
223    Several static member functions control the thread scheduler.  Function
224    \Ref{GThread::yield} relinquishes the processor to another thread.
225    Function \Ref{GThread::select} (#COTHREADS# only) provides a thread-aware
226    replacement for the well-known unix system call #select#. 
227
228    {\bf Note} --- Both the copy constructor and the copy operator are declared
229    as private members. It is therefore not possible to make multiple copies
230    of instances of this class, as implied by the class semantic. */
231
232class GThread {
233public:
234  /** Constructs a new thread object.  Memory is allocated for the
235      thread, but the thread is not started.
236      Argument #stacksize# is used by the #COTHREADS# model only for
237      specifying the amount of memory needed for the processor stack. A
238      negative value will be replaced by a suitable default value of 128Kb.
239      A minimum value of 32Kb is silently enforced. */
240  GThread(int stacksize = -1);
241  /** Destructor.  Destroying the thread object while the thread is running is
242      perfectly ok since it only destroys the thread identifier.  Execution
243      will continue without interference. */
244  ~GThread();
245  /** Starts the thread. The new thread executes function #entry# with
246      argument #arg#.  The thread terminates when the function returns.  A
247      thread cannot be restarted after its termination. You must create a new
248      #GThread# object. */
249  int  create(void (*entry)(void*), void *arg);
250  /** Terminates a thread with extreme prejudice. The thread is removed from
251      the scheduling list.  Execution terminates regardless of the execution
252      status of the thread function. Automatic variables may or may not be
253      destroyed. This function must be considered as a last resort since
254      memory may be lost. */
255  void terminate();
256  /** Causes the current thread to relinquish the processor.  The scheduler
257      selects a thread ready to run and transfers control to that thread.  The
258      actual effect of #yield# heavily depends on the selected implementation.
259      Function #yield# usually returns zero when the execution of the current
260      thread is resumed.  It may return a positive number when it can
261      determine that the current thread will remain the only runnable thread
262      for some time.  You may then call function \Ref{get_select} to
263      obtain more information. */
264  static int yield();
265  /** Returns a value which uniquely identifies the current thread. */
266  static void *current();
267
268#if THREADMODEL==WINTHREADS
269private:
270  HANDLE hthr;
271  DWORD  thrid;
272#elif THREADMODEL==MACTHREADS
273private:
274  unsigned long thid;
275  static pascal void *start(void *arg);
276#elif THREADMODEL==POSIXTHREADS
277private:
278  pthread_t hthr;
279  static void *start(void *arg);
280#elif THREADMODEL==JRITHREADS
281private:
282  JRIGlobalRef obj;
283#elif THREADMODEL==COTHREADS
284  friend class GMonitor;
285public:
286  class cotask;
287  class cotask *task;
288  /** Replaces system call #select# (COTHREADS only).  The #COTHREADS# model
289      does not redefine system function.  System functions therefore can
290      potentially block the whole process (instead of blocking the current
291      thread only) because the system is not aware of the #COTHREADS#
292      scheduler.  The function #GThread::select# is a #COTHREADS#-aware
293      replacement for the well known system function #select#.  You can also
294      use #GThread::select# for making sure that calls to system functions
295      will not block the entire process, as demonstrated below:
296      \begin{verbatim}
297      int
298      gthread_read(int fd, void *buffer, size_t len)
299      {
300        fd_set rdset;
301        FD_ZERO(&rdset);
302        FD_SET(fd, &rdset);
303        GThread::select(fd+1, &rdset, 0, 0, 0);
304        return read(fd, buffer, len);
305      }
306      \end{verbatim} */
307  static int select(int nfds, fd_set*, fd_set*, fd_set*, struct timeval*);
308  /** Provide arguments for system call #select# (COTHREADS only). It may be
309      appropriate to call the real system call #select# if the current thread
310      is the only thread ready to run.  Other threads however may wake up when
311      certain file descriptors are ready or when a certain delay expires.
312      Function #get_select# returns this information by filling the three
313      usual file descriptor sets (similar to the arguments of system call
314      #select#).  It also returns a timeout #timeout# expressed in
315      milliseconds.  Note that this timeout is zero is the current thread is
316      not the sole thread ready to run. */
317  static void get_select(int &nfds, fd_set*, fd_set*, fd_set*, unsigned long &timeout);
318  /** Install hooks in the scheduler (COTHREADS only).  The hook function
319      #call# is called when a new thread is created (argument is
320      #GThread::CallbackCreate#), when a thread terminates (argument is
321      #GThread::CallbackTerminate#), or when thread is unblocked (argument is
322      #GThread::CallbackUnblock#).  This callback can be useful in certain GUI
323      toolkits where the most convenient method for scheduling the threads
324      consists in setting a timer event that calls \Ref{GThread::yield}.  */
325  static void set_scheduling_callback(void (*call)(int));
326  enum { CallbackCreate, CallbackTerminate, CallbackUnblock };
327
328#endif
329public:
330  // Should be considered as private
331  void (*xentry)(void*);
332  void  *xarg;
333private:
334  // Disable default members
335  GThread(const GThread&);
336  GThread& operator=(const GThread&);
337};
338
339
340/** Monitor class.  Monitors have been first described in (C.A.R Hoare,
341    Communications of the ACM, 17(10), 1974).  This mechanism provides the
342    basic mutual exclusion (mutex) and thread notification facilities
343    (condition variables).
344   
345    Only one thread can own the monitor at a given time.  Functions
346    \Ref{enter} and \Ref{leave} can be used to acquire and release the
347    monitor. This mutual exclusion provides an efficient way to protect
348    segment of codes ({\em critical sections}) which should not be
349    simultaneously executed by two threads. Class \Ref{GMonitorLock} provides
350    a convenient way to do this effectively.
351   
352    When the thread owning the monitor calls function \Ref{wait}, the monitor
353    is released and the thread starts waiting until another thread calls
354    function \Ref{signal} or \Ref{broadcast}.  When the thread wakes-up, it
355    re-acquires the monitor and function #wait# returns.  Since the signaling
356    thread must acquire the monitor before calling functions #signal# and
357    #broadcast#, the signaled thread will not be able to re-acquire the
358    monitor until the signaling thread(s) releases the monitor.
359   
360    {\bf Note} --- Both the copy constructor and the copy operator are declared
361    as private members. It is therefore not possible to make multiple copies
362    of instances of this class, as implied by the class semantic. */
363
364class GMonitor
365{
366public:
367  GMonitor();
368  ~GMonitor();
369  /** Enters the monitor.  If the monitor is acquired by another thread this
370      function waits until the monitor is released.  The current thread then
371      acquires the monitor.  Calls to #enter# and #leave# may be nested. */
372  void enter();
373  /** Leaves the monitor.  The monitor counts how many times the current
374      thread has entered the monitor.  Function #leave# decrement this count.
375      The monitor is released when this count reaches zero.  An exception is
376      thrown if this function is called by a thread which does not own the
377      monitor. */
378  void leave();
379  /** Waits until the monitor is signaled.  The current thread atomically
380      releases the monitor and waits until another thread calls function
381      #signal# or #broadcast#.  Function #wait# then re-acquires the monitor
382      and returns.  An exception is thrown if this function is called by a
383      thread which does not own the monitor. */
384  void wait();
385  /** Waits until the monitor is signaled or a timeout is reached.  The
386      current thread atomically releases the monitor and waits until another
387      thread calls function #signal# or #broadcast# or a maximum of #timeout#
388      milliseconds.  Function #wait# then re-acquires the monitor and returns.
389      An exception is thrown if this function is called by a thread which does
390      not own the monitor. */
391  void wait(unsigned long timeout);
392  /** Signals one waiting thread.  Function #signal# wakes up at most one of
393      the waiting threads for this monitor.  An exception is thrown if this
394      function is called by a thread which does not own the monitor. */
395  void signal();
396  /** Signals all waiting threads. Function #broadcast# wakes up all the
397      waiting threads for this monitor.  An exception is thrown if this
398      function is called by a thread which does not own the monitor. */
399  void broadcast();
400private:
401#if THREADMODEL==WINTHREADS
402  int ok;
403  int count;
404  DWORD locker;
405  CRITICAL_SECTION cs;
406  struct thr_waiting *head;
407  struct thr_waiting *tail;
408#elif THREADMODEL==MACTHREADS
409  int ok;
410  int count;
411  unsigned long locker;
412  int wlock;
413  int wsig;
414#elif THREADMODEL==POSIXTHREADS
415  int ok;
416  int count;
417  pthread_t locker;
418  pthread_mutex_t mutex;
419  pthread_cond_t cond;
420#elif THREADMODEL==COTHREADS
421  int ok;
422  int count;
423  void *locker;
424  int wlock;
425  int wsig;
426#elif THREADMODEL==JRITHREADS
427  JRIGlobalRef obj;
428#endif 
429private:
430  // Disable default members
431  GMonitor(const GMonitor&);
432  GMonitor& operator=(const GMonitor&);
433};
434
435
436
437
438// ----------------------------------------
439// NOTHREADS INLINES
440
441#if THREADMODEL==NOTHREADS
442inline GThread::GThread(int stacksize) {}
443inline GThread::~GThread(void) {}
444inline void GThread::terminate() {}
445inline int GThread::yield() { return 0; }
446inline void* GThread::current() { return 0; }
447inline GMonitor::GMonitor() {}
448inline GMonitor::~GMonitor() {}
449inline void GMonitor::enter() {}
450inline void GMonitor::leave() {}
451inline void GMonitor::wait() {}
452inline void GMonitor::wait(unsigned long timeout) {}
453inline void GMonitor::signal() {}
454inline void GMonitor::broadcast() {}
455#endif // NOTHREADS
456
457
458// ----------------------------------------
459// SCOPE LOCK
460
461
462/** Wrapper for mutually exclusive code.
463    This class locks a specified critical section (see \Ref{GCriticalSection})
464    at construction time and unlocks it at destruction time. It provides a
465    convenient way to take advantage of the C++ implicit destruction of
466    automatic variables in order to make sure that the monitor is
467    released when exiting the protected code.  The following code will release
468    the monitor when the execution thread leaves the protected scope, either
469    because the protected code has executed successfully, or because an
470    exception was thrown.
471    \begin{verbatim}
472      {      -- protected scope
473         static GMonitor theMonitor;
474         GMonitorLock lock(&theMonitor)
475         ... -- protected code
476      }
477    \end{verbatim}
478    This construct will do nothing when passed a null pointer.
479*/
480class GMonitorLock
481{
482private:
483  GMonitor *gsec;
484public:
485  /** Constructor. Enters the monitor #gsec#. */
486  GMonitorLock(GMonitor *gsec) : gsec(gsec) 
487    { if (gsec) gsec->enter(); };
488  /** Destructor. Leaves the associated monitor. */
489  ~GMonitorLock() 
490    { if (gsec) gsec->leave(); };
491};
492
493
494
495// ----------------------------------------
496// GSAFEFLAGS (not so safe)
497
498
499/** A thread safe class representing a set of flags. The flags are protected
500    by \Ref{GMonitor}, which is attempted to be locked whenever somebody
501    accesses the flags. One can modify the class contents using one of
502    two functions: \Ref{test_and_modify}() and \Ref{wait_and_modify}().
503    Both of them provide atomic operation of testing (first) and modification
504    (second). The flags remain locked between the moment of testing and
505    modification, which guarantees, that their state cannot be changed in
506    between of these operations. */
507class GSafeFlags : public GMonitor
508{
509private:
510   volatile long flags;
511public:
512      /// Constructs #GSafeFlags# object.
513   GSafeFlags(long flags=0);
514
515      /** Assignment operator. Will also wake up threads waiting for the
516          flags to change. */
517   GSafeFlags & operator=(long flags);
518
519      /** Returns the value of the flags */
520   operator long(void) const;
521      /** Modifies the flags by ORing them with the provided mask. A broadcast
522          will be sent after the modification is done. */
523   GSafeFlags & operator|=(long mask);
524      /** Modifies the flags by ANDing them with the provided mask. A broadcast
525          will be sent after the modification is done. */
526   GSafeFlags & operator&=(long mask);
527
528      /** If all bits mentioned in #set_mask# are set in the flags and all
529          bits mentioned in #clr_mask# are cleared in the flags, it sets all
530          bits from #set_mask1# in the flags, clears all flags from
531          #clr_mask1# in the flags and returns #TRUE#. Otherwise returns
532          #FALSE#. */
533   bool test_and_modify(long set_mask, long clr_mask,
534                        long set_mask1, long clr_mask1);
535
536      /** Waits until all bits mentioned in #set_mask# are set in the flags
537          and all bits mentioned in #clr_flags# are cleared in the flags.
538          After that it sets bits from #set_mask1# and clears bits from
539          #clr_mask1# in the flags. */
540   void wait_and_modify(long set_mask, long clr_mask,
541                        long set_mask1, long clr_mask1);
542
543      /** Waits until all bits set in #set_mask# are set in the flags and
544          all bits mentioned in #clr_mask# are cleared in the flags. */
545   void wait_for_flags(long set_mask, long clr_mask=0) const;
546
547      /** Modifies the flags by setting all bits mentioned in #set_mask#
548          and clearing all bits mentioned in #clr_mask#. If the flags have
549          actually been modified, a broadcast will be sent. */
550   void modify(long set_mask, long clr_mask);
551};
552
553inline
554GSafeFlags::GSafeFlags(long xflags) 
555  : flags(xflags) 
556{
557}
558
559inline void
560GSafeFlags::wait_for_flags(long set_mask, long clr_mask) const
561{
562   ((GSafeFlags *) this)->wait_and_modify(set_mask, clr_mask, 0, 0);
563}
564
565inline void
566GSafeFlags::modify(long set_mask, long clr_mask)
567{
568   test_and_modify(0, 0, set_mask, clr_mask);
569}
570
571inline GSafeFlags &
572GSafeFlags::operator|=(long mask)
573{
574   test_and_modify(0, 0, mask, 0);
575   return *this;
576}
577
578inline GSafeFlags &
579GSafeFlags::operator&=(long mask)
580{
581   test_and_modify(0, 0, 0, ~mask);
582   return *this;
583}
584
585//@}
586
587
588
589
590// ----------------------------------------
591// COMPATIBILITY CLASSES
592
593
594// -- these classes are no longer documented.
595
596class GCriticalSection : protected GMonitor
597{
598public:
599  void lock() 
600    { GMonitor::enter(); };
601  void unlock() 
602    { GMonitor::leave(); };
603};
604
605class GEvent : protected GMonitor
606{
607private:
608  int status;
609public:
610  GEvent() 
611    : status(0) { };
612  void set() 
613    { if (!status) { enter(); status=1; signal(); leave(); } };
614  void wait() 
615    { enter(); if (!status) GMonitor::wait(); status=0; leave(); };
616  void wait(int timeout) 
617    { enter(); if (!status) GMonitor::wait(timeout); status=0; leave(); };
618};
619
620class GCriticalSectionLock
621{
622private:
623  GCriticalSection *gsec;
624public:
625  GCriticalSectionLock(GCriticalSection *gsec) : gsec(gsec) 
626    { if (gsec) gsec->lock(); };
627  ~GCriticalSectionLock() 
628    { if (gsec) gsec->unlock(); };
629};
630
631
632// ----------------------------------------
633
634#ifdef HAVE_NAMESPACES
635}
636# ifndef NOT_USING_DJVU_NAMESPACE
637using namespace DJVU;
638# endif
639#endif
640#endif //_GTHREADS_H_
641
Note: See TracBrowser for help on using the repository browser.