Blame libdjvu/GThreads.h

Packit df99a1
//C-  -*- C++ -*-
Packit df99a1
//C- -------------------------------------------------------------------
Packit df99a1
//C- DjVuLibre-3.5
Packit df99a1
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
Packit df99a1
//C- Copyright (c) 2001  AT&T
Packit df99a1
//C-
Packit df99a1
//C- This software is subject to, and may be distributed under, the
Packit df99a1
//C- GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- or (at your option) any later version. The license should have
Packit df99a1
//C- accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C-
Packit df99a1
//C- This program is distributed in the hope that it will be useful,
Packit df99a1
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit df99a1
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit df99a1
//C- GNU General Public License for more details.
Packit df99a1
//C- 
Packit df99a1
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
Packit df99a1
//C- Lizardtech Software.  Lizardtech Software has authorized us to
Packit df99a1
//C- replace the original DjVu(r) Reference Library notice by the following
Packit df99a1
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
Packit df99a1
//C-
Packit df99a1
//C-  ------------------------------------------------------------------
Packit df99a1
//C- | DjVu (r) Reference Library (v. 3.5)
Packit df99a1
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
Packit df99a1
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
Packit df99a1
//C- | 6,058,214 and patents pending.
Packit df99a1
//C- |
Packit df99a1
//C- | This software is subject to, and may be distributed under, the
Packit df99a1
//C- | GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- | or (at your option) any later version. The license should have
Packit df99a1
//C- | accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- | from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C- |
Packit df99a1
//C- | The computer code originally released by LizardTech under this
Packit df99a1
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
Packit df99a1
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
Packit df99a1
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
Packit df99a1
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
Packit df99a1
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
Packit df99a1
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
Packit df99a1
//C- | General Public License.   This grant only confers the right to 
Packit df99a1
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
Packit df99a1
//C- | the extent such infringement is reasonably necessary to enable 
Packit df99a1
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
Packit df99a1
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
Packit df99a1
//C- | any greater extent that may be necessary to utilize further 
Packit df99a1
//C- | modifications or combinations.
Packit df99a1
//C- |
Packit df99a1
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
Packit df99a1
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
Packit df99a1
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
Packit df99a1
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Packit df99a1
//C- +------------------------------------------------------------------
Packit df99a1
Packit df99a1
#ifndef _GTHREADS_H_
Packit df99a1
#define _GTHREADS_H_
Packit df99a1
#ifdef HAVE_CONFIG_H
Packit df99a1
#include "config.h"
Packit df99a1
#endif
Packit df99a1
#if NEED_GNUG_PRAGMAS
Packit df99a1
# pragma interface
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
/** @name GThreads.h
Packit df99a1
Packit df99a1
    Files #"GThreads.h"# and #"GThreads.cpp"# implement common entry points
Packit df99a1
    for multithreading on multiple platforms.  Each execution thread is
Packit df99a1
    represented by an instance of class \Ref{GThread}.  Synchronization is
Packit df99a1
    provided by class \Ref{GMonitor} which implements a monitor (C.A.R Hoare,
Packit df99a1
    Communications of the ACM, 17(10), 1974).
Packit df99a1
Packit df99a1
    @memo
Packit df99a1
    Portable threads
Packit df99a1
    @author
Packit df99a1
    L\'eon Bottou <leonb@research.att.com> -- initial implementation.\\
Packit df99a1
    Praveen Guduru <praveen@sanskrit.lz.att.com> -- mac implementation.
Packit df99a1
Packit df99a1
// From: Leon Bottou, 1/31/2002
Packit df99a1
// Almost unchanged by Lizardtech.
Packit df99a1
// GSafeFlags should go because it not as safe as it claims.
Packit df99a1
// Reduced to only WINTHREADS and POSIXTHREADS around djvulibre-3.5.25
Packit df99a1
Packit df99a1
*/
Packit df99a1
//@{
Packit df99a1
Packit df99a1
Packit df99a1
#include "DjVuGlobal.h"
Packit df99a1
#include "GException.h"
Packit df99a1
Packit df99a1
// Known platforms
Packit df99a1
# ifdef _WIN32
Packit df99a1
#  define WINTHREADS 1
Packit df99a1
# elif HAVE_PTHREAD
Packit df99a1
#  define POSIXTHREADS 1
Packit df99a1
# else
Packit df99a1
#  error "Libdjvu requires thread support"
Packit df99a1
# endif
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// INCLUDES
Packit df99a1
Packit df99a1
#if WINTHREADS
Packit df99a1
#ifndef _WINDOWS_
Packit df99a1
#define WIN32_LEAN_AND_MEAN
Packit df99a1
#include "windows.h"
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#if POSIXTHREADS
Packit df99a1
#include <sys/types.h>
Packit df99a1
#include <sys/time.h>
Packit df99a1
#include <unistd.h>
Packit df99a1
#undef TRY
Packit df99a1
#undef CATCH
Packit df99a1
#define _CMA_NOWRAPPERS_
Packit df99a1
#include <pthread.h>
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// PORTABLE CLASSES
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
namespace DJVU {
Packit df99a1
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
/** Thread class.  A multithreaded process is composed of a main execution
Packit df99a1
    thread and of several secondary threads.  Each secondary thread is
Packit df99a1
    represented by a #GThread# object.  The amount of memory required for the
Packit df99a1
    stack of a secondary thread is defined when the #GThread# object is
Packit df99a1
    constructed.  The execution thread is started when function
Packit df99a1
    \Ref{GThread::create} is called.  The destructor of class GThread waits
Packit df99a1
    until the thread terminanes.  Note that the execution can be terminated at
Packit df99a1
    any time (with possible prejudice) by calling \Ref{GThread::terminate}.
Packit df99a1
Packit df99a1
    Several static member functions control the thread scheduler.  Function
Packit df99a1
    \Ref{GThread::yield} relinquishes the processor to another thread.
Packit df99a1
    Function \Ref{GThread::select} (#COTHREADS# only) provides a thread-aware
Packit df99a1
    replacement for the well-known unix system call #select#.  
Packit df99a1
Packit df99a1
    {\bf Note} --- Both the copy constructor and the copy operator are declared
Packit df99a1
    as private members. It is therefore not possible to make multiple copies
Packit df99a1
    of instances of this class, as implied by the class semantic. */
Packit df99a1
Packit df99a1
class GThread {
Packit df99a1
public:
Packit df99a1
  /** Constructs a new thread object.  Memory is allocated for the
Packit df99a1
      thread, but the thread is not started. 
Packit df99a1
      Argument #stacksize# is used by the #COTHREADS# model only for
Packit df99a1
      specifying the amount of memory needed for the processor stack. A
Packit df99a1
      negative value will be replaced by a suitable default value of 128Kb.
Packit df99a1
      A minimum value of 32Kb is silently enforced. */
Packit df99a1
  GThread(int stacksize = -1);
Packit df99a1
  /** Destructor.  Destroying the thread object while the thread is running is
Packit df99a1
      perfectly ok since it only destroys the thread identifier.  Execution
Packit df99a1
      will continue without interference. */
Packit df99a1
  ~GThread();
Packit df99a1
  /** Starts the thread. The new thread executes function #entry# with
Packit df99a1
      argument #arg#.  The thread terminates when the function returns.  A
Packit df99a1
      thread cannot be restarted after its termination. You must create a new
Packit df99a1
      #GThread# object. */
Packit df99a1
  int  create(void (*entry)(void*), void *arg);
Packit df99a1
  /** Terminates a thread with extreme prejudice. The thread is removed from
Packit df99a1
      the scheduling list.  Execution terminates regardless of the execution
Packit df99a1
      status of the thread function. Automatic variables may or may not be
Packit df99a1
      destroyed. This function must be considered as a last resort since
Packit df99a1
      memory may be lost. */
Packit df99a1
  void terminate();
Packit df99a1
  /** Causes the current thread to relinquish the processor.  The scheduler
Packit df99a1
      selects a thread ready to run and transfers control to that thread.  The
Packit df99a1
      actual effect of #yield# heavily depends on the selected implementation.
Packit df99a1
      Function #yield# usually returns zero when the execution of the current
Packit df99a1
      thread is resumed.  It may return a positive number when it can
Packit df99a1
      determine that the current thread will remain the only runnable thread
Packit df99a1
      for some time.  You may then call function \Ref{get_select} to
Packit df99a1
      obtain more information. */
Packit df99a1
  static int yield();
Packit df99a1
  /** Returns a value which uniquely identifies the current thread. */
Packit df99a1
  static void *current();
Packit df99a1
#if WINTHREADS
Packit df99a1
private:
Packit df99a1
  HANDLE hthr;
Packit df99a1
  DWORD  thrid;
Packit df99a1
#elif POSIXTHREADS
Packit df99a1
private:
Packit df99a1
  pthread_t hthr;
Packit df99a1
  static void *start(void *arg);
Packit df99a1
#endif
Packit df99a1
public:
Packit df99a1
  // Should be considered as private
Packit df99a1
  void (*xentry)(void*);
Packit df99a1
  void  *xarg;
Packit df99a1
private:
Packit df99a1
  // Disable default members
Packit df99a1
  GThread(const GThread&);
Packit df99a1
  GThread& operator=(const GThread&);
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
/** Monitor class.  Monitors have been first described in (C.A.R Hoare,
Packit df99a1
    Communications of the ACM, 17(10), 1974).  This mechanism provides the
Packit df99a1
    basic mutual exclusion (mutex) and thread notification facilities
Packit df99a1
    (condition variables).
Packit df99a1
    
Packit df99a1
    Only one thread can own the monitor at a given time.  Functions
Packit df99a1
    \Ref{enter} and \Ref{leave} can be used to acquire and release the
Packit df99a1
    monitor. This mutual exclusion provides an efficient way to protect
Packit df99a1
    segment of codes ({\em critical sections}) which should not be
Packit df99a1
    simultaneously executed by two threads. Class \Ref{GMonitorLock} provides
Packit df99a1
    a convenient way to do this effectively.
Packit df99a1
    
Packit df99a1
    When the thread owning the monitor calls function \Ref{wait}, the monitor
Packit df99a1
    is released and the thread starts waiting until another thread calls
Packit df99a1
    function \Ref{signal} or \Ref{broadcast}.  When the thread wakes-up, it
Packit df99a1
    re-acquires the monitor and function #wait# returns.  Since the signaling
Packit df99a1
    thread must acquire the monitor before calling functions #signal# and
Packit df99a1
    #broadcast#, the signaled thread will not be able to re-acquire the
Packit df99a1
    monitor until the signaling thread(s) releases the monitor.
Packit df99a1
    
Packit df99a1
    {\bf Note} --- Both the copy constructor and the copy operator are declared
Packit df99a1
    as private members. It is therefore not possible to make multiple copies
Packit df99a1
    of instances of this class, as implied by the class semantic. */
Packit df99a1
Packit df99a1
class GMonitor
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
  GMonitor();
Packit df99a1
  ~GMonitor();
Packit df99a1
  /** Enters the monitor.  If the monitor is acquired by another thread this
Packit df99a1
      function waits until the monitor is released.  The current thread then
Packit df99a1
      acquires the monitor.  Calls to #enter# and #leave# may be nested. */
Packit df99a1
  void enter();
Packit df99a1
  /** Leaves the monitor.  The monitor counts how many times the current
Packit df99a1
      thread has entered the monitor.  Function #leave# decrement this count.
Packit df99a1
      The monitor is released when this count reaches zero.  An exception is
Packit df99a1
      thrown if this function is called by a thread which does not own the
Packit df99a1
      monitor. */
Packit df99a1
  void leave();
Packit df99a1
  /** Waits until the monitor is signaled.  The current thread atomically
Packit df99a1
      releases the monitor and waits until another thread calls function
Packit df99a1
      #signal# or #broadcast#.  Function #wait# then re-acquires the monitor
Packit df99a1
      and returns.  An exception is thrown if this function is called by a
Packit df99a1
      thread which does not own the monitor. */
Packit df99a1
  void wait();
Packit df99a1
  /** Waits until the monitor is signaled or a timeout is reached.  The
Packit df99a1
      current thread atomically releases the monitor and waits until another
Packit df99a1
      thread calls function #signal# or #broadcast# or a maximum of #timeout#
Packit df99a1
      milliseconds.  Function #wait# then re-acquires the monitor and returns.
Packit df99a1
      An exception is thrown if this function is called by a thread which does
Packit df99a1
      not own the monitor. */
Packit df99a1
  void wait(unsigned long timeout);
Packit df99a1
  /** Signals one waiting thread.  Function #signal# wakes up at most one of
Packit df99a1
      the waiting threads for this monitor.  An exception is thrown if this
Packit df99a1
      function is called by a thread which does not own the monitor. */
Packit df99a1
  void signal();
Packit df99a1
  /** Signals all waiting threads. Function #broadcast# wakes up all the
Packit df99a1
      waiting threads for this monitor.  An exception is thrown if this
Packit df99a1
      function is called by a thread which does not own the monitor. */
Packit df99a1
  void broadcast();
Packit df99a1
private:
Packit df99a1
#if WINTHREADS
Packit df99a1
  int ok;
Packit df99a1
  int count;
Packit df99a1
  DWORD locker;
Packit df99a1
  CRITICAL_SECTION cs;
Packit df99a1
  struct thr_waiting *head;
Packit df99a1
  struct thr_waiting *tail;
Packit df99a1
#elif POSIXTHREADS
Packit df99a1
  int ok;
Packit df99a1
  int count;
Packit df99a1
  pthread_t locker;
Packit df99a1
  pthread_mutex_t mutex;
Packit df99a1
  pthread_cond_t cond;
Packit df99a1
#endif  
Packit df99a1
private:
Packit df99a1
  // Disable default members
Packit df99a1
  GMonitor(const GMonitor&);
Packit df99a1
  GMonitor& operator=(const GMonitor&);
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// SCOPE LOCK
Packit df99a1
Packit df99a1
Packit df99a1
/** Wrapper for mutually exclusive code.
Packit df99a1
    This class locks a specified critical section (see \Ref{GCriticalSection})
Packit df99a1
    at construction time and unlocks it at destruction time. It provides a
Packit df99a1
    convenient way to take advantage of the C++ implicit destruction of
Packit df99a1
    automatic variables in order to make sure that the monitor is
Packit df99a1
    released when exiting the protected code.  The following code will release
Packit df99a1
    the monitor when the execution thread leaves the protected scope, either
Packit df99a1
    because the protected code has executed successfully, or because an
Packit df99a1
    exception was thrown.
Packit df99a1
    \begin{verbatim}
Packit df99a1
      {      -- protected scope
Packit df99a1
         static GMonitor theMonitor;
Packit df99a1
         GMonitorLock lock(&theMonitor)
Packit df99a1
         ... -- protected code
Packit df99a1
      }
Packit df99a1
    \end{verbatim} 
Packit df99a1
    This construct will do nothing when passed a null pointer.
Packit df99a1
*/
Packit df99a1
class GMonitorLock 
Packit df99a1
{
Packit df99a1
private:
Packit df99a1
  GMonitor *gsec;
Packit df99a1
public:
Packit df99a1
  /** Constructor. Enters the monitor #gsec#. */
Packit df99a1
  GMonitorLock(GMonitor *gsec) : gsec(gsec) 
Packit df99a1
    { if (gsec) gsec->enter(); };
Packit df99a1
  /** Destructor. Leaves the associated monitor. */
Packit df99a1
  ~GMonitorLock() 
Packit df99a1
    { if (gsec) gsec->leave(); };
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// GSAFEFLAGS (LB: this is not foolproof-safe but can be used savely!)
Packit df99a1
Packit df99a1
/** A thread safe class representing a set of flags. The flags are protected
Packit df99a1
    by \Ref{GMonitor}, which is attempted to be locked whenever somebody
Packit df99a1
    accesses the flags. One can modify the class contents using one of
Packit df99a1
    two functions: \Ref{test_and_modify}() and \Ref{wait_and_modify}().
Packit df99a1
    Both of them provide atomic operation of testing (first) and modification
Packit df99a1
    (second). The flags remain locked between the moment of testing and
Packit df99a1
    modification, which guarantees, that their state cannot be changed in
Packit df99a1
    between of these operations. */
Packit df99a1
Packit df99a1
class GSafeFlags : public GMonitor
Packit df99a1
{
Packit df99a1
private:
Packit df99a1
   volatile long flags;
Packit df99a1
public:
Packit df99a1
      /// Constructs #GSafeFlags# object.
Packit df99a1
   GSafeFlags(long flags=0);
Packit df99a1
Packit df99a1
      /** Assignment operator. Will also wake up threads waiting for the
Packit df99a1
	  flags to change. */
Packit df99a1
   GSafeFlags & operator=(long flags);
Packit df99a1
Packit df99a1
      /** Returns the value of the flags */
Packit df99a1
   operator long(void) const;
Packit df99a1
      /** Modifies the flags by ORing them with the provided mask. A broadcast
Packit df99a1
	  will be sent after the modification is done. */
Packit df99a1
   GSafeFlags &	operator|=(long mask);
Packit df99a1
      /** Modifies the flags by ANDing them with the provided mask. A broadcast
Packit df99a1
	  will be sent after the modification is done. */
Packit df99a1
   GSafeFlags &	operator&=(long mask);
Packit df99a1
Packit df99a1
      /** If all bits mentioned in #set_mask# are set in the flags and all
Packit df99a1
	  bits mentioned in #clr_mask# are cleared in the flags, it sets all
Packit df99a1
	  bits from #set_mask1# in the flags, clears all flags from
Packit df99a1
	  #clr_mask1# in the flags and returns #TRUE#. Otherwise returns
Packit df99a1
	  #FALSE#. */
Packit df99a1
   bool	test_and_modify(long set_mask, long clr_mask,
Packit df99a1
			long set_mask1, long clr_mask1);
Packit df99a1
Packit df99a1
      /** Waits until all bits mentioned in #set_mask# are set in the flags
Packit df99a1
	  and all bits mentioned in #clr_flags# are cleared in the flags.
Packit df99a1
	  After that it sets bits from #set_mask1# and clears bits from
Packit df99a1
	  #clr_mask1# in the flags. */
Packit df99a1
   void	wait_and_modify(long set_mask, long clr_mask,
Packit df99a1
			long set_mask1, long clr_mask1);
Packit df99a1
Packit df99a1
      /** Waits until all bits set in #set_mask# are set in the flags and
Packit df99a1
	  all bits mentioned in #clr_mask# are cleared in the flags. */
Packit df99a1
   void	wait_for_flags(long set_mask, long clr_mask=0) const;
Packit df99a1
Packit df99a1
      /** Modifies the flags by setting all bits mentioned in #set_mask#
Packit df99a1
	  and clearing all bits mentioned in #clr_mask#. If the flags have
Packit df99a1
	  actually been modified, a broadcast will be sent. */
Packit df99a1
   void	modify(long set_mask, long clr_mask);
Packit df99a1
};
Packit df99a1
Packit df99a1
inline
Packit df99a1
GSafeFlags::GSafeFlags(long xflags) 
Packit df99a1
  : flags(xflags) 
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
inline void
Packit df99a1
GSafeFlags::wait_for_flags(long set_mask, long clr_mask) const
Packit df99a1
{
Packit df99a1
   ((GSafeFlags *) this)->wait_and_modify(set_mask, clr_mask, 0, 0);
Packit df99a1
}
Packit df99a1
Packit df99a1
inline void
Packit df99a1
GSafeFlags::modify(long set_mask, long clr_mask)
Packit df99a1
{
Packit df99a1
   test_and_modify(0, 0, set_mask, clr_mask);
Packit df99a1
}
Packit df99a1
Packit df99a1
inline GSafeFlags &
Packit df99a1
GSafeFlags::operator|=(long mask)
Packit df99a1
{
Packit df99a1
   test_and_modify(0, 0, mask, 0);
Packit df99a1
   return *this;
Packit df99a1
}
Packit df99a1
Packit df99a1
inline GSafeFlags &
Packit df99a1
GSafeFlags::operator&=(long mask)
Packit df99a1
{
Packit df99a1
   test_and_modify(0, 0, 0, ~mask);
Packit df99a1
   return *this;
Packit df99a1
}
Packit df99a1
Packit df99a1
//@}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// COMPATIBILITY CLASSES
Packit df99a1
Packit df99a1
Packit df99a1
// -- these classes are no longer documented.
Packit df99a1
Packit df99a1
class GCriticalSection : protected GMonitor 
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
  void lock() 
Packit df99a1
    { GMonitor::enter(); };
Packit df99a1
  void unlock() 
Packit df99a1
    { GMonitor::leave(); };
Packit df99a1
};
Packit df99a1
Packit df99a1
class GEvent : protected GMonitor 
Packit df99a1
{
Packit df99a1
private:
Packit df99a1
  int status;
Packit df99a1
public:
Packit df99a1
  GEvent() 
Packit df99a1
    : status(0) { };
Packit df99a1
  void set() 
Packit df99a1
    { if (!status) { enter(); status=1; signal(); leave(); } };
Packit df99a1
  void wait() 
Packit df99a1
    { enter(); if (!status) GMonitor::wait(); status=0; leave(); };
Packit df99a1
  void wait(int timeout) 
Packit df99a1
    { enter(); if (!status) GMonitor::wait(timeout); status=0; leave(); };
Packit df99a1
};
Packit df99a1
Packit df99a1
class GCriticalSectionLock
Packit df99a1
{
Packit df99a1
private:
Packit df99a1
  GCriticalSection *gsec;
Packit df99a1
public:
Packit df99a1
  GCriticalSectionLock(GCriticalSection *gsec) : gsec(gsec) 
Packit df99a1
    { if (gsec) gsec->lock(); };
Packit df99a1
  ~GCriticalSectionLock() 
Packit df99a1
    { if (gsec) gsec->unlock(); };
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
}
Packit df99a1
# ifndef NOT_USING_DJVU_NAMESPACE
Packit df99a1
using namespace DJVU;
Packit df99a1
# endif
Packit df99a1
#endif
Packit df99a1
#endif //_GTHREADS_H_
Packit df99a1