[Gc] Re: [gclist] boehm-gc and the STL

Palash palash_singha_roy at yahoo.co.in
Tue Jul 18 07:47:19 PDT 2006


Boehm, Hans <hans_boehm at ...> writes:

> 
> [ Copied to gc at ..., which may be more appropriate for this sort of
> detailed discussion.  For subscription/archive info see the bottom of
> http://www.hpl.hp.com/personal/Hans_Boehm/gc ]
> 
> Some more partial answers:
> 
> 1) Recent versions of the GC distribution include a file gc_allocator.h.  
This defines two
> standard-conforming allocator templates.  One allocates collectable memory; 
the other allocates
> uncollectable but traced memory.  The second is intended for containers that 
are explicitly deallocated
> but point to collectable memory.  These should work with any reasonably 
standard-conforming
> implementation.  (The distribution also contains older versions that were 
designed to work with STL
> implementations derived from the SGI one.)  I'm not sure this code has been 
terribly well tested, but bug
> reports are welcome.  It does contains some optimizations for pointer-free 
data.
> 
> 2) I'm a bit surprised by the leakage problems.  This could happen if 
objects are deallocated explicitly but
> references to them are retained, or if the objects have a very high 
probability of containing false
> pointers.  It would be nice to track this down.  If this still occurs with 
the above allocator, and you have a
> small test program, I will be happy to take a look.
> 
> 3) Re: finalization cycles.  My preferred solution is generally to break 
objects needing cleanup into two
> pieces:  One piece (A) contains only pointers that actually need to be 
followed during cleanup.  The other
> (A') contains all other data and a reference to A.  Only A is actually 
enabled for cleanup.  (In simple cases
> A' may not be needed.)  Any remaining cycles between objects needing cleanup 
in this scheme are at least
> suggestive of a real logic error, in that there is no acceptable order in 
which the finalizers/cleanup
> actions can safely be run.  (In theory they could be resolved by further 
splitting of objects, but I don't
> think I've ever seen a case where that was necessary.)
> 
> If this turns out to be too expensive, the "disappearing link" facility in 
the collector can be used to do
> basically the same thing without adding the second object.
> 
> This has the advantage over the unordered/Java solution in that ordering 
dependencies between
> finalizers are usually handled correctly automagically.  And when things do 
go wrong (due to an
> unexpected cycle), you got a leak with a collector warning that you 
generated a finalization cycle,
> instead of a crash (when you forgot to deal explicitly with an ordering 
constraint in the unordered case).
> 
> Hans
> 
> > -----Original Message-----
> > From: Marcin.Skubiszewski at ... 
> > [mailto:Marcin.Skubiszewski at ...]
> > Sent: Wednesday, May 07, 2003 1:24 AM
> > To: gclist at ...
> > Subject: Re: [gclist] boehm-gc and the STL
> > 
> > 
> > On Tue, May 06, 2003 at 12:19:01PM -0400, David Jones wrote:
> > > I have just started playing with the Boehm collector under 
> > C++ and have run
> > > into a problem with STL objects.
> > 
> > I have been using STL with Boehm GC for more than a year now. This is
> > difficult and delicate.
> > 
> > Pointers found in malloc'd objects are ignored by the
> > GC. An stl::set that points to collectable objects needs to be
> > collectable, not malloc'd.
> > 
> > > 1. Write an allocator for STL objects that uses GC_malloc.  
> > Drawback: since
> > >    C++ doesn't have "template typedefs", you need to write 
> > an ugly template
> > >    instantiation each time you want to use a container, e.g.:
> > 
> > This is what I do. And it is ugly, indeed, but the ugliness is not
> > where you think.
> > 
> > This is my allocator:
> > 
> > class gcalloc : public __malloc_alloc_template<0> {
> >  public:
> >   static void* allocate(size_t __n) {
> >     void* __result = GC_malloc(__n);
> >     if (__result == 0) {
> >       throw std::bad_alloc();
> >     }
> >     //cerr << "did GC_malloc" << endl;
> >     return __result;
> >   }
> > 
> >   static void deallocate(void* __p, size_t __n)
> >   {
> >     //cerr << "TRYING free" << endl;
> >   }
> > 
> >   static void* reallocate(void* __p, size_t /* old_sz */, 
> > size_t __new_sz)
> >   {
> >     void* __result = GC_realloc(__p, __new_sz);
> >     if (0 == __result) {
> >       throw std::bad_alloc();
> >     }
> >     //cerr << "did *** GC_realloc" << endl;
> >     return __result;
> >   }
> > };
> > 
> > template <class _Tp>
> > struct _Alloc_traits<_Tp, gcalloc >
> > {
> >   static const bool _S_instanceless = true;
> > #if ((__GNUG__==3) && (__GNUC_MINOR__ < 2))
> >   typedef simple_alloc<_Tp, gcalloc> _Alloc_type;
> > #else
> >   typedef __simple_alloc<_Tp, gcalloc> _Alloc_type;
> > #endif
> >   typedef __allocator<_Tp, gcalloc> allocator_type;
> > };
> > 
> > 
> > 
> > Some examples of use of this allocator:
> > 
> > std::list <WLocker *, gcalloc> l; /* local variable declaration */
> > 
> > struct AlarmDescList : std::list<AlarmDesc, gcalloc>, gc {};
> > 
> > typedef std::basic_string<char, std::char_traits<char>,
> > 			  std::__allocator<char, gcalloc> > 
> > AuxMTKstring;
> > struct MTKstring : AuxMTKstring, gc {
> >   MTKstring(const char *a) : AuxMTKstring(a) {}
> >   MTKstring() {}
> > }; /* Here, MTKstring is a fully collectable string */
> > 
> > 
> > 
> > Now, where is the ugliness ?
> > 
> > Small ugliness: I do not understand why certain STL templates need the
> > parameter gcalloc, and others (like basic_string) need
> > std::__allocator<char, gcalloc> instead. I always try out both of
> > them.
> > 
> > Middle-sized ugliness: my definition of gcalloc depends on the
> > internals of STL. Therefore, I needed to rewrite it while
> > migrating from gcc 2.95.3 to gcc 3.0 (no rewrite for migrating to gcc
> > 3.2.2, which I use now).
> > 
> > Big ugliness: the whole thing only half-works: with STL, the GC seems
> > to leave behind lots of leaks.
> > 
> > I got very big, ever increasing leaks with collectable std::set and
> > basic_string. I do not really know what caused these leaks.
> > 
> > For std::set, I took the hypothesis that internal nodes of the tree
> > somehow retain pointers to dead nodes (I don't know why, I did not
> > analyze the operation of std::set). As a result, if one dead node
> > leaks (is falsely considered by the GC as being alive), many other
> > nodes, that are (recursively) referenced by it, will leak along with
> > it.
> > 
> > To fix this, I wrote a version of the gcalloc allocator that clears
> > objects that are explicitly deleted. This way, whenever some dead
> > (explicitly deleted) node leaks, it will contain no pointers, and will
> > not cause other nodes to leak. This solved the problem with std::set
> > and other similar structures.
> > 
> > Here comes the modified version of gcalloc:
> > 
> > class eraseGcalloc : public gcalloc {
> >  public:
> >   static void deallocate(void* __p, size_t __n)
> >   {
> >     bzero (__p, __n);
> >     //cerr << "TRYING free" << endl;
> >   }
> > };
> > 
> > _Alloc_traits<_Tp, eraseGcalloc > is defined similarly to
> > _Alloc_traits<_Tp, gcalloc >.
> > 
> > Here is an example of use of eraseGcalloc:
> > 
> > typedef multiset < Measure *, OrderingByDesiredDate, eraseGcalloc >
> > MultisetSortedByDesiredDate;
> > 
> > Concerning basic_string, I chose a much simpler solution: I quit using
> > the collectable version. This is possible because a basic_string never
> > points to outside objects.
> > 
> > The use of malloc'd strings induces another problem: we need to
> > somehow trigger the destruction of these strings. I use the following
> > solution: every string is embedded in a collectable object, and the
> > collectable object is set up so that its collection will trigger the
> > destructor; recursively, the destructor will cause the embedded string
> > to be properly and completely freed.
> > 
> > To cause the destructor to be called, it would suffice to have the
> > object inherit from gc_cleanup. But this is not quite the solution I
> > retain, because gc_cleanup has a problem with cycles of garbage: if A
> > and B are garbage objects, and A points to B, and B points to A, then
> > A and B will never be collected. This has to do with having a
> > perfectly clean semantics of finalization/destruction (ask Hans Boehm,
> > not me, about this issue).
> > 
> > Instead of using gc_cleanup, I declare gc_destruct, which is very
> > similar to gc_cleanup, but ignores cycles: a dead object will be
> > destructed ASAP, regardless of who references it and/or who is
> > referenced by it. Unlike gc_cleanup, gc_destruct does not guarantee
> > correct operation of fancy destructors, but is perfectly OK with
> > simple destructors that only destroy things.
> > 
> > gc_destruct is defined as follows:
> > 
> > class gc_destruct: virtual public gc {
> >  public:
> >   inline gc_destruct();
> >   inline virtual ~gc_destruct();
> >  private:
> >   inline static void GC_cdecl cleanup( void* obj, void* clientData );
> > };
> > /*
> >   Instances of classes derived from "gc_destruct" will be allocated
> >   in the collected heap by default.  When the collector discovers an
> >   inaccessible object derived from "gc_destruct" or containing a
> >   member derived from "gc_destruct", its destructors will be
> >   invoked. */
> > 
> > inline gc_destruct::~gc_destruct() {
> >   GC_REGISTER_FINALIZER_IGNORE_SELF(GC_base(this), 0, 0, 0, 0 );
> > }
> > 
> > inline void gc_destruct::cleanup( void* obj, void* displ ) {
> >   ((gc_destruct*) ((char*) obj + (ptrdiff_t) displ))->~gc_destruct();
> > }
> > 
> > inline gc_destruct::gc_destruct() {
> >   GC_finalization_proc oldProc;
> >   void* oldData;
> >   void* base = GC_base( (void *) this );
> >   if (0 != base)  {
> >     // Don't call the debug version, since this is a real 
> > base address.
> >     GC_register_finalizer_no_order
> >       (base, (GC_finalization_proc)cleanup,
> >        (void*) ((char*) this - (char*) base), 
> >        &oldProc, &oldData );
> >     if (0 != oldProc) {
> >       GC_register_finalizer_no_order(base, oldProc, oldData, 0, 0 );
> >     }
> >   }
> > }
> > 
> > 
> > Examples of use of gc_destruct (this is really trivial):
> > 
> > struct PathList: std::list <Pathname *, gcalloc>, gc_destruct {};
> > 
> > class WebAdministrable : public gc_destruct {
> > /* ... */
> > };
> > 
> > 
> > Good luck !
> > 
> > 					Marcin.
> > 
> > 
> > ----- End forwarded message -----
> > 
> 
> 


If you have any idea , please send to us :::::::::

The following error we are getting at the time of build :::::::::::::
--------------------------------------------------------------------------

/home/sagara/voy2_lca_cmp_old_17_07/ws/include/department.h:220: error: 
`__malloc_alloc_template' is not a member of `std'
/home/sagara/voy2_lca_cmp_old_17_07/ws/include/department.h:220: error: 
`__malloc_alloc_template' is not a member of `std'
/home/sagara/voy2_lca_cmp_old_17_07/ws/include/department.h:220: error: 
template argument 2 is invalid
/home/sagara/voy2_lca_cmp_old_17_07/ws/include/department.h:220: error: 
expected `,' or `...' before '>' token
/home/sagara/voy2_lca_cmp_old_17_07/ws/include/department.h:221: error: ISO 
C++ forbids declaration of `parameter' with no type
/home/sagara/voy2_lca_cmp_old_17_07/ws/include/department.h:352: error: 
`__malloc_alloc_template' is not a member of `std'
/home/sagara/voy2_lca_cmp_old_17_07/ws/include/department.h:352: error: 
`__malloc_alloc_template' is not a member of `std'
/home/sagara/voy2_lca_cmp_old_17_07/ws/include/department.h:352: error: 
template argument 2 is invalid
/home/sagara/voy2_lca_cmp_old_17_07/ws/include/department.h:352: error: 
expected unqualified-id before '>' token


The following is the program :::::::::::
----------------------------------------


/*
 * Copyright (C) 2004-2005 KYOCERAMITA CORPORATION. All rights reserved.
 * KYOCERAMITA PROPRIETARY/CONFIDENTIAL
 * 
 * department.h -
 * 
 */

#ifndef _kyoceramita_falcon3_entity_department_department_h_
#define _kyoceramita_falcon3_entity_department_department_h_


/*
 *  include file.
 */
#include <iostream>
#include <vector>
#ifdef DEBUG_DPT
#include <pthread.h>

#include "act_account.h"
#include "dptaccount.h"
#else
#include "emwgncid.h"
#include "concurrent.h"
#include "act_account.h"
#include "dptaccount.h"
#endif

#include "emwosw.h"

/*
 * class prototype.
 */

class DptCoreAttrs;

/*
 *  common macro difinition.
 */

#define DPT_OTHER_DPT_ID  1001

#define DPT_NAME_LEN       192
#define DPT_FURI_LEN       128
#define DPT_CODE_LEN         8

#define ERRORCODE_PACKAGE_ENTITY_DPT       0x010000
#define ERRORCODE_COMPONENT_DPT              0x0900

#define DPT_LIMIT_MIN               1
#define DPT_LIMIT_MAX          999999
#define DPT_LIMIT_TIME_MAX    3599999


namespace kyoceramita {

/*
 * class prototype.
 */

class Department;
class DepartmentIterator;
class DptCoreAttrs;
struct SearchFilter;
struct DepartmentAttrs;

/*
 *  common constant.
 */


/* error code definition. */
enum {
  DPT_OK                      = 0x00,
  ERRORCODE_DPT_OUT_OF_MEMORY = 0x01,
  ERRORCODE_DPT_INVALID_DPTID,
  ERRORCODE_DPT_INVALID_DPTCODE,
  ERRORCODE_DPT_INVALID_COUNTERTYPE,
  ERRORCODE_DPT_PARAMETER,
  ERRORCODE_DPT_EXCEEDED_MAX_NUMBER,
  ERRORCODE_DPT_EXCEEDED_MAX_COUNT,
  ERRORCODE_DPT_STOP_EMMEDIATELY,
  ERRORCODE_DPT_WARNING_MAX_COUNT,
  ERRORCODE_DPT_ALREADY_EXIST,
  ERRORCODE_DPT_NOT_FOUND,
  ERRORCODE_DPT_NOT_AUTHORIZED,
  ERRORCODE_DPT_NOT_INITIALIZED,
  ERRORCODE_DPT_INTERNAL,
  ERRORCODE_BASE = ( ERRORCODE_PACKAGE_ENTITY_DPT + ERRORCODE_COMPONENT_DPT )
};

#ifdef DEBUG_DPT
#define   GEN_CID_DPT   0x69
#endif

/* error code definition. */
enum {
  ENT_DPT_OK                      = 0,
  ENT_DPT_ERR                     = (GEN_CID_DPT << 16),
  ENT_DPT_ERR_OUT_OF_MEMORY       = ( ENT_DPT_ERR | 0x01 ),
  ENT_DPT_ERR_INVALID_DPTID       = ( ENT_DPT_ERR | 0x02 ),
  ENT_DPT_ERR_INVALID_DPTCODE     = ( ENT_DPT_ERR | 0x03 ),
  ENT_DPT_ERR_INVALID_COUNTERTYPE = ( ENT_DPT_ERR | 0x04 ),
  ENT_DPT_ERR_PARAMETER           = ( ENT_DPT_ERR | 0x05 ),
  ENT_DPT_ERR_EXCEEDED_MAX_NUMBER = ( ENT_DPT_ERR | 0x06 ),
  ENT_DPT_ERR_EXCEEDED_MAX_COUNT  = ( ENT_DPT_ERR | 0x07 ),
  ENT_DPT_ERR_STOP_EMMEDIATELY    = ( ENT_DPT_ERR | 0x08 ),
  ENT_DPT_ERR_WARNING_MAX_COUNT   = ( ENT_DPT_ERR | 0x09 ),
  ENT_DPT_ERR_ALREADY_EXIST       = ( ENT_DPT_ERR | 0x10 ),
  ENT_DPT_ERR_NOT_FOUND           = ( ENT_DPT_ERR | 0x11 ),
  ENT_DPT_ERR_NOT_AUTHORIZED      = ( ENT_DPT_ERR | 0x12 ),
  ENT_DPT_ERR_NOT_INITIALIZED     = ( ENT_DPT_ERR | 0x13 ),
  ENT_DPT_ERR_INTERNAL            = ( ENT_DPT_ERR | 0x14 )
};

/*
 * Counter type definition.
 */
enum {
  DPT_COUNTER_COPY = 1,
  DPT_COUNTER_PRINT,
  DPT_COUNTER_COPY_SCAN,
  DPT_COUNTER_OTHER_SCAN,
  DPT_COUNTER_FAX_RECEIVE,
  DPT_COUNTER_FAX_SEND,
  DPT_COUNTER_FAX_SEND_TIME,
  DPT_COUNTER_SIZE1,
  DPT_COUNTER_SIZE2,
  DPT_COUNTER_SIZE3,
  DPT_COUNTER_SIZE4,
  DPT_COUNTER_SIZE5,
  DPT_COUNTER_SIZEOTHER,
  DPT_COUNTER_DUPLEX,
  DPT_COUNTER_SIMPLEX
};

/*
 * Parameter value difinition.
 * for Department::setcopylimit
 *     Department::setprintlimit
 *     Department::setotherscanlimit
 *     Department::setfaxsendlimit
 */
enum {
  DPT_COUNTER_LIMIT_OFF = 0,
  DPT_COUNTER_LIMIT_ON,
  DPT_COUNTER_DISABLE
};

/*
 * Structue attribute difinition.
 * for SerchFilter
 */
enum {
  DPT_ATTR_NAME  = 1,   /* name search */
  DPT_ATTR_FURIGANA,    /* furigana search */
  DPT_ATTR_DPTCODE      /* code search */
};

enum {
  DPT_COND_PRE = 1,     /* condition pre */
  // DPT_COND_INCLUDE,  /* condition include */
  // DPT_COND_POST      /* condition post */
};

/*
 * Parameter value difinition.
 * for DepartmentIterator::sort
 *
 * 1st parameter
 */
enum {
  DPT_TYPE_ID = 1,      /* sort type id */
  DPT_TYPE_NAME,        /* sort type name */
  DPT_TYPE_FURIGANA,    /* sort type furigana */
  DPT_TYPE_DPTCODE      /* sort type code */
};
/*
 * 2nd parameter
 */
enum {
  DPT_ORDER_TOP = 1,    /* top order */
  DPT_ORDER_BOTTOM      /* bottom order */
};


/* 
 * backup task
 */
void dptbackuptask( void );

/*************************************************************
 * Name:        DepartmentManager
 * Stereotype:  singleton
 * Description: To edit department infomation
 *************************************************************/

class DepartmentManager {
  int count_;
  int * upflag_;
  TIMID backup_time_id_;
#ifdef DEBUG_DPT
  pthread_mutex_t editmtx_;
  pthread_mutex_t rtrvmtx_;
  pthread_mutex_t itrtmtx_;
#else
  kyoceramita::Mutex editmtx_;
  kyoceramita::Mutex rtrvmtx_;
  kyoceramita::Mutex itrtmtx_;
#endif
  DepartmentManager();
  //  DepartmentManager( const DepartmentManager& );
  //  DepartmentManager& operator=( const DepartmentManager& );
  void upcount( int id );
  void upcountall( void );
  int backup( void );
  int backupcount( std::vector<DptCoreAttrs, std::__malloc_alloc_template<0> 
>& list,
		   int total );
  int restoredata( void );
  int getdepartment( int id, Department& dpt );
  int setdepartment( int id, DepartmentAttrs& attrs );
  int notifyremove( void );

 public:
  virtual ~DepartmentManager();
  static DepartmentManager& instance();
  int init();
  int create( const ACT_Certificate& cert,
	      const char * dptcode,
	      const char * name = "", const char * furigana = "" );
  int remove( const ACT_Certificate& cert,
	      int id );
  int update( const ACT_Certificate& cert,
	      int id, const Department& department );
  int update( const ACT_Certificate& cert,
	      const Department& department );
  int retrieve( const ACT_Certificate& cert,
		int id, Department& department );
  int getiterator( const ACT_Certificate& cert,
		   const SearchFilter * filter,
		   DepartmentIterator& itr);
  int getid( const char * dptcode, int * id );
  int login( const char* dptcode, 
	     ACT_Certificate& cert );
  int logout( ACT_Certificate& cert );
  int child_login( const ACT_Certificate& input_cert, ACT_Certificate& cert );
  int child_logout( ACT_Certificate& cert );
  int resetcounter( const ACT_Certificate& cert, int id );
  int resetallcounter( const ACT_Certificate& cert );
  int setcounter( const ACT_Certificate& cert, int id, int countertype,
		  int count );
  int countup( int id, int countertype, int count );
  int countup( int id, int countertype,
	       int papersize, int count );
  int remainpage( int id, int countertype, int * remain );
  int allclear( void );
  int getupdatecount( int * count );
  int restore( void );
  int gettotalcounter( const ACT_Certificate cert, DepartmentAttrs& attrs );

  //
  // following functions are for test. they will be deleted.
  //
  int create( const DPT_Certificate& cert,
	      const char * dptcode,
	      const char * name = "", const char * furigana = "" );
  int remove( const DPT_Certificate& cert,
	      int id );
  int update( const DPT_Certificate& cert,
	      int id, const Department& department );
  int update( const DPT_Certificate& cert,
	      const Department& department );
  int retrieve( const DPT_Certificate& cert,
		int id, Department& department );
  int getiterator( const DPT_Certificate& cert,
		   const SearchFilter * filter,
		   DepartmentIterator& itr);
  int login( const char* dptcode, 
	     DPT_Certificate& cert );
  int logout( DPT_Certificate& cert );
  int resetcounter( const DPT_Certificate& cert, int id );
  int resetallcounter( const DPT_Certificate& cert );
  int setcounter( const DPT_Certificate& cert, int id, int countertype,
		  int count );

  int backuptest( void );
  int setcountertest( int id );

  friend void dptbackuptask( void );

  //  friend class DepartmentIterator;
  //  friend class Department;
};
/* Name: DepartmentManager */


/*************************************************************
 * Name:        Department
 * Stereotype:  
 * Description: Department data class
 *************************************************************/

class Department {
  int         id_;
  std::string name_;
  std::string furigana_;
  std::string dptcode_;
  int         copylimit_;
  int         printlimit_;
  int         otherscanlimit_;
  int         faxsendlimit_;
  int         copymax_;
  int         printmax_;
  int         otherscanmax_;
  int         faxsendmax_;
 public:
  Department();
  virtual~Department();
  //  Department( const Department& );
  //  Department& operator=( const Department& );
  int setname( const char * name );
  int setfurigana( const char * furigana );
  int setdptcode( const char * dptcode );
  int setcopylimit( int limit );
  int setprintlimit( int limit );
  int setotherscanlimit( int limit );
  int setfaxsendlimit( int limit );
  int setcopymax( int max );
  int setprintmax( int max );
  int setotherscanmax( int max );
  int setfaxsendmax( int max );
  int getattrs( DepartmentAttrs& attrs ) const;
  friend class DepartmentManager;
  friend class DptDB2eAccesser;
};
/* Name: Department */


/*************************************************************
 * Name:        DepartmentIterator
 * Stereotype:  
 * Description: Department iterator class
 *************************************************************/

class DepartmentIterator {
  int           index_;
  int           length_;
  int           order_;
  std::vector<DptCoreAttrs, std::__malloc_alloc_template<0> > list_;
 public:
  //  DepartmentIterator( const DepartmentIterator& );
  //  DepartmentIterator& operator=( const DepartmentIterator& );
  DepartmentIterator();
  virtual ~DepartmentIterator();
  int get( Department& department );
  int getid( int * id );
  int getname( char * namebuf, int buflen );
  int getcode( char * dptbuf, int buflen );
  int getfuri( char * furibuf, int buflen );
  int begin();
  int prev();
  int next();
  int sort( int type, int order );
  int size( int * len );
  int jump( int type, const std::string strkey );
  int release();
  friend class DepartmentManager;
};
/* Name: DepartmentIterator */


/*************************************************************
 * Name:        DepartmentAttrs
 * Stereotype:  
 * Description: Department attributes structure
 *************************************************************/

struct DepartmentAttrs {
  int id;
  char name[DPT_NAME_LEN + 1];
  char furigana[DPT_FURI_LEN + 1];
  char dptcode[DPT_CODE_LEN + 1];
  int copylimit;
  int printlimit;
  int otherscanlimit;
  int faxsendlimit;
  int copymax;
  int printmax;
  int otherscanmax;
  int faxsendmax;
  int copycount;
  int printcount;
  int copyscancount;
  int otherscancount;
  int faxreceivecount;
  int faxsendcount;
  int faxsendtime;
  int size1count;
  int size2count;
  int size3count;
  int size4count;
  int size5count;
  int sizeothercount;
  int duplexcount;
  int simplexcount;
};
/* Name: DepartmentAttrs */


/*************************************************************
 * Name:        SearchFilter
 * Stereotype:  
 * Description: SearchFilter to get iterator
 *************************************************************/

struct SearchFilter {
  int    type;
  int    condition;
  char   value[DPT_NAME_LEN + 1];
};
/* Name: SearchFilter */


/*************************************************************
 * Name:        DptCoreAttr
 * Stereotype:  
 * Description: Department search result data class
 *************************************************************/
class DptCoreAttrs {
 public:
  int id;
  std::string name;
  std::string furigana;
  std::string dptcode;
};


} // namespace kyoceramita


#endif // dpt department h


/* end of file */










More information about the Gc mailing list