# object.h

Go to the documentation of this file.

    00001 /*
    00002  * object.h
    00003  *
    00004  * Mother of all ancestor classes.
    00005  *
    00006  * Portable Tools Library
    00007  *
    00008  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
    00009  *
    00010  * The contents of this file are subject to the Mozilla Public License
    00011  * Version 1.0 (the "License"); you may not use this file except in
    00012  * compliance with the License. You may obtain a copy of the License at
    00013  * http://www.mozilla.org/MPL/
    00014  *
    00015  * Software distributed under the License is distributed on an "AS IS"
    00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
    00017  * the License for the specific language governing rights and limitations
    00018  * under the License.
    00019  *
    00020  * The Original Code is Portable Windows Library.
    00021  *
    00022  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
    00023  *
    00024  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
    00025  * All Rights Reserved.
    00026  *
    00027  * Contributor(s): ______________________________________.
    00028  *
    00029  * $Revision: 28201 $
    00030  * $Author: rjongbloed $
    00031  * $Date: 2012-08-14 21:30:31 -0500 (Tue, 14 Aug 2012) $
    00032  */
    00033
    00034 #ifndef PTLIB_OBJECT_H
    00035 #define PTLIB_OBJECT_H
    00036
    00037 #ifdef P_USE_PRAGMA
    00038 #pragma interface
    00039 #endif
    00040
    00041 #if defined(_WIN32) || defined(_WIN32_WCE)
    00042 #include "msos/ptlib/contain.h"
    00043 #else
    00044 #include "unix/ptlib/contain.h"
    00045 #endif
    00046
    00047 #if defined(P_VXWORKS)
    00048 #include <private/stdiop.h>
    00049 #endif
    00050
    00051 #include <stdio.h>
    00052 #include <stdarg.h>
    00053 #include <stdlib.h>
    00054
    00055 #include <string.h>
    00056
    00057 #include <string>
    00058 #include <iomanip>
    00059 #include <iostream>
    00060 #include <sstream>
    00061 #include <vector>
    00062 #include <list>
    00063 #include <map>
    00064 #include <algorithm>
    00065
    00066
    00067 #define P_REMOVE_VIRTUAL_INTERNAL_BASE(fn) __inline virtual struct ptlib_virtual_function_changed_or_removed ****** fn { return 0; }
    00068
    00069 #if defined(_MSC_VER)
    00070   #if _MSC_VER < 1310
    00071     #define P_DEPRECATED
    00072     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
    00073   #elif _MSC_VER < 1400
    00074     #define P_DEPRECATED __declspec(deprecated)
    00075     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated) type fn body
    00076   #else
    00077     #define P_DEPRECATED __declspec(deprecated)
    00078     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated("Virtual function signature changed or function deprecated")) type fn body
    00079   #endif
    00080 #elif defined(__GNUC__)
    00081   #if __GNUC__ < 4
    00082     #define P_DEPRECATED
    00083     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
    00084   #else
    00085     #define P_DEPRECATED __attribute__((deprecated))
    00086     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __attribute__((warn_unused_result)) __attribute__((deprecated)) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
    00087   #endif
    00088 #else
    00089     #define P_DEPRECATED
    00090     #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
    00091 #endif
    00092
    00093 #define P_REMOVE_VIRTUAL_VOID(fn)       P_REMOVE_VIRTUAL_INTERNAL(void, fn, {})
    00094 #define P_REMOVE_VIRTUAL(type, fn, ret) P_REMOVE_VIRTUAL_INTERNAL(type, fn, { return ret; })
    00095
    00096
    00097 // P_USE_INTEGER_BOOL is the default and gives the old behaviour (it
    00098 // is also used for C translation units).
    00099 // without P_USE_INTEGER_BOOL, the ANSI C++ bool is used.
    00100
    00101 #if defined(P_USE_INTEGER_BOOL) || !defined(__cplusplus)
    00102    typedef BOOL PBoolean;
    00103 #  define PTrue TRUE
    00104 #  define PFalse FALSE
    00105 #else
    00106    typedef bool PBoolean;
    00107 #  define PTrue true
    00108 #  define PFalse false
    00109 #endif
    00110
    00111
    00113 // Disable inlines when debugging for faster compiles (the compiler doesn't
    00114 // actually inline the function with debug on any way).
    00115
    00116 #ifndef P_USE_INLINES
    00117 #ifdef _DEBUG
    00118 #define P_USE_INLINES 0
    00119 #else
    00120 #define P_USE_INLINES 0
    00121 #endif
    00122 #endif
    00123
    00124 #if P_USE_INLINES
    00125 #define PINLINE inline
    00126 #else
    00127 #define PINLINE
    00128 #endif
    00129
    00130
    00132 // Declare the debugging support
    00133
    00134 #ifndef P_USE_ASSERTS
    00135 #define P_USE_ASSERTS 1
    00136 #endif
    00137
    00138 #if !P_USE_ASSERTS
    00139
    00140 #define PAssert(b, m) (b)
    00141 #define PAssert2(b, c, m) (b)
    00142 #define PAssertOS(b) (b)
    00143 #define PAssertNULL(p) (p)
    00144 #define PAssertAlways(m) {}
    00145 #define PAssertAlways2(c, m) {}
    00146
    00147 #else // P_USE_ASSERTS
    00148
    00150 enum PStandardAssertMessage {
    00151   PLogicError,
    00152   POutOfMemory,
    00153   PNullPointerReference,
    00154   PInvalidCast,
    00155   PInvalidArrayIndex,
    00156   PInvalidArrayElement,
    00157   PStackEmpty,
    00158   PUnimplementedFunction,
    00159   PInvalidParameter,
    00160   POperatingSystemError,
    00161   PChannelNotOpen,
    00162   PUnsupportedFeature,
    00163   PInvalidWindow,
    00164   PMaxStandardAssertMessage
    00165 };
    00166
    00167 #define __CLASS__ NULL
    00168
    00169 void PAssertFunc(const char * file, int line, const char * className, PStandardAssertMessage msg);
    00170 void PAssertFunc(const char * file, int line, const char * className, const char * msg);
    00171 void PAssertFunc(const char * full_msg);
    00172
    00173 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, PStandardAssertMessage msg)
    00174 {
    00175   if (!b)
    00176     PAssertFunc(file, line, className, msg);
    00177   return b;
    00178 }
    00179 inline bool PAssertFuncInline(bool b, const char * file, int line, const char * className, const char * msg)
    00180 {
    00181   if (!b)
    00182     PAssertFunc(file, line, className, msg);
    00183   return b;
    00184 }
    00185
    00192 #define PAssert(b, msg) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,(msg))
    00193
    00201 #define PAssert2(b, cls, msg) PAssertFuncInline((b), __FILE__,__LINE__,(cls),(msg))
    00202
    00209 #define PAssertOS(b) PAssertFuncInline((b), __FILE__,__LINE__,__CLASS__,POperatingSystemError)
    00210
    00220 #define PAssertNULL(ptr) (((ptr)!=NULL)?(ptr): \
    00221                      (PAssertFunc(__FILE__,__LINE__, __CLASS__, PNullPointerReference),(ptr)))
    00222
    00229 #define PAssertAlways(msg) PAssertFunc(__FILE__,__LINE__,__CLASS__,(msg))
    00230
    00237 #define PAssertAlways2(cls, msg) PAssertFunc(__FILE__,__LINE__,(cls),(msg))
    00238
    00239 #endif // P_USE_ASSERTS
    00240
    00241
    00246 ostream & PGetErrorStream();
    00247
    00251 void PSetErrorStream(ostream * strm  );
    00252
    00267 #define PError (PGetErrorStream())
    00268
    00269
    00270
    00272 // Debug and tracing
    00273
    00274 #ifndef PTRACING
    00275 #define PTRACING 1
    00276 #endif
    00277
    00278 #if PTRACING
    00279
    00292 class PTrace
    00293 {
    00294 public:
    00296   enum Options {
    00302     Blocks = 1,
    00304     DateAndTime = 2,
    00306     Timestamp = 4,
    00308     Thread = 8,
    00310     TraceLevel = 16,
    00312     FileAndLine = 32,
    00314     ThreadAddress = 64,
    00316     AppendToFile = 128,
    00318     GMTTime = 256,
    00320     RotateDaily = 512,
    00322     RotateHourly = 1024,
    00324     RotateMinutely = 2048,
    00326     RotateLogMask = RotateDaily + RotateHourly + RotateMinutely,
    00330     SystemLogStream = 32768
    00331   };
    00332
    00333
    00347   static void Initialise(
    00348     unsigned level,
    00349     const char * filename = NULL,
    00350     unsigned options = Timestamp | Thread | Blocks
    00351   );
    00352
    00363   static void Initialise(
    00364     unsigned level,
    00365     const char * filename,
    00366     const char * rolloverPattern,
    00367     unsigned options = Timestamp | Thread | Blocks
    00368   );
    00369
    00376   static void SetOptions(
    00377     unsigned options
    00378   );
    00379
    00388   static void ClearOptions(
    00389     unsigned options
    00390   );
    00391
    00397   static unsigned GetOptions();
    00398
    00404   static void SetLevel(
    00405     unsigned level
    00406   );
    00407
    00413   static unsigned GetLevel();
    00414
    00419   static PBoolean CanTrace(
    00420     unsigned level
    00421   );
    00422
    00427   static void SetStream(
    00428     ostream * out
    00429   );
    00430
    00446   static ostream & Begin(
    00447     unsigned level,
    00448     const char * fileName,
    00449     int lineNum
    00450   );
    00451
    00469   static ostream & End(
    00470     ostream & strm
    00471   );
    00472
    00476   static void Cleanup();
    00477
    00483   class Block {
    00484     public:
    00486       Block(
    00487         const char * fileName,
    00488         int lineNum,
    00489         const char * traceName
    00491        );
    00492       Block(const Block & obj)
    00493         : file(obj.file), line(obj.line), name(obj.name) { }
    00495       ~Block();
    00496     private:
    00497       Block & operator=(const Block &)
    00498       { return *this; }
    00499       const char * file;
    00500       int          line;
    00501       const char * name;
    00502   };
    00503 };
    00504
    00505 /* Macro to conditionally declare a parameter to a function to avoid compiler
    00506    warning due that parameter only being used in a <code>PTRACE()</code> */
    00507 #define PTRACE_PARAM(param) param
    00508
    00515 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
    00516
    00520 #define PTRACE_LINE() \
    00521     if (PTrace::CanTrace(1)) \
    00522       PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End; \
    00523     else (void)0
    00524
    00530 #define PTRACE(level, args) \
    00531     if (PTrace::CanTrace(level)) \
    00532       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
    00533     else (void)0
    00534
    00542 #define PTRACE_IF(level, cond, args) \
    00543     if ((PTrace::CanTrace(level) && (cond))) \
    00544       PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End; \
    00545     else (void)0
    00546
    00547 #else // PTRACING
    00548
    00549 #define PTRACE_PARAM(param)
    00550 #define PTRACE_BLOCK(n)
    00551 #define PTRACE_LINE()
    00552 #define PTRACE(level, arg)
    00553 #define PTRACE_IF(level, cond, args)
    00554
    00555 #endif // PTRACING
    00556
    00557
    00558
    00559 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE))
    00560
    00561 #define PMEMORY_HEAP 1
    00562
    00569 class PMemoryHeap {
    00570   public:
    00572     PMemoryHeap();
    00573
    00574     // Clear up the memory checking subsystem, dumping memory leaks.
    00575     ~PMemoryHeap();
    00576
    00583     static void * Allocate(
    00584       size_t nSize,
    00585       const char * file,
    00586       int line,
    00587       const char * className
    00588     );
    00595     static void * Allocate(
    00596       size_t count,
    00597       size_t iSize,
    00598       const char * file,
    00599       int line
    00600     );
    00601
    00609     static void * Reallocate(
    00610       void * ptr,
    00611       size_t nSize,
    00612       const char * file,
    00613       int line
    00614     );
    00615
    00621     static void Deallocate(
    00622       void * ptr,
    00623       const char * className
    00624     );
    00625
    00628     enum Validation {
    00629       Ok, Bad, Trashed
    00630     };
    00638     static Validation Validate(
    00639       const void * ptr,
    00640       const char * className,
    00641       ostream * error
    00642     );
    00643
    00648     static PBoolean ValidateHeap(
    00649       ostream * error = NULL
    00650     );
    00651
    00657     static PBoolean SetIgnoreAllocations(
    00658       PBoolean ignore
    00659     );
    00660
    00664     static void DumpStatistics();
    00668     static void DumpStatistics(ostream & strm );
    00669
    00670 #if PMEMORY_CHECK
    00671     struct State {
    00672       DWORD allocationNumber;
    00673     };
    00674 #else
    00675         typedef _CrtMemState State;
    00676 #endif
    00677
    00678     /* Get memory state.
    00679       This returns a state that may be used to determine where to start dumping
    00680       objects from.
    00681      */
    00682     static void GetState(
    00683       State & state
    00684     );
    00685
    00693     static void DumpObjectsSince(
    00694       const State & when
    00695     );
    00696
    00702     static void DumpObjectsSince(
    00703       const State & when,
    00704       ostream & strm
    00705     );
    00706
    00712     static void SetAllocationBreakpoint(
    00713       DWORD point
    00714     );
    00715
    00716 #if PMEMORY_CHECK
    00717
    00718   protected:
    00719     void * InternalAllocate(
    00720       size_t nSize,           // Number of bytes to allocate.
    00721       const char * file,      // Source file name for allocating function.
    00722       int line,               // Source file line for allocating function.
    00723       const char * className  // Class name for allocating function.
    00724     );
    00725     Validation InternalValidate(
    00726       const void * ptr,       // Pointer to memory block to check
    00727       const char * className, // Class name it should be.
    00728       ostream * error         // Stream to receive error message (may be NULL)
    00729     );
    00730     void InternalDumpStatistics(ostream & strm);
    00731     void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
    00732
    00733     class Wrapper {
    00734       public:
    00735         Wrapper();
    00736         ~Wrapper();
    00737         PMemoryHeap * operator->() const { return instance; }
    00738       private:
    00739         PMemoryHeap * instance;
    00740     };
    00741     friend class Wrapper;
    00742
    00743     enum Flags {
    00744       NoLeakPrint = 1
    00745     };
    00746
    00747 #pragma pack(1)
    00748     struct Header {
    00749       enum {
    00750         // Assure that the Header struct is aligned to 8 byte boundary
    00751         NumGuardBytes = 16 - (sizeof(Header *) +
    00752                               sizeof(Header *) +
    00753                               sizeof(const char *) +
    00754                               sizeof(const char *) +
    00755                               sizeof(size_t) +
    00756                               sizeof(DWORD) +
    00757                               sizeof(WORD) +
    00758                               sizeof(BYTE)
    00759 #if P_PTHREADS
    00760                               + sizeof(pthread_t)
    00761 #endif
    00762                               )%8
    00763       };
    00764
    00765       Header     * prev;
    00766       Header     * next;
    00767       const char * className;
    00768       const char * fileName;
    00769       size_t       size;
    00770       DWORD        request;
    00771       WORD         line;
    00772       BYTE         flags;
    00773 #if P_PTHREADS
    00774       pthread_t    thread;
    00775 #endif
    00776       char         guard[NumGuardBytes];
    00777
    00778       static char GuardBytes[NumGuardBytes];
    00779     };
    00780 #pragma pack()
    00781
    00782     PBoolean isDestroyed;
    00783
    00784     Header * listHead;
    00785     Header * listTail;
    00786
    00787     static DWORD allocationBreakpoint;
    00788     DWORD allocationRequest;
    00789     DWORD firstRealObject;
    00790     BYTE  flags;
    00791
    00792     char  allocFillChar;
    00793     char  freeFillChar;
    00794
    00795     DWORD currentMemoryUsage;
    00796     DWORD peakMemoryUsage;
    00797     DWORD currentObjects;
    00798     DWORD peakObjects;
    00799     DWORD totalObjects;
    00800
    00801     ostream * leakDumpStream;
    00802
    00803 #if defined(_WIN32)
    00804     CRITICAL_SECTION mutex;
    00805 #elif defined(P_PTHREADS)
    00806     pthread_mutex_t mutex;
    00807 #elif defined(P_VXWORKS)
    00808     void * mutex;
    00809 #endif
    00810
    00811 #else
    00812
    00813 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
    00814     _CrtMemState initialState;
    00815
    00816 #endif // PMEMORY_CHECK
    00817 };
    00818
    00819
    00824 inline void * runtime_malloc(size_t bytes  ) { return malloc(bytes); }
    00825
    00830 inline void runtime_free(void * ptr  ) { free(ptr); }
    00831
    00832
    00839 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
    00840
    00847 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
    00848
    00855 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
    00856
    00857
    00864 #define free(p) PMemoryHeap::Deallocate(p, NULL)
    00865
    00866
    00873 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
    00874
    00875
    00890 #define PNEW  new (__FILE__, __LINE__)
    00891
    00892 #if !defined(_MSC_VER) || _MSC_VER<1200
    00893 #define PSPECIAL_DELETE_FUNCTION
    00894 #else
    00895 #define PSPECIAL_DELETE_FUNCTION \
    00896     void operator delete(void * ptr, const char *, int) \
    00897       { PMemoryHeap::Deallocate(ptr, Class()); } \
    00898     void operator delete[](void * ptr, const char *, int) \
    00899       { PMemoryHeap::Deallocate(ptr, Class()); }
    00900 #endif
    00901
    00902 #define PNEW_AND_DELETE_FUNCTIONS \
    00903     void * operator new(size_t nSize, const char * file, int line) \
    00904       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
    00905     void * operator new(size_t nSize) \
    00906       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
    00907     void operator delete(void * ptr) \
    00908       { PMemoryHeap::Deallocate(ptr, Class()); } \
    00909     void * operator new(size_t, void * placement) \
    00910       { return placement; } \
    00911     void operator delete(void *, void *) \
    00912       { } \
    00913     void * operator new[](size_t nSize, const char * file, int line) \
    00914       { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
    00915     void * operator new[](size_t nSize) \
    00916       { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
    00917     void operator delete[](void * ptr) \
    00918       { PMemoryHeap::Deallocate(ptr, Class()); } \
    00919     PSPECIAL_DELETE_FUNCTION
    00920
    00921
    00922 inline void * operator new(size_t nSize, const char * file, int line)
    00923   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
    00924
    00925 inline void * operator new[](size_t nSize, const char * file, int line)
    00926   { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
    00927
    00928 #ifndef __GNUC__
    00929 void * operator new(size_t nSize);
    00930 void * operator new[](size_t nSize);
    00931
    00932 void operator delete(void * ptr);
    00933 void operator delete[](void * ptr);
    00934
    00935 #if defined(_MSC_VER) && _MSC_VER>=1200
    00936 inline void operator delete(void * ptr, const char *, int)
    00937   { PMemoryHeap::Deallocate(ptr, NULL); }
    00938
    00939 inline void operator delete[](void * ptr, const char *, int)
    00940   { PMemoryHeap::Deallocate(ptr, NULL); }
    00941 #endif
    00942 #endif
    00943
    00944
    00945 class PMemoryHeapIgnoreAllocationsForScope {
    00946 public:
    00947   PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(true)) { }
    00948   ~PMemoryHeapIgnoreAllocationsForScope() { PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations); }
    00949 private:
    00950   PBoolean previousIgnoreAllocations;
    00951 };
    00952
    00953 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
    00954
    00955 class PMemoryAllocationBreakpoint {
    00956 public:
    00957   PMemoryAllocationBreakpoint(DWORD point)
    00958   {
    00959     PMemoryHeap::SetAllocationBreakpoint(point);
    00960   }
    00961 };
    00962
    00963 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
    00964
    00965
    00966 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
    00967
    00968 #define PMEMORY_HEAP 0
    00969
    00970 #define PNEW new
    00971
    00972 #define PNEW_AND_DELETE_FUNCTIONS
    00973
    00974 #define runtime_malloc(s) malloc(s)
    00975 #define runtime_free(p) free(p)
    00976
    00977 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
    00978 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
    00979
    00980 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
    00981
    00982
    00983
    00984 /*
    00985  *  Implement "construct on first use" paradigm
    00986  */
    00987
    00988 template <class GnuAllocator, class Type>
    00989 struct PAllocatorTemplate
    00990 {
    00991   Type * allocate(size_t v)
    00992   {
    00993     return GetAllocator().allocate(v);
    00994   }
    00995
    00996   void deallocate(Type * p, size_t v)
    00997   {
    00998     GetAllocator().deallocate(p, v);
    00999   }
    01000
    01001   private:
    01002     static GnuAllocator & GetAllocator()
    01003     {
    01004       static GnuAllocator instance;
    01005       return instance;
    01006     }
    01007 };
    01008
    01009 #define GCC_VERSION (__GNUC__ * 10000 \
    01010                    + __GNUC_MINOR__ * 100 \
    01011                    + __GNUC_PATCHLEVEL__)
    01012
    01013 // Memory pooling allocators
    01014 #if defined(__GNUC__) && (GCC_VERSION > 40000) && !defined(P_MINGW) && !defined(P_MACOSX)
    01015 #include <ext/mt_allocator.h>
    01016 template <class Type> struct PFixedPoolAllocator    : public PAllocatorTemplate<__gnu_cxx::__mt_alloc<Type>, Type> { };
    01017 template <class Type> struct PVariablePoolAllocator : public PAllocatorTemplate<__gnu_cxx::__mt_alloc<Type>, Type> { };
    01018
    01019 #else
    01020
    01021 template <class Type> struct PFixedPoolAllocator    : public PAllocatorTemplate<std::allocator<Type>, Type> { };
    01022 template <class Type> struct PVariablePoolAllocator : public PAllocatorTemplate<std::allocator<Type>, Type> { };
    01023 #endif
    01024
    01025 #define PDECLARE_POOL_ALLOCATOR() \
    01026     void * operator new(size_t nSize); \
    01027     void * operator new(size_t nSize, const char * file, int line); \
    01028     void operator delete(void * ptr); \
    01029     void operator delete(void * ptr, const char *, int)
    01030
    01031 #define PDEFINE_POOL_ALLOCATOR(cls) \
    01032   static PFixedPoolAllocator<cls> cls##_allocator; \
    01033   void * cls::operator new(size_t)                           { return cls##_allocator.allocate(1);               } \
    01034   void * cls::operator new(size_t, const char *, int)        { return cls##_allocator.allocate(1);               } \
    01035   void   cls::operator delete(void * ptr)                    {        cls##_allocator.deallocate((cls *)ptr, 1); } \
    01036   void   cls::operator delete(void * ptr, const char *, int) {        cls##_allocator.deallocate((cls *)ptr, 1); }
    01037
    01038
    01049 #define PCLASSINFO(cls, par) \
    01050   public: \
    01051     typedef cls P_thisClass; \
    01052     static inline const char * Class() \
    01053       { return #cls; } \
    01054     virtual PBoolean InternalIsDescendant(const char * clsName) const \
    01055       { return strcmp(clsName, cls::Class()) == 0 || par::InternalIsDescendant(clsName); } \
    01056     virtual const char * GetClass(unsigned ancestor = 0) const \
    01057       { return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
    01058     virtual PObject::Comparison CompareObjectMemoryDirect(const PObject & obj) const \
    01059       { return PObject::InternalCompareObjectMemoryDirect(this, dynamic_cast<const cls *>(&obj), sizeof(cls)); } \
    01060     PNEW_AND_DELETE_FUNCTIONS
    01061
    01062
    01063 #if P_HAS_TYPEINFO
    01064
    01065 #define PIsDescendant(ptr, cls)    (dynamic_cast<const cls *>(ptr) != NULL)
    01066 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
    01067
    01068 #define PRemoveConst(cls, ptr)  (const_cast<cls*>(ptr))
    01069
    01070 #if P_USE_ASSERTS
    01071 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line)
    01072   { if (obj == NULL) PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return obj; }
    01073 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
    01074 #else
    01075 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
    01076 #endif
    01077
    01078 #include <typeinfo>
    01079
    01080 #else // P_HAS_TYPEINFO
    01081
    01082 #define PIsDescendant(ptr, cls)    ((ptr)->InternalIsDescendant(cls::Class()))
    01083 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
    01084
    01085 #define PRemoveConst(cls, ptr)  ((cls*)(ptr))
    01086
    01087 #if P_USE_ASSERTS
    01088 template<class BaseClass> inline BaseClass * PAssertCast(PObject * obj, const char * file, int line)
    01089   { if (obj->InternalIsDescendant(BaseClass::Class())) return (BaseClass *)obj; PAssertFunc(file, line, BaseClass::Class(), PInvalidCast); return NULL; }
    01090 #define PDownCast(cls, ptr) PAssertCast<cls>((ptr),__FILE__,__LINE__)
    01091 #else
    01092 #define PDownCast(cls, ptr) ((cls*)(ptr))
    01093 #endif
    01094
    01095 #endif // P_HAS_TYPEINFO
    01096
    01097
    01106 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
    01107 #ifdef DOC_PLUS_PLUS
    01108 } Match previous opening brace in doc++
    01109 #endif
    01110
    01112 // The root of all evil ... umm classes
    01113
    01118 class PObject {
    01119
    01120   protected:
    01124     PObject() { }
    01125
    01126   public:
    01127     /* Destructor required to get the "virtual". A PObject really has nothing
    01128        to destroy.
    01129      */
    01130     virtual ~PObject() { }
    01131
    01144     static inline const char * Class()    { return "PObject"; }
    01145
    01158     virtual const char * GetClass(unsigned ancestor = 0) const { return ancestor > 0 ? "" : Class(); }
    01159
    01160     PBoolean IsClass(const char * cls) const
    01161     { return strcmp(cls, GetClass()) == 0; }
    01162
    01172     virtual PBoolean InternalIsDescendant(
    01173       const char * clsName    // Ancestor class name to compare against.
    01174     ) const
    01175     { return IsClass(clsName); }
    01176
    01178
    01184     enum Comparison {
    01185       LessThan = -1,
    01186       EqualTo = 0,
    01187       GreaterThan = 1
    01188     };
    01189
    01201     virtual Comparison Compare(
    01202       const PObject & obj   // Object to compare against.
    01203     ) const;
    01204
    01216     virtual Comparison CompareObjectMemoryDirect(
    01217       const PObject & obj   // Object to compare against.
    01218     ) const;
    01219
    01221     static Comparison InternalCompareObjectMemoryDirect(
    01222       const PObject * obj1,
    01223       const PObject * obj2,
    01224       PINDEX size
    01225     );
    01226
    01232     bool operator==(
    01233       const PObject & obj   // Object to compare against.
    01234     ) const { return Compare(obj) == EqualTo; }
    01235
    01241     bool operator!=(
    01242       const PObject & obj   // Object to compare against.
    01243     ) const { return Compare(obj) != EqualTo; }
    01244
    01250     bool operator<(
    01251       const PObject & obj   // Object to compare against.
    01252     ) const { return Compare(obj) == LessThan; }
    01253
    01259     bool operator>(
    01260       const PObject & obj   // Object to compare against.
    01261     ) const { return Compare(obj) == GreaterThan; }
    01262
    01268     bool operator<=(
    01269       const PObject & obj   // Object to compare against.
    01270     ) const { return Compare(obj) != GreaterThan; }
    01271
    01277     bool operator>=(
    01278       const PObject & obj   // Object to compare against.
    01279     ) const { return Compare(obj) != LessThan; }
    01281
    01290     virtual void PrintOn(
    01291       ostream &strm   // Stream to print the object into.
    01292     ) const;
    01293
    01300     virtual void ReadFrom(
    01301       istream &strm   // Stream to read the objects contents from.
    01302     );
    01303
    01304
    01310     inline friend ostream & operator<<(
    01311       ostream &strm,
    01312       const PObject & obj
    01313     ) { obj.PrintOn(strm); return strm; }
    01314
    01320     inline friend istream & operator>>(
    01321       istream &strm,
    01322       PObject & obj
    01323     ) { obj.ReadFrom(strm); return strm; }
    01324
    01325
    01340     virtual PObject * Clone() const;
    01341
    01353     virtual PINDEX HashFunction() const;
    01355 };
    01356
    01358 // Platform independent types
    01359
    01360 // All these classes encapsulate primitive types such that they may be
    01361 // transfered in a platform independent manner. In particular it is used to
    01362 // do byte swapping for little endien and big endien processor architectures
    01363 // as well as accommodating structure packing rules for memory structures.
    01364
    01365 #define PANSI_CHAR 1
    01366 #define PLITTLE_ENDIAN 2
    01367 #define PBIG_ENDIAN 3
    01368
    01369
    01370 template <typename type>
    01371 struct PIntSameOrder {
    01372   __inline PIntSameOrder()                            : data(0)              { }
    01373   __inline PIntSameOrder(type value)                  : data(value)          { }
    01374   __inline PIntSameOrder(const PIntSameOrder & value) : data(value.data)     { }
    01375   __inline PIntSameOrder & operator=(type value)                             { data = value; return *this; }
    01376   __inline PIntSameOrder & operator=(const PIntSameOrder & value)            { data = value.data; return *this; }
    01377   __inline operator type() const                                             { return data; }
    01378   __inline friend ostream & operator<<(ostream & s, const PIntSameOrder & v) { return s << v.data; }
    01379   __inline friend istream & operator>>(istream & s, PIntSameOrder & v)       { return s >> v.data; }
    01380
    01381   private:
    01382     type data;
    01383 };
    01384
    01385
    01386 template <typename type>
    01387 struct PIntReversedOrder {
    01388   __inline PIntReversedOrder()                                : data(0)              { }
    01389   __inline PIntReversedOrder(type value)                                             { ReverseBytes(value, data); }
    01390   __inline PIntReversedOrder(const PIntReversedOrder & value) : data(value.data)     { }
    01391   __inline PIntReversedOrder & operator=(type value)                                 { ReverseBytes(value, data); return *this; }
    01392   __inline PIntReversedOrder & operator=(const PIntReversedOrder & value)            { data = value.data; return *this; }
    01393   __inline operator type() const                                                     { type value; ReverseBytes(data, value); return value; }
    01394   __inline friend ostream & operator<<(ostream & s, const PIntReversedOrder & value) { return s << (type)value; }
    01395   __inline friend istream & operator>>(istream & s, PIntReversedOrder & v)           { type val; s >> val; v = val; return s; }
    01396
    01397   private:
    01398     type data;
    01399
    01400   static __inline void ReverseBytes(const type & src, type & dst)
    01401   {
    01402     size_t s = sizeof(type)-1;
    01403     for (size_t d = 0; d < sizeof(type); ++d,--s)
    01404       ((BYTE *)&dst)[d] = ((const BYTE *)&src)[s];
    01405   }
    01406 };
    01407
    01408 #ifndef PCHAR8
    01409 #define PCHAR8 PANSI_CHAR
    01410 #endif
    01411
    01412 #if PCHAR8==PANSI_CHAR
    01413 typedef PIntSameOrder<char> PChar8;
    01414 #endif
    01415
    01416 typedef PIntSameOrder<char> PInt8;
    01417
    01418 typedef PIntSameOrder<unsigned char> PUInt8;
    01419
    01420 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01421 typedef PIntSameOrder<PInt16> PInt16l;
    01422 #elif PBYTE_ORDER==PBIG_ENDIAN
    01423 typedef PIntReversedOrder<PInt16> PInt16l;
    01424 #endif
    01425
    01426 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01427 typedef PIntReversedOrder<PInt16> PInt16b;
    01428 #elif PBYTE_ORDER==PBIG_ENDIAN
    01429 typedef PIntSameOrder<PInt16> PInt16b;
    01430 #endif
    01431
    01432 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01433 typedef PIntSameOrder<WORD> PUInt16l;
    01434 #elif PBYTE_ORDER==PBIG_ENDIAN
    01435 typedef PIntReversedOrder<WORD> PUInt16l;
    01436 #endif
    01437
    01438 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01439 typedef PIntReversedOrder<WORD> PUInt16b;
    01440 #elif PBYTE_ORDER==PBIG_ENDIAN
    01441 typedef PIntSameOrder<WORD> PUInt16b;
    01442 #endif
    01443
    01444 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01445 typedef PIntSameOrder<PInt32> PInt32l;
    01446 #elif PBYTE_ORDER==PBIG_ENDIAN
    01447 typedef PIntReversedOrder<PInt32> PInt32l;
    01448 #endif
    01449
    01450 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01451 typedef PIntReversedOrder<PInt32> PInt32b;
    01452 #elif PBYTE_ORDER==PBIG_ENDIAN
    01453 typedef PIntSameOrder<PInt32> PInt32b;
    01454 #endif
    01455
    01456 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01457 typedef PIntSameOrder<DWORD> PUInt32l;
    01458 #elif PBYTE_ORDER==PBIG_ENDIAN
    01459 typedef PIntReversedOrder<DWORD> PUInt32l;
    01460 #endif
    01461
    01462 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01463 typedef PIntReversedOrder<DWORD> PUInt32b;
    01464 #elif PBYTE_ORDER==PBIG_ENDIAN
    01465 typedef PIntSameOrder<DWORD> PUInt32b;
    01466 #endif
    01467
    01468 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01469 typedef PIntSameOrder<PInt64> PInt64l;
    01470 #elif PBYTE_ORDER==PBIG_ENDIAN
    01471 typedef PIntReversedOrder<PInt64> PInt64l;
    01472 #endif
    01473
    01474 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01475 typedef PIntReversedOrder<PInt64> PInt64b;
    01476 #elif PBYTE_ORDER==PBIG_ENDIAN
    01477 typedef PIntSameOrder<PInt64> PInt64b;
    01478 #endif
    01479
    01480 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01481 typedef PIntSameOrder<PUInt64> PUInt64l;
    01482 #elif PBYTE_ORDER==PBIG_ENDIAN
    01483 typedef PIntReversedOrder<PUInt64> PUInt64l;
    01484 #endif
    01485
    01486 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01487 typedef PIntReversedOrder<PUInt64> PUInt64b;
    01488 #elif PBYTE_ORDER==PBIG_ENDIAN
    01489 typedef PIntSameOrder<PUInt64> PUInt64b;
    01490 #endif
    01491
    01492 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01493 typedef PIntSameOrder<float> PFloat32l;
    01494 #elif PBYTE_ORDER==PBIG_ENDIAN
    01495 typedef PIntReversedOrder<float> PFloat32l;
    01496 #endif
    01497
    01498 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01499 typedef PIntReversedOrder<float> PFloat32b;
    01500 #elif PBYTE_ORDER==PBIG_ENDIAN
    01501 typedef PIntSameOrder<float> PFloat32b;
    01502 #endif
    01503
    01504 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01505 typedef PIntSameOrder<double> PFloat64l;
    01506 #elif PBYTE_ORDER==PBIG_ENDIAN
    01507 typedef PIntReversedOrder<double> PFloat64l;
    01508 #endif
    01509
    01510 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01511 typedef PIntReversedOrder<double> PFloat64b;
    01512 #elif PBYTE_ORDER==PBIG_ENDIAN
    01513 typedef PIntSameOrder<double> PFloat64b;
    01514 #endif
    01515
    01516 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
    01517 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01518 typedef PIntSameOrder<long double> PFloat80l;
    01519 #elif PBYTE_ORDER==PBIG_ENDIAN
    01520 typedef PIntReversedOrder<long double> PFloat80l;
    01521 #endif
    01522
    01523 #if PBYTE_ORDER==PLITTLE_ENDIAN
    01524 typedef PIntReversedOrder<long double> PFloat80b;
    01525 #elif PBYTE_ORDER==PBIG_ENDIAN
    01526 typedef PIntSameOrder<long double> PFloat80b;
    01527 #endif
    01528 #endif
    01529
    01530
    01532 // Miscellaneous
    01533
    01534 /*$MACRO PARRAYSIZE(array)
    01535    This macro is used to calculate the number of array elements in a static
    01536    array.
    01537  */
    01538 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
    01539
    01540 /*$MACRO PMIN(v1, v2)
    01541    This macro is used to calculate the minimum of two values. As this is a
    01542    macro the expression in <code>v1</code> or <code>v2</code> is executed
    01543    twice so extreme care should be made in its use.
    01544  */
    01545 #define PMIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
    01546
    01547 /*$MACRO PMAX(v1, v2)
    01548    This macro is used to calculate the maximum of two values. As this is a
    01549    macro the expression in <code>v1</code> or <code>v2</code> is executed
    01550    twice so extreme care should be made in its use.
    01551  */
    01552 #define PMAX(v1, v2) ((v1) > (v2) ? (v1) : (v2))
    01553
    01554 /*$MACRO PABS(val)
    01555    This macro is used to calculate an absolute value. As this is a macro the
    01556    expression in <code>val</code> is executed twice so extreme care should be
    01557    made in its use.
    01558  */
    01559 #define PABS(v) ((v) < 0 ? -(v) : (v))
    01560
    01561
    01562 #endif // PTLIB_OBJECT_H
    01563
    01564
    01565 // End Of File ///////////////////////////////////////////////////////////////