source: trunk/libdjvu/GThreads.h @ 81

Last change on this file since 81 was 17, checked in by Eugene Romanenko, 16 years ago

update makefiles, remove absolute paths, update djvulibre to version 3.5.17

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