Rework pjlib++

git-svn-id: https://svn.pjsip.org/repos/pjproject/main@36 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjlib/build/pjlib++-test.dsp b/pjlib/build/pjlib++-test.dsp
new file mode 100644
index 0000000..88ae04a
--- /dev/null
+++ b/pjlib/build/pjlib++-test.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="pjlib++_test" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Console Application" 0x0103

+

+CFG=pjlib++_test - Win32 Debug

+!MESSAGE This is not a valid makefile. To build this project using NMAKE,

+!MESSAGE use the Export Makefile command and run

+!MESSAGE 

+!MESSAGE NMAKE /f "pjlib++-test.mak".

+!MESSAGE 

+!MESSAGE You can specify a configuration when running NMAKE

+!MESSAGE by defining the macro CFG on the command line. For example:

+!MESSAGE 

+!MESSAGE NMAKE /f "pjlib++-test.mak" CFG="pjlib++_test - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "pjlib++_test - Win32 Release" (based on "Win32 (x86) Console Application")

+!MESSAGE "pjlib++_test - Win32 Debug" (based on "Win32 (x86) Console Application")

+!MESSAGE 

+

+# Begin Project

+# PROP AllowPerConfigDependencies 0

+# PROP Scc_ProjName ""

+# PROP Scc_LocalPath ""

+CPP=cl.exe

+RSC=rc.exe

+

+!IF  "$(CFG)" == "pjlib++_test - Win32 Release"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir "./output/pjlib++-test-i386-win32-vc6-release"

+# PROP BASE Intermediate_Dir "./output/pjlib++-test-i386-win32-vc6-release"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir "./output/pjlib++-test-i386-win32-vc6-release"

+# PROP Intermediate_Dir "./output/pjlib++-test-i386-win32-vc6-release"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c

+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /I "../../pjlib-util/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /YX /FD /c

+# ADD BASE RSC /l 0x409 /d "NDEBUG"

+# ADD RSC /l 0x409 /d "NDEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386

+# ADD LINK32 netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/pjlib++-test-i386-win32-vc6-release.exe"

+

+!ELSEIF  "$(CFG)" == "pjlib++_test - Win32 Debug"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 1

+# PROP BASE Output_Dir "./output/pjlib++-test-i386-win32-vc6-debug"

+# PROP BASE Intermediate_Dir "./output/pjlib++-test-i386-win32-vc6-debug"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 1

+# PROP Output_Dir "./output/pjlib++-test-i386-win32-vc6-debug"

+# PROP Intermediate_Dir "./output/pjlib++-test-i386-win32-vc6-debug"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c

+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib-util/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /GZ /c

+# ADD BASE RSC /l 0x409 /d "_DEBUG"

+# ADD RSC /l 0x409 /d "_DEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept

+# ADD LINK32 netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/pjlib++-test-i386-win32-vc6-debug.exe" /pdbtype:sept

+

+!ENDIF 

+

+# Begin Target

+

+# Name "pjlib++_test - Win32 Release"

+# Name "pjlib++_test - Win32 Debug"

+# Begin Group "Source Files"

+

+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"

+# Begin Source File

+

+SOURCE="..\src\pjlib++-test\main.cpp"

+# End Source File

+# End Group

+# Begin Group "Header Files"

+

+# PROP Default_Filter "h;hpp;hxx;hm;inl"

+# End Group

+# Begin Group "Resource Files"

+

+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"

+# End Group

+# End Target

+# End Project

diff --git a/pjlib/build/pjlib++.dsp b/pjlib/build/pjlib++.dsp
new file mode 100644
index 0000000..77057fb
--- /dev/null
+++ b/pjlib/build/pjlib++.dsp
@@ -0,0 +1,142 @@
+# Microsoft Developer Studio Project File - Name="pjlib++" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Static Library" 0x0104

+

+CFG=pjlib++ - Win32 Debug

+!MESSAGE This is not a valid makefile. To build this project using NMAKE,

+!MESSAGE use the Export Makefile command and run

+!MESSAGE 

+!MESSAGE NMAKE /f "pjlib++.mak".

+!MESSAGE 

+!MESSAGE You can specify a configuration when running NMAKE

+!MESSAGE by defining the macro CFG on the command line. For example:

+!MESSAGE 

+!MESSAGE NMAKE /f "pjlib++.mak" CFG="pjlib++ - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "pjlib++ - Win32 Release" (based on "Win32 (x86) Static Library")

+!MESSAGE "pjlib++ - Win32 Debug" (based on "Win32 (x86) Static Library")

+!MESSAGE 

+

+# Begin Project

+# PROP AllowPerConfigDependencies 0

+# PROP Scc_ProjName ""$/pjproject/pjlib/build", UIAAAAAA"

+# PROP Scc_LocalPath "."

+CPP=cl.exe

+RSC=rc.exe

+

+!IF  "$(CFG)" == "pjlib++ - Win32 Release"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir ".\output\pjlib++-i386-win32-vc6-release"

+# PROP BASE Intermediate_Dir ".\output\pjlib++-i386-win32-vc6-release"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir ".\output\pjlib++-i386-win32-vc6-release"

+# PROP Intermediate_Dir ".\output\pjlib++-i386-win32-vc6-release"

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c

+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FD /c

+# SUBTRACT CPP /YX

+# ADD BASE RSC /l 0x409 /d "NDEBUG"

+# ADD RSC /l 0x409 /d "NDEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LIB32=link.exe -lib

+# ADD BASE LIB32 /nologo

+# ADD LIB32 /nologo /out:"../lib/pjlibp_vc6s.lib"

+

+!ELSEIF  "$(CFG)" == "pjlib++ - Win32 Debug"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 1

+# PROP BASE Output_Dir ".\output\pjlib++-i386-win32-vc6-debug"

+# PROP BASE Intermediate_Dir ".\output\pjlib++-i386-win32-vc6-debug"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 1

+# PROP Output_Dir ".\output\pjlib++-i386-win32-vc6-debug"

+# PROP Intermediate_Dir ".\output\pjlib++-i386-win32-vc6-debug"

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c

+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib-util/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FD /GZ /c

+# SUBTRACT CPP /YX

+# ADD BASE RSC /l 0x409 /d "_DEBUG"

+# ADD RSC /l 0x409 /d "_DEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LIB32=link.exe -lib

+# ADD BASE LIB32 /nologo

+# ADD LIB32 /nologo /out:"../lib/pjlibp_vc6sd.lib"

+

+!ENDIF 

+

+# Begin Target

+

+# Name "pjlib++ - Win32 Release"

+# Name "pjlib++ - Win32 Debug"

+# Begin Group "Header Files"

+

+# PROP Default_Filter "h;hpp;hxx;hm;inl"

+# Begin Source File

+

+SOURCE="..\include\pj++\file.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\hash.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\list.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\lock.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\os.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\pool.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\proactor.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\scanner.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\sock.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\string.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\timer.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\tree.hpp"

+# End Source File

+# Begin Source File

+

+SOURCE="..\include\pj++\types.hpp"

+# End Source File

+# End Group

+# End Target

+# End Project

diff --git a/pjlib/build/pjlibpp.vcproj b/pjlib/build/pjlib++.vcproj
similarity index 100%
rename from pjlib/build/pjlibpp.vcproj
rename to pjlib/build/pjlib++.vcproj
diff --git a/pjlib/build/pjlib.dsp b/pjlib/build/pjlib.dsp
index 8b95515..a4222ca 100644
--- a/pjlib/build/pjlib.dsp
+++ b/pjlib/build/pjlib.dsp
@@ -234,6 +234,13 @@
 # Begin Source File

 

 SOURCE=..\src\pj\ioqueue_winnt.c

+

+!IF  "$(CFG)" == "pjlib - Win32 Release"

+

+!ELSEIF  "$(CFG)" == "pjlib - Win32 Debug"

+

+!ENDIF 

+

 # End Source File

 # Begin Source File

 

diff --git a/pjlib/build/pjlib.dsw b/pjlib/build/pjlib.dsw
index 87ebf47..41d8c9e 100644
--- a/pjlib/build/pjlib.dsw
+++ b/pjlib/build/pjlib.dsw
@@ -3,14 +3,10 @@
 

 ###############################################################################

 

-Project: "pjlib"=".\pjlib.dsp" - Package Owner=<4>

+Project: "pjlib"=.\pjlib.dsp - Package Owner=<4>

 

 Package=<5>

 {{{

-    begin source code control

-    "$/pjproject-0.3/pjlib/build", EJDAAAAA

-    .

-    end source code control

 }}}

 

 Package=<4>

@@ -19,14 +15,22 @@
 

 ###############################################################################

 

-Project: "pjlib_samples"=".\pjlib_samples.dsp" - Package Owner=<4>

+Project: "pjlib++"=".\pjlib++.dsp" - Package Owner=<4>

 

 Package=<5>

 {{{

-    begin source code control

-    "$/pjproject-0.3/pjlib/build", EJDAAAAA

-    .

-    end source code control

+}}}

+

+Package=<4>

+{{{

+}}}

+

+###############################################################################

+

+Project: "pjlib_samples"=.\pjlib_samples.dsp - Package Owner=<4>

+

+Package=<5>

+{{{

 }}}

 

 Package=<4>

@@ -38,14 +42,10 @@
 

 ###############################################################################

 

-Project: "pjlib_test"=".\pjlib_test.dsp" - Package Owner=<4>

+Project: "pjlib_test"=.\pjlib_test.dsp - Package Owner=<4>

 

 Package=<5>

 {{{

-    begin source code control

-    "$/pjproject-0.3/pjlib/build", EJDAAAAA

-    .

-    end source code control

 }}}

 

 Package=<4>

@@ -57,18 +57,20 @@
 

 ###############################################################################

 

-Project: "pjlibpp"=".\pjlibpp.dsp" - Package Owner=<4>

+Project: "pjlib++_test"=.\pjlib++-test.dsp - Package Owner=<4>

 

 Package=<5>

 {{{

-    begin source code control

-    "$/pjproject-0.3/pjlib/build", EJDAAAAA

-    .

-    end source code control

 }}}

 

 Package=<4>

 {{{

+    Begin Project Dependency

+    Project_Dep_Name pjlib

+    End Project Dependency

+    Begin Project Dependency

+    Project_Dep_Name pjlib++

+    End Project Dependency

 }}}

 

 ###############################################################################

@@ -77,10 +79,6 @@
 

 Package=<5>

 {{{

-    begin source code control

-    "$/pjproject-0.3/pjlib/build", EJDAAAAA

-    .

-    end source code control

 }}}

 

 Package=<3>

diff --git a/pjlib/build/pjlibpp.dsp b/pjlib/build/pjlibpp.dsp
deleted file mode 100644
index 34b31a8..0000000
--- a/pjlib/build/pjlibpp.dsp
+++ /dev/null
@@ -1,158 +0,0 @@
-# Microsoft Developer Studio Project File - Name="pjlibpp" - Package Owner=<4>

-# Microsoft Developer Studio Generated Build File, Format Version 6.00

-# ** DO NOT EDIT **

-

-# TARGTYPE "Win32 (x86) Static Library" 0x0104

-

-CFG=pjlibpp - Win32 Debug

-!MESSAGE This is not a valid makefile. To build this project using NMAKE,

-!MESSAGE use the Export Makefile command and run

-!MESSAGE 

-!MESSAGE NMAKE /f "pjlibpp.mak".

-!MESSAGE 

-!MESSAGE You can specify a configuration when running NMAKE

-!MESSAGE by defining the macro CFG on the command line. For example:

-!MESSAGE 

-!MESSAGE NMAKE /f "pjlibpp.mak" CFG="pjlibpp - Win32 Debug"

-!MESSAGE 

-!MESSAGE Possible choices for configuration are:

-!MESSAGE 

-!MESSAGE "pjlibpp - Win32 Release" (based on "Win32 (x86) Static Library")

-!MESSAGE "pjlibpp - Win32 Debug" (based on "Win32 (x86) Static Library")

-!MESSAGE 

-

-# Begin Project

-# PROP AllowPerConfigDependencies 0

-# PROP Scc_ProjName ""$/pjproject/pjlib/build", UIAAAAAA"

-# PROP Scc_LocalPath "."

-CPP=cl.exe

-RSC=rc.exe

-

-!IF  "$(CFG)" == "pjlibpp - Win32 Release"

-

-# PROP BASE Use_MFC 0

-# PROP BASE Use_Debug_Libraries 0

-# PROP BASE Output_Dir ".\output\pjlibpp-i386-win32-vc6-release"

-# PROP BASE Intermediate_Dir ".\output\pjlibpp-i386-win32-vc6-release"

-# PROP BASE Target_Dir ""

-# PROP Use_MFC 0

-# PROP Use_Debug_Libraries 0

-# PROP Output_Dir ".\output\pjlibpp-i386-win32-vc6-release"

-# PROP Intermediate_Dir ".\output\pjlibpp-i386-win32-vc6-release"

-# PROP Target_Dir ""

-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c

-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../src" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "PJ_WIN32" /D "PJ_M_I386" /FD /c

-# SUBTRACT CPP /YX

-# ADD BASE RSC /l 0x409 /d "NDEBUG"

-# ADD RSC /l 0x409 /d "NDEBUG"

-BSC32=bscmake.exe

-# ADD BASE BSC32 /nologo

-# ADD BSC32 /nologo

-LIB32=link.exe -lib

-# ADD BASE LIB32 /nologo

-# ADD LIB32 /nologo /out:"../lib/pjlibp_vc6s.lib"

-

-!ELSEIF  "$(CFG)" == "pjlibpp - Win32 Debug"

-

-# PROP BASE Use_MFC 0

-# PROP BASE Use_Debug_Libraries 1

-# PROP BASE Output_Dir ".\output\pjlibpp-i386-win32-vc6-debug"

-# PROP BASE Intermediate_Dir ".\output\pjlibpp-i386-win32-vc6-debug"

-# PROP BASE Target_Dir ""

-# PROP Use_MFC 0

-# PROP Use_Debug_Libraries 1

-# PROP Output_Dir ".\output\pjlibpp-i386-win32-vc6-debug"

-# PROP Intermediate_Dir ".\output\pjlibpp-i386-win32-vc6-debug"

-# PROP Target_Dir ""

-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c

-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../src" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "PJ_WIN32" /D "PJ_M_I386" /FD /GZ /c

-# SUBTRACT CPP /YX

-# ADD BASE RSC /l 0x409 /d "_DEBUG"

-# ADD RSC /l 0x409 /d "_DEBUG"

-BSC32=bscmake.exe

-# ADD BASE BSC32 /nologo

-# ADD BSC32 /nologo

-LIB32=link.exe -lib

-# ADD BASE LIB32 /nologo

-# ADD LIB32 /nologo /out:"../lib/pjlibp_vc6sd.lib"

-

-!ENDIF 

-

-# Begin Target

-

-# Name "pjlibpp - Win32 Release"

-# Name "pjlibpp - Win32 Debug"

-# Begin Group "Source Files"

-

-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"

-# Begin Source File

-

-SOURCE="..\src\pj++\compiletest.cpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\pj++.cpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\proactor.cpp"

-# End Source File

-# End Group

-# Begin Group "Header Files"

-

-# PROP Default_Filter "h;hpp;hxx;hm;inl"

-# Begin Source File

-

-SOURCE="..\src\pj++\hash.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\ioqueue.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\list.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\os.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pjlib++.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\pool.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\proactor.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\scanner.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\sock.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\string.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\timer.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\tree.hpp"

-# End Source File

-# Begin Source File

-

-SOURCE="..\src\pj++\types.hpp"

-# End Source File

-# End Group

-# End Target

-# End Project

diff --git a/pjlib/include/pj++/file.hpp b/pjlib/include/pj++/file.hpp
new file mode 100644
index 0000000..dfd78d5
--- /dev/null
+++ b/pjlib/include/pj++/file.hpp
@@ -0,0 +1,171 @@
+/* $Id$ */

+

+#ifndef __PJPP_FILE_HPP__

+#define __PJPP_FILE_HPP__

+

+#include <pj/file_io.h>

+#include <pj/file_access.h>

+#include <pj++/types.hpp>

+#include <pj++/pool.hpp>

+

+//

+// File API.

+//

+class Pj_File_API

+{

+public:

+    //

+    // Check file existance.

+    //

+    static bool file_exists(const char *filename)

+    {

+        return pj_file_exists(filename) != 0;

+    }

+

+    //

+    // Get file size.

+    //

+    static pj_off_t file_size(const char *filename)

+    {

+        return pj_file_size(filename);

+    }

+

+    //

+    // Delete file.

+    //

+    static pj_status_t file_delete(const char *filename)

+    {

+        return pj_file_delete(filename);

+    }

+

+    //

+    // Move/rename file.

+    //

+    static pj_status_t file_move(const char *oldname, const char *newname)

+    {

+        return pj_file_move(oldname, newname);

+    }

+

+    //

+    // Get stat.

+    //

+    static pj_status_t file_stat(const char *filename, pj_file_stat *buf)

+    {

+        return pj_file_getstat(filename, buf);

+    }

+};

+

+

+//

+// File.

+//

+class Pj_File : public Pj_Object

+{

+public:

+    //

+    // Offset type to be used in setpos.

+    //

+    enum Offset_Type

+    {

+        SEEK_SET = PJ_SEEK_SET,

+        SEEK_CUR = PJ_SEEK_CUR,

+        SEEK_END = PJ_SEEK_END,

+    };

+

+    //

+    // Default constructor.

+    //

+    Pj_File()

+        : hnd_(0)

+    {

+    }

+

+    //

+    // Construct and open a file.

+    //

+    Pj_File(Pj_Pool *pool, const char *filename,

+            unsigned access = PJ_O_RDONLY)

+    : hnd_(NULL)

+    {

+        open(pool, filename, access);

+    }

+

+    //

+    // Destructor closes the file.

+    //

+    ~Pj_File()

+    {

+        close();

+    }

+

+    //

+    // Open a file.

+    //

+    pj_status_t open(Pj_Pool *pool, const char *filename, 

+                     unsigned access = PJ_O_RDONLY )

+    {

+        close();

+        return pj_file_open(pool->pool_(), filename, access, &hnd_);

+    }

+

+    //

+    // Close a file.

+    //

+    void close()

+    {

+        if (hnd_ != 0) {

+            pj_file_close(hnd_);

+            hnd_ = 0;

+        }

+    }

+

+    //

+    // Write data.

+    //

+    pj_ssize_t write(const void *buff, pj_size_t size)

+    {

+        pj_ssize_t bytes = size;

+        if (pj_file_write(hnd_, buff, &bytes) != PJ_SUCCESS)

+            return -1;

+        return bytes;

+    }

+

+    //

+    // Read data.

+    //

+    pj_ssize_t read(void *buf, pj_size_t size)

+    {

+        pj_ssize_t bytes = size;

+        if (pj_file_read(hnd_, buf, &bytes) != PJ_SUCCESS)

+            return -1;

+        return bytes;

+    }

+

+    //

+    // Set file position.

+    //

+    pj_status_t setpos(pj_off_t offset, Offset_Type whence)

+    {

+        return pj_file_setpos(hnd_, offset, 

+                              (enum pj_file_seek_type)whence);

+    }

+

+    //

+    // Get file position.

+    //

+    pj_off_t getpos()

+    {

+        pj_off_t pos;

+        if (pj_file_getpos(hnd_, &pos) != PJ_SUCCESS)

+            return -1;

+        return pos;

+    }

+

+private:

+    pj_oshandle_t hnd_;

+};

+

+

+

+#endif  /* __PJPP_FILE_HPP__ */

+

diff --git a/pjlib/include/pj++/hash.hpp b/pjlib/include/pj++/hash.hpp
index 26f4801..6d4a5e6 100644
--- a/pjlib/include/pj++/hash.hpp
+++ b/pjlib/include/pj++/hash.hpp
@@ -1,73 +1,139 @@
 /* $Id$
- *
  */

 #ifndef __PJPP_HASH_H__

 #define __PJPP_HASH_H__

 

 #include <pj++/types.hpp>

+#include <pj++/pool.hpp>

 #include <pj/hash.h>

 

-class PJ_Hash_Table

+//

+// Hash table.

+//

+class Pj_Hash_Table : public Pj_Object

 {

 public:

+    //

+    // Hash table iterator.

+    //

     class iterator

     {

     public:

-	iterator() {}

-	explicit iterator(pj_hash_table_t *h, pj_hash_iterator_t *i) : ht_(h), it_(i) {}

-	iterator(const iterator &rhs) : ht_(rhs.ht_), it_(rhs.it_) {}

-	void operator++() { it_ = pj_hash_next(ht_, it_); }

-	bool operator==(const iterator &rhs) { return ht_ == rhs.ht_ && it_ == rhs.it_; }

-	iterator & operator=(const iterator &rhs) { ht_=rhs.ht_; it_=rhs.it_; return *this; }

+	iterator() 

+        {

+        }

+	explicit iterator(pj_hash_table_t *h, pj_hash_iterator_t *i) 

+        : ht_(h), it_(i) 

+        {

+        }

+	iterator(const iterator &rhs) 

+        : ht_(rhs.ht_), it_(rhs.it_) 

+        {

+        }

+	void operator++() 

+        { 

+            it_ = pj_hash_next(ht_, it_); 

+        }

+	bool operator==(const iterator &rhs) 

+        { 

+            return ht_ == rhs.ht_ && it_ == rhs.it_; 

+        }

+	iterator & operator=(const iterator &rhs) 

+        { 

+            ht_=rhs.ht_; it_=rhs.it_; 

+            return *this; 

+        }

     private:

 	pj_hash_table_t *ht_;

 	pj_hash_iterator_t it_val_;

 	pj_hash_iterator_t *it_;

 

-	friend class PJ_Hash_Table;

+	friend class Pj_Hash_Table;

     };

 

-    static PJ_Hash_Table *create(PJ_Pool *pool, unsigned size)

+    //

+    // Construct hash table.

+    //

+    Pj_Hash_Table(Pj_Pool *pool, unsigned size)

     {

-	return (PJ_Hash_Table*) pj_hash_create(pool->pool_(), size);

+	table_ = pj_hash_create(pool->pool_(), size);

     }

 

-    static pj_uint32_t calc(pj_uint32_t initial_hval, const void *key, unsigned keylen)

+    //

+    // Destroy hash table.

+    //

+    ~Pj_Hash_Table()

+    {

+    }

+

+    //

+    // Calculate hash value.

+    //

+    static pj_uint32_t calc( pj_uint32_t initial_hval, 

+                             const void *key, 

+                             unsigned keylen = PJ_HASH_KEY_STRING)

     {

 	return pj_hash_calc(initial_hval, key, keylen);

     }

 

-    pj_hash_table_t *hash_table_()

+    //

+    // Return pjlib compatible hash table object.

+    //

+    pj_hash_table_t *pj_hash_table_t_()

     {

-	return (pj_hash_table_t*)this;

+	return table_;

     }

 

-    void *get(const void *key, unsigned keylen)

+    //

+    // Get the value associated with the specified key.

+    //

+    void *get(const void *key, unsigned keylen = PJ_HASH_KEY_STRING)

     {

-	return pj_hash_get(this->hash_table_(), key, keylen);

+	return pj_hash_get(table_, key, keylen);

     }

 

-    void set(PJ_Pool *pool, const void *key, unsigned keylen, void *value)

+    //

+    // Associate a value with a key.

+    // Set the value to NULL to delete the key from the hash table.

+    //

+    void set(Pj_Pool *pool, 

+             const void *key, 

+             void *value,

+             unsigned keylen = PJ_HASH_KEY_STRING)

     {

-	pj_hash_set(pool->pool_(), this->hash_table_(), key, keylen, value);

+	pj_hash_set(pool->pool_(), table_, key, keylen, value);

     }

 

+    //

+    // Get number of items in the hash table.

+    //

     unsigned count()

     {

-	return pj_hash_count(this->hash_table_());

+	return pj_hash_count(table_);

     }

 

+    //

+    // Iterate hash table.

+    //

     iterator begin()

     {

-	iterator it(this->hash_table_(), NULL);

-	it.it_ = pj_hash_first(this->hash_table_(), &it.it_val_);

+	iterator it(table_, NULL);

+	it.it_ = pj_hash_first(table_, &it.it_val_);

 	return it;

     }

 

+    //

+    // End of items.

+    //

     iterator end()

     {

-	return iterator(this->hash_table_(), NULL);

+	return iterator(table_, NULL);

     }

+

+private:

+    pj_hash_table_t *table_;

 };

 

+

 #endif	/* __PJPP_HASH_H__ */

+

diff --git a/pjlib/include/pj++/ioqueue.hpp b/pjlib/include/pj++/ioqueue.hpp
deleted file mode 100644
index 5724ecd..0000000
--- a/pjlib/include/pj++/ioqueue.hpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/* $Id$
- *
- */

-#ifndef __PJPP_IOQUEUE_H__

-#define __PJPP_IOQUEUE_H__

-

-#include <pj++/sock.hpp>

-#include <pj++/pool.hpp>

-#include <pj++/types.hpp>

-#include <pj/ioqueue.h>

-

-class PJ_IOQueue;

-

-class PJ_IOQueue_Event_Handler

-{

-public:

-    virtual ~PJ_IOQueue_Event_Handler()

-    {

-    }

-

-    pj_ioqueue_key_t* get_key() const

-    {

-	return key_;

-    }

-

-protected:

-    //

-    // Override this to get notification from I/O Queue

-    //

-    virtual void on_read_complete(pj_ssize_t bytes_read)

-    {

-    }

-

-    virtual void on_write_complete(pj_ssize_t bytes_sent)

-    {

-    }

-

-    virtual void on_accept_complete(int status)

-    {

-    }

-

-    virtual void on_connect_complete(int status)

-    {

-    }

-

-protected:

-    PJ_IOQueue_Event_Handler()

-	: ioqueue_(NULL), key_(NULL)

-    {

-    }

-

-private:

-    PJ_IOQueue *ioqueue_;

-    pj_ioqueue_key_t *key_;

-

-    static void read_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_read)

-    {

-	PJ_IOQueue_Event_Handler *handler = 

-	    (PJ_IOQueue_Event_Handler*)pj_ioqueue_get_user_data(key);

-	handler->on_read_complete(bytes_read);

-    }

-

-    static void write_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent);

-    static void accept_complete_cb(pj_ioqueue_key_t *key, int status);

-    static void connect_complete_cb(pj_ioqueue_key_t *key, int status);

-

-    friend class PJ_IOQueue;

-};

-

-

-class PJ_IOQueue

-{

-    typedef pj_ioqueue_t *B_;

-

-public:

-    typedef pj_ioqueue_key_t Key;

-

-    enum Operation

-    {

-	OP_NONE	     = PJ_IOQUEUE_OP_NONE,

-	OP_READ	     = PJ_IOQUEUE_OP_READ,

-	OP_RECV_FROM = PJ_IOQUEUE_OP_RECV_FROM,

-	OP_WRITE     = PJ_IOQUEUE_OP_WRITE,

-	OP_SEND_TO   = PJ_IOQUEUE_OP_SEND_TO,

-#if PJ_HAS_TCP

-	OP_ACCEPT    = PJ_IOQUEUE_OP_ACCEPT,

-	OP_CONNECT   = PJ_IOQUEUE_OP_CONNECT,

-#endif

-    };

-

-    enum Status

-    {

-	IS_PENDING = PJ_IOQUEUE_PENDING

-    };

-

-    static PJ_IOQueue *create(PJ_Pool *pool, pj_size_t max_fd)

-    {

-	return (PJ_IOQueue*) pj_ioqueue_create(pool->pool_(), max_fd);

-    }

-

-    operator B_()

-    {

-	return (pj_ioqueue_t*)(PJ_IOQueue*)this;

-    }

-

-    pj_ioqueue_t *ioq_()

-    {

-	return (B_)this;

-    }

-

-    void destroy()

-    {

-	pj_ioqueue_destroy(this->ioq_());

-    }

-

-    Key *register_handle(PJ_Pool *pool, pj_oshandle_t hnd, void *user_data)

-    {

-	return pj_ioqueue_register(pool->pool_(), this->ioq_(), hnd, user_data);

-    }

-

-    Key *register_socket(PJ_Pool *pool, pj_sock_t hnd, void *user_data)

-    {

-	return pj_ioqueue_register(pool->pool_(), this->ioq_(), (pj_oshandle_t)hnd, user_data);

-    }

-

-    pj_status_t unregister(Key *key)

-    {

-	return pj_ioqueue_unregister(this->ioq_(), key);

-    }

-

-    void *get_user_data(Key *key)

-    {

-	return pj_ioqueue_get_user_data(key);

-    }

-

-    int poll(Key **key, pj_ssize_t *bytes_status, Operation *op, const PJ_Time_Val *timeout)

-    {

-	return pj_ioqueue_poll(this->ioq_(), key, bytes_status, (pj_ioqueue_operation_e*)op, timeout);

-    }

-

-#if PJ_HAS_TCP

-    pj_status_t connect(Key *key, const pj_sockaddr_t *addr, int addrlen)

-    {

-	return pj_ioqueue_connect(this->ioq_(), key, addr, addrlen);

-    }

-

-    pj_status_t accept(Key *key, PJ_Socket *sock, pj_sockaddr_t *local, pj_sockaddr_t *remote, int *addrlen)

-    {

-	return pj_ioqueue_accept(this->ioq_(), key, &sock->get_handle(), local, remote, addrlen);

-    }

-#endif

-

-    int read(Key *key, void *buf, pj_size_t len)

-    {

-	return pj_ioqueue_read(this->ioq_(), key, buf, len);

-    }

-

-    int recvfrom(Key *key, void *buf, pj_size_t len, pj_sockaddr_t *addr, int *addrlen)

-    {

-	return pj_ioqueue_recvfrom(this->ioq_(), key, buf, len, addr, addrlen);

-    }

-

-    int write(Key *key, const void *data, pj_size_t len)

-    {

-	return pj_ioqueue_write(this->ioq_(), key, data, len);

-    }

-

-    int sendto(Key *key, const void *data, pj_size_t len, const pj_sockaddr_t *addr, int addrlen)

-    {

-	return pj_ioqueue_sendto(this->ioq_(), key, data, len, addr, addrlen);

-    }

-};

-

-#endif	/* __PJPP_IOQUEUE_H__ */

diff --git a/pjlib/include/pj++/list.hpp b/pjlib/include/pj++/list.hpp
index 6807678..9895c1c 100644
--- a/pjlib/include/pj++/list.hpp
+++ b/pjlib/include/pj++/list.hpp
@@ -1,164 +1,290 @@
 /* $Id$
- *
  */

 #ifndef __PJPP_LIST_H__

 #define __PJPP_LIST_H__

 

 #include <pj/list.h>

-

-template <typename T>

-struct PJ_List_Node

-{

-    PJ_DECL_LIST_MEMBER(T)

-};

+#include <pj++/pool.hpp>

 

 

-template <class Node>

-class PJ_List

+//

+// Linked-list.

+//

+// Note:

+//  List_Node must have public member next and prev. Normally

+//  it will be declared like:

+//

+//  struct my_node

+//  {

+//      PJ_DECL_LIST_MEMBER(struct my_node);

+//      ..

+//  };

+//

+//

+template <class List_Node>

+class Pj_List : public Pj_Object

 {

 public:

-    PJ_List() { pj_list_init(&root_); if (0) compiletest(); }

-    ~PJ_List() {}

-

+    //

+    // List const_iterator.

+    //

     class const_iterator

     {

     public:

-	const_iterator() : node_(NULL) {}

-	const_iterator(const Node *nd) : node_((Node*)nd) {}

-	const Node * operator *() { return node_; }

-	const Node * operator -> () { return node_; }

-	const_iterator operator++() { return const_iterator(node_->next); }

-	bool operator==(const const_iterator &rhs) { return node_ == rhs.node_; }

-	bool operator!=(const const_iterator &rhs) { return node_ != rhs.node_; }

+	const_iterator() 

+            : node_(NULL) 

+        {}

+	const_iterator(const List_Node *nd) 

+            : node_((List_Node*)nd) 

+        {}

+	const List_Node * operator *() 

+        { 

+            return node_; 

+        }

+	const List_Node * operator -> () 

+        { 

+            return node_; 

+        }

+	const_iterator operator++() 

+        { 

+            return const_iterator(node_->next); 

+        }

+	bool operator==(const const_iterator &rhs) 

+        { 

+            return node_ == rhs.node_; 

+        }

+	bool operator!=(const const_iterator &rhs) 

+        { 

+            return node_ != rhs.node_; 

+        }

 

     protected:

-	Node *node_;

+	List_Node *node_;

     };

 

+    //

+    // List iterator.

+    //

     class iterator : public const_iterator

     {

     public:

-	iterator() {}

-	iterator(Node *nd) : const_iterator(nd) {}

-	Node * operator *() { return node_; }

-	Node * operator -> () { return node_; }

-	iterator operator++() { return iterator(node_->next); }

-	bool operator==(const iterator &rhs) { return node_ == rhs.node_; }

-	bool operator!=(const iterator &rhs) { return node_ != rhs.node_; }

+	iterator() 

+        {}

+	iterator(List_Node *nd) 

+            : const_iterator(nd) 

+        {}

+	List_Node * operator *() 

+        { 

+            return node_; 

+        }

+	List_Node * operator -> () 

+        { 

+            return node_; 

+        }

+	iterator operator++() 

+        { 

+            return iterator(node_->next); 

+        }

+	bool operator==(const iterator &rhs) 

+        { 

+            return node_ == rhs.node_; 

+        }

+	bool operator!=(const iterator &rhs) 

+        { 

+            return node_ != rhs.node_; 

+        }

     };

 

+    //

+    // Default constructor.

+    //

+    Pj_List() 

+    { 

+        pj_list_init(&root_); 

+        if (0) compiletest(); 

+    }

+

+    //

+    // Check if list is empty.

+    // 

     bool empty() const

     {

 	return pj_list_empty(&root_);

     }

 

+    //

+    // Get first element.

+    //

     iterator begin()

     {

 	return iterator(root_.next);

     }

 

+    //

+    // Get first element.

+    //

     const_iterator begin() const

     {

 	return const_iterator(root_.next);

     }

 

+    //

+    // Get end-of-element

+    //

     const_iterator end() const

     {

-	return const_iterator((Node*)&root_);

+	return const_iterator((List_Node*)&root_);

     }

 

+    //

+    // Get end-of-element

+    //

     iterator end()

     {

-	return iterator((Node*)&root_);

+	return iterator((List_Node*)&root_);

     }

 

-    void insert_before (iterator &pos, Node *node)

+    //

+    // Insert node.

+    //

+    void insert_before (iterator &pos, List_Node *node)

     {

 	pj_list_insert_before( *pos, node );

     }

 

-    void insert_after(iterator &pos, Node *node)

+    //

+    // Insert node.

+    //

+    void insert_after(iterator &pos, List_Node *node)

     {

 	pj_list_insert_after(*pos, node);

     }

 

-    void merge_first(Node *list2)

+    //

+    // Merge list.

+    //

+    void merge_first(List_Node *list2)

     {

 	pj_list_merge_first(&root_, list2);

     }

 

-    void merge_last(PJ_List *list)

+    //

+    // Merge list.

+    //

+    void merge_last(Pj_List *list)

     {

 	pj_list_merge_last(&root_, &list->root_);

     }

 

-    void insert_nodes_before(iterator &pos, PJ_List *list2)

+    //

+    // Insert list.

+    //

+    void insert_nodes_before(iterator &pos, Pj_List *list2)

     {

 	pj_list_insert_nodes_before(*pos, &list2->root_);

     }

 

-    void insert_nodes_after(iterator &pos, PJ_List *list2)

+    //

+    // Insert list.

+    //

+    void insert_nodes_after(iterator &pos, Pj_List *list2)

     {

 	pj_list_insert_nodes_after(*pos, &list2->root_);

     }

 

+    //

+    // Erase an element.

+    //

     void erase(iterator &it)

     {

 	pj_list_erase(*it);

     }

 

-    Node *front()

+    //

+    // Get first element.

+    //

+    List_Node *front()

     {

 	return root_.next;

     }

 

-    const Node *front() const

+    //

+    // Get first element.

+    //

+    const List_Node *front() const

     {

 	return root_.next;

     }

 

+    //

+    // Remove first element.

+    //

     void pop_front()

     {

 	pj_list_erase(root_.next);

     }

 

-    Node *back()

+    //

+    // Get last element.

+    //

+    List_Node *back()

     {

 	return root_.prev;

     }

 

-    const Node *back() const

+    //

+    // Get last element.

+    //

+    const List_Node *back() const

     {

 	return root_.prev;

     }

 

+    //

+    // Remove last element.

+    //

     void pop_back()

     {

 	pj_list_erase(root_.prev);

     }

 

-    iterator find(Node *node)

+    //

+    // Find a node.

+    //

+    iterator find(List_Node *node)

     {

-	Node *n = pj_list_find_node(&root_, node);

+	List_Node *n = pj_list_find_node(&root_, node);

 	return n ? iterator(n) : end();

     }

 

-    const_iterator find(Node *node) const

+    //

+    // Find a node.

+    //

+    const_iterator find(List_Node *node) const

     {

-	Node *n = pj_list_find_node(&root_, node);

+	List_Node *n = pj_list_find_node(&root_, node);

 	return n ? const_iterator(n) : end();

     }

 

-    void push_back(Node *node)

+    //

+    // Insert a node in the back.

+    //

+    void push_back(List_Node *node)

     {

 	pj_list_insert_after(root_.prev, node);

     }

 

-    void push_front(Node *node)

+    //

+    // Insert a node in the front.

+    //

+    void push_front(List_Node *node)

     {

 	pj_list_insert_before(root_.next, node);

     }

 

+    //

+    // Remove all elements.

+    //

     void clear()

     {

 	root_.next = &root_;

@@ -168,14 +294,14 @@
 private:

     struct RootNode

     {

-	PJ_DECL_LIST_MEMBER(Node)

+	PJ_DECL_LIST_MEMBER(List_Node);

     } root_;

 

     void compiletest()

     {

 	// If you see error in this line, 

-	// it's because Node is not derived from PJ_List_Node.

-	Node *n = (Node*)0;

+	// it's because List_Node is not derived from Pj_List_Node.

+	List_Node *n = (List_Node*)0;

 	n = n->next; n = n->prev;

     }

 };

diff --git a/pjlib/include/pj++/lock.hpp b/pjlib/include/pj++/lock.hpp
new file mode 100644
index 0000000..93a435e
--- /dev/null
+++ b/pjlib/include/pj++/lock.hpp
@@ -0,0 +1,131 @@
+/* $Id$ */

+#ifndef __PJPP_LOCK_H__

+#define __PJPP_LOCK_H__

+

+#include <pj++/types.hpp>

+#include <pj/lock.h>

+#include <pj++/pool.hpp>

+

+//////////////////////////////////////////////////////////////////////////////

+// Lock object.

+//

+class Pj_Lock : public Pj_Object

+{

+public:

+    //

+    // Constructor.

+    //

+    explicit Pj_Lock(pj_lock_t *lock)

+        : lock_(lock)

+    {

+    }

+

+    //

+    // Destructor.

+    //

+    ~Pj_Lock()

+    {

+        if (lock_)

+            pj_lock_destroy(lock_);

+    }

+

+    //

+    // Get pjlib compatible lock object.

+    //

+    pj_lock_t *pj_lock_t_()

+    {

+        return lock_;

+    }

+

+    //

+    // acquire lock.

+    //

+    pj_status_t acquire()

+    {

+        return pj_lock_acquire(lock_);

+    }

+

+    //

+    // release lock,.

+    //

+    pj_status_t release()

+    {

+        return pj_lock_release(lock_);

+    }

+

+protected:

+    pj_lock_t *lock_;

+};

+

+

+//////////////////////////////////////////////////////////////////////////////

+// Null lock object.

+//

+class Pj_Null_Lock : public Pj_Lock

+{

+public:

+    //

+    // Default constructor.

+    //

+    explicit Pj_Null_Lock(Pj_Pool *pool, const char *name = NULL)

+        : Pj_Lock(NULL)

+    {

+        pj_lock_create_null_mutex(pool->pool_(), name, &lock_);

+    }

+};

+

+//////////////////////////////////////////////////////////////////////////////

+// Simple mutex lock object.

+//

+class Pj_Simple_Mutex_Lock : public Pj_Lock

+{

+public:

+    //

+    // Default constructor.

+    //

+    explicit Pj_Simple_Mutex_Lock(Pj_Pool *pool, const char *name = NULL)

+        : Pj_Lock(NULL)

+    {

+        pj_lock_create_simple_mutex(pool->pool_(), name, &lock_);

+    }

+};

+

+//////////////////////////////////////////////////////////////////////////////

+// Recursive mutex lock object.

+//

+class Pj_Recursive_Mutex_Lock : public Pj_Lock

+{

+public:

+    //

+    // Default constructor.

+    //

+    explicit Pj_Recursive_Mutex_Lock(Pj_Pool *pool, const char *name = NULL)

+        : Pj_Lock(NULL)

+    {

+        pj_lock_create_recursive_mutex(pool->pool_(), name, &lock_);

+    }

+};

+

+//////////////////////////////////////////////////////////////////////////////

+// Semaphore lock object.

+//

+class Pj_Semaphore_Lock : public Pj_Lock

+{

+public:

+    //

+    // Default constructor.

+    //

+    explicit Pj_Semaphore_Lock(Pj_Pool *pool, 

+                               unsigned max=PJ_MAXINT32,

+                               unsigned initial=0,

+                               const char *name=NULL)

+        : Pj_Lock(NULL)

+    {

+        pj_lock_create_semaphore(pool->pool_(), name, initial, max, &lock_);

+    }

+};

+

+

+

+#endif	/* __PJPP_LOCK_H__ */

+

diff --git a/pjlib/include/pj++/os.hpp b/pjlib/include/pj++/os.hpp
index af89ac8..1101dae 100644
--- a/pjlib/include/pj++/os.hpp
+++ b/pjlib/include/pj++/os.hpp
@@ -1,5 +1,4 @@
 /* $Id$
- *
  */

 #ifndef __PJPP_OS_H__

 #define __PJPP_OS_H__

@@ -8,7 +7,96 @@
 #include <pj++/types.hpp>

 #include <pj++/pool.hpp>

 

-class PJ_Thread

+class Pj_Thread;

+

+//

+// Thread API.

+//

+class Pj_Thread_API

+{

+public:

+    //

+    // Create a thread.

+    //

+    static pj_status_t create( Pj_Pool *pool, pj_thread_t **thread,

+                               pj_thread_proc *proc, void *arg,

+                               unsigned flags = 0,

+                               const char *name = NULL,

+                               pj_size_t stack_size = 0 )

+    {

+        return pj_thread_create(pool->pool_(), name, proc, arg, stack_size,

+                                flags, thread);

+    }

+

+    //

+    // Register a thread.

+    //

+    static pj_status_t register_this_thread( pj_thread_desc desc,

+                                             pj_thread_t **thread,

+                                             const char *name = NULL )

+    {

+        return pj_thread_register( name, desc, thread );

+    }

+

+    //

+    // Get current thread.

+    // Will return pj_thread_t (sorry folks, not Pj_Thread).

+    //

+    static pj_thread_t *this_thread()

+    {

+        return pj_thread_this();

+    }

+

+    //

+    // Get thread name.

+    //

+    static const char *get_name(pj_thread_t *thread)

+    {

+        return pj_thread_get_name(thread);

+    }

+

+    //

+    // Resume thread.

+    //

+    static pj_status_t resume(pj_thread_t *thread)

+    {

+        return pj_thread_resume(thread);

+    }

+

+    //

+    // Sleep.

+    //

+    static pj_status_t sleep(unsigned msec)

+    {

+	return pj_thread_sleep(msec);

+    }

+

+    //

+    // Join the specified thread.

+    //

+    static pj_status_t join(pj_thread_t *thread)

+    {

+        return pj_thread_join(thread);

+    }

+

+    //

+    // Destroy thread

+    //

+    static pj_status_t destroy(pj_thread_t *thread)

+    {

+        return pj_thread_destroy(thread);

+    }

+};

+

+

+

+//

+// Thread object.

+//

+// How to use:

+//  Derive a class from this class, then override main().

+//

+class Pj_Thread : public Pj_Object

 {

 public:

     enum Flags

@@ -16,134 +104,305 @@
 	FLAG_SUSPENDED = PJ_THREAD_SUSPENDED

     };

 

-    static PJ_Thread *create( PJ_Pool *pool, const char *thread_name,

-			      pj_thread_proc *proc, void *arg,

-			      pj_size_t stack_size, void *stack_ptr, 

-			      unsigned flags)

+    //

+    // Default constructor.

+    //

+    Pj_Thread()

+        : thread_(NULL)

     {

-	return (PJ_Thread*) pj_thread_create( pool->pool_(), thread_name, proc, arg, stack_size, stack_ptr, flags);

     }

 

-    static PJ_Thread *register_current_thread(const char *name, pj_thread_desc desc)

+    //

+    // Destroy thread.

+    //

+    ~Pj_Thread()

     {

-	return (PJ_Thread*) pj_thread_register(name, desc);

+        destroy();

     }

 

-    static PJ_Thread *get_current_thread()

+    //

+    // This is the main thread function.

+    //

+    virtual int main() = 0;

+

+    //

+    // Start a thread.

+    //

+    pj_status_t create( Pj_Pool *pool, 

+                        unsigned flags = 0,

+                        const char *thread_name = NULL,

+			pj_size_t stack_size = PJ_THREAD_DEFAULT_STACK_SIZE)

     {

-	return (PJ_Thread*) pj_thread_this();

+        destroy();

+        return Pj_Thread_API::create( pool, &thread_, &thread_proc, this,

+                                      flags, thread_name);

     }

 

-    static pj_status_t sleep(unsigned msec)

-    {

-	return pj_thread_sleep(msec);

-    }

-

-    static pj_status_t usleep(unsigned usec)

-    {

-	return pj_thread_usleep(usec);

-    }

-

+    //

+    // Get pjlib compatible thread object.

+    //

     pj_thread_t *pj_thread_t_()

     {

-	return (pj_thread_t*)this;

+	return thread_;

     }

 

+    //

+    // Get thread name.

+    //

     const char *get_name()

     {

-	return pj_thread_get_name( this->pj_thread_t_() );

+        return Pj_Thread_API::get_name(thread_);

     }

 

+    //

+    // Resume a suspended thread.

+    //

     pj_status_t resume()

     {

-	return pj_thread_resume( this->pj_thread_t_() );

+        return Pj_Thread_API::resume(thread_);

     }

 

+    //

+    // Join this thread.

+    //

     pj_status_t join()

     {

-	return pj_thread_join( this->pj_thread_t_() );

+        return Pj_Thread_API::join(thread_);

     }

 

+    //

+    // Destroy thread.

+    //

     pj_status_t destroy()

     {

-	return pj_thread_destroy( this->pj_thread_t_() );

+        if (thread_) {

+            Pj_Thread_API::destroy(thread_);

+            thread_ = NULL;

+        }

+    }

+

+protected:

+    pj_thread_t *thread_;

+

+    static int PJ_THREAD_FUNC thread_proc(void *obj)

+    {

+        Pj_Thread *thread_class = (Pj_Thread*)obj;

+        return thread_class->main();

     }

 };

 

 

-class PJ_Thread_Local

+//

+// External Thread

+//  (threads that were started by external means, i.e. not 

+//   with Pj_Thread::create).

+//

+// This class will normally be defined as local variable in

+// external thread's stack, normally inside thread's main proc.

+// But be aware that the handle will be destroyed on destructor!

+//

+class Pj_External_Thread : public Pj_Thread

 {

 public:

-    static PJ_Thread_Local *alloc()

+    Pj_External_Thread()

     {

-	long index = pj_thread_local_alloc();

-	return index < 0 ? NULL : (PJ_Thread_Local*)index;

-    }

-    void free()

-    {

-	pj_thread_local_free( this->tls_() );

     }

 

-    long tls_() const

+    //

+    // Register external thread so that pjlib functions can work

+    // in that thread.

+    //

+    pj_status_t register_this_thread( const char *name=NULL )

     {

-	return (long)this;

+        return Pj_Thread_API::register_this_thread(desc_, &thread_,name);

     }

 

-    void set(void *value)

-    {

-	pj_thread_local_set( this->tls_(), value );

-    }

-

-    void *get()

-    {

-	return pj_thread_local_get( this->tls_() );

-    }

+private:

+    pj_thread_desc desc_;

 };

 

 

-class PJ_Atomic

+//

+// Thread specific data/thread local storage/TLS.

+//

+class Pj_Thread_Local_API

 {

 public:

-    static PJ_Atomic *create(PJ_Pool *pool, long initial)

+    //

+    // Allocate thread local storage (TLS) index.

+    //

+    static pj_status_t alloc(long *index)

     {

-	return (PJ_Atomic*) pj_atomic_create(pool->pool_(), initial);

+        return pj_thread_local_alloc(index);

     }

 

+    //

+    // Free TLS index.

+    //

+    static void free(long index)

+    {

+        pj_thread_local_free(index);

+    }

+

+    //

+    // Set thread specific data.

+    //

+    static pj_status_t set(long index, void *value)

+    {

+        return pj_thread_local_set(index, value);

+    }

+

+    //

+    // Get thread specific data.

+    //

+    static void *get(long index)

+    {

+        return pj_thread_local_get(index);

+    }

+

+};

+

+//

+// Atomic variable

+//

+// How to use:

+//   Pj_Atomic_Var var(pool, 0);

+//   var.set(..);

+//

+class Pj_Atomic_Var : public Pj_Object

+{

+public:

+    //

+    // Default constructor, initialize variable with NULL.

+    //

+    Pj_Atomic_Var()

+        : var_(NULL)

+    {

+    }

+

+    //

+    // Construct atomic variable.

+    //

+    Pj_Atomic_Var(Pj_Pool *pool, pj_atomic_value_t value)

+        : var_(NULL)

+    {

+        create(pool, value);

+    }

+

+    //

+    // Destructor.

+    //

+    ~Pj_Atomic_Var()

+    {

+        destroy();

+    }

+

+    //

+    // Create atomic variable.

+    //

+    pj_status_t create( Pj_Pool *pool, pj_atomic_value_t value)

+    {

+        destroy();

+	return pj_atomic_create(pool->pool_(), value, &var_);

+    }

+

+    //

+    // Destroy.

+    //

+    void destroy()

+    {

+        if (var_) {

+            pj_atomic_destroy(var_);

+            var_ = NULL;

+        }

+    }

+

+    //

+    // Get pjlib compatible atomic variable.

+    //

     pj_atomic_t *pj_atomic_t_()

     {

-	return (pj_atomic_t*)this;

+	return var_;

     }

 

-    pj_status_t destroy()

+    //

+    // Set the value.

+    //

+    void set(pj_atomic_value_t val)

     {

-	return pj_atomic_destroy( this->pj_atomic_t_() );

+	pj_atomic_set(var_, val);

     }

 

-    long set(long val)

+    //

+    // Get the value.

+    //

+    pj_atomic_value_t get()

     {

-	return pj_atomic_set( this->pj_atomic_t_(), val);

+	return pj_atomic_get(var_);

     }

 

-    long get()

+    //

+    // Increment.

+    //

+    void inc()

     {

-	return pj_atomic_get( this->pj_atomic_t_() );

+	pj_atomic_inc(var_);

     }

 

-    long inc()

+    //

+    // Increment and get the result.

+    //

+    pj_atomic_value_t inc_and_get()

     {

-	return pj_atomic_inc( this->pj_atomic_t_() );

+        return pj_atomic_inc_and_get(var_);

     }

 

-    long dec()

+    //

+    // Decrement.

+    //

+    void dec()

     {

-	return pj_atomic_dec( this->pj_atomic_t_() );

+	pj_atomic_dec(var_);

     }

+

+    //

+    // Decrement and get the result.

+    //

+    pj_atomic_value_t dec_and_get()

+    {

+        return pj_atomic_dec_and_get(var_);

+    }

+

+    //

+    // Add the variable.

+    //

+    void add(pj_atomic_value_t value)

+    {

+        pj_atomic_add(var_, value);

+    }

+

+    //

+    // Add the variable and get the value.

+    //

+    pj_atomic_value_t add_and_get(pj_atomic_value_t value)

+    {

+        return pj_atomic_add_and_get(var_, value );

+    }

+

+private:

+    pj_atomic_t *var_;

 };

 

 

-class PJ_Mutex

+//

+// Mutex

+//

+class Pj_Mutex : public Pj_Object

 {

 public:

+    //

+    // Mutex type.

+    //

     enum Type

     {

 	DEFAULT = PJ_MUTEX_DEFAULT,

@@ -151,194 +410,378 @@
 	RECURSE = PJ_MUTEX_RECURSE,

     };

 

-    static PJ_Mutex *create( PJ_Pool *pool, const char *name, Type type)

+    //

+    // Default constructor will create default mutex.

+    //

+    explicit Pj_Mutex(Pj_Pool *pool, Type type = DEFAULT,

+                      const char *name = NULL)

+        : mutex_(NULL)

     {

-	return (PJ_Mutex*) pj_mutex_create( pool->pool_(), name, type);

+        create(pool, type, name);

     }

 

-    pj_mutex_t *pj_mutex_()

+    //

+    // Destructor.

+    //

+    ~Pj_Mutex()

     {

-	return (pj_mutex_t*)this;

+        destroy();

     }

 

-    pj_status_t destroy()

+    //

+    // Create mutex.

+    //

+    pj_status_t create( Pj_Pool *pool, Type type, const char *name = NULL)

     {

-	return pj_mutex_destroy( this->pj_mutex_() );

+        destroy();

+	return pj_mutex_create( pool->pool_(), name, type,

+                                &mutex_ );

     }

 

-    pj_status_t lock()

+    //

+    // Create simple mutex.

+    //

+    pj_status_t create_simple( Pj_Pool *pool,const char *name = NULL)

     {

-	return pj_mutex_lock( this->pj_mutex_() );

+        return create(pool, SIMPLE, name);

     }

 

-    pj_status_t unlock()

+    //

+    // Create recursive mutex.

+    //

+    pj_status_t create_recursive( Pj_Pool *pool, const char *name = NULL )

     {

-	return pj_mutex_unlock( this->pj_mutex_() );

+        return create(pool, RECURSE, name);

     }

 

-    pj_status_t trylock()

+    //

+    // Get pjlib compatible mutex object.

+    //

+    pj_mutex_t *pj_mutex_t_()

     {

-	return pj_mutex_trylock( this->pj_mutex_() );

+	return mutex_;

     }

 

-#if PJ_DEBUG

-    pj_status_t is_locked()

+    //

+    // Destroy mutex.

+    //

+    void destroy()

     {

-	return pj_mutex_is_locked( this->pj_mutex_() );

+        if (mutex_) {

+	    pj_mutex_destroy(mutex_);

+            mutex_ = NULL;

+        }

     }

-#endif

+

+    //

+    // Lock mutex.

+    //

+    pj_status_t acquire()

+    {

+	return pj_mutex_lock(mutex_);

+    }

+

+    //

+    // Unlock mutex.

+    //

+    pj_status_t release()

+    {

+	return pj_mutex_unlock(mutex_);

+    }

+

+    //

+    // Try locking the mutex.

+    //

+    pj_status_t tryacquire()

+    {

+	return pj_mutex_trylock(mutex_);

+    }

+

+private:

+    pj_mutex_t *mutex_;

 };

 

 

-class PJ_Semaphore

+//

+// Semaphore

+//

+class Pj_Semaphore : public Pj_Object

 {

 public:

-    static PJ_Semaphore *create( PJ_Pool *pool, const char *name, unsigned initial, unsigned max)

+    //

+    // Construct semaphore

+    //

+    Pj_Semaphore(Pj_Pool *pool, unsigned max,

+                 unsigned initial = 0, const char *name = NULL)

+    : sem_(NULL)

     {

-	return (PJ_Semaphore*) pj_sem_create( pool->pool_(), name, initial, max);

     }

 

+    //

+    // Destructor.

+    //

+    ~Pj_Semaphore()

+    {

+        destroy();

+    }

+

+    //

+    // Create semaphore

+    //

+    pj_status_t create( Pj_Pool *pool, unsigned max,

+                        unsigned initial = 0, const char *name = NULL )

+    {

+        destroy();

+	return pj_sem_create( pool->pool_(), name, initial, max, &sem_);

+    }

+

+    //

+    // Destroy semaphore.

+    //

+    void destroy()

+    {

+        if (sem_) {

+            pj_sem_destroy(sem_);

+            sem_ = NULL;

+        }

+    }

+

+    //

+    // Get pjlib compatible semaphore object.

+    //

     pj_sem_t *pj_sem_t_()

     {

 	return (pj_sem_t*)this;

     }

 

-    pj_status_t destroy()

-    {

-	return pj_sem_destroy(this->pj_sem_t_());

-    }

-

+    //

+    // Wait semaphore.

+    //

     pj_status_t wait()

     {

 	return pj_sem_wait(this->pj_sem_t_());

     }

 

-    pj_status_t lock()

+    //

+    // Wait semaphore.

+    //

+    pj_status_t acquire()

     {

 	return wait();

     }

 

+    //

+    // Try wait semaphore.

+    //

     pj_status_t trywait()

     {

 	return pj_sem_trywait(this->pj_sem_t_());

     }

 

-    pj_status_t trylock()

+    //

+    // Try wait semaphore.

+    //

+    pj_status_t tryacquire()

     {

 	return trywait();

     }

 

+    //

+    // Post semaphore.

+    //

     pj_status_t post()

     {

 	return pj_sem_post(this->pj_sem_t_());

     }

 

-    pj_status_t unlock()

+    //

+    // Post semaphore.

+    //

+    pj_status_t release()

     {

 	return post();

     }

+

+private:

+    pj_sem_t *sem_;

 };

 

 

-class PJ_Event

+//

+// Event object.

+//

+class Pj_Event

 {

 public:

-    static PJ_Event *create( PJ_Pool *pool, const char *name, bool manual_reset, bool initial)

+    //

+    // Construct event object.

+    //

+    Pj_Event( Pj_Pool *pool, bool manual_reset = false,

+              bool initial = false, const char *name = NULL )

+    : event_(NULL)

     {

-	return (PJ_Event*) pj_event_create(pool->pool_(), name, manual_reset, initial);

+        create(pool, manual_reset, initial, name);

     }

 

+    //

+    // Destructor.

+    //

+    ~Pj_Event()

+    {

+        destroy();

+    }

+

+    //

+    // Create event object.

+    //

+    pj_status_t create( Pj_Pool *pool, bool manual_reset = false, 

+                        bool initial = false, const char *name = NULL)

+    {

+        destroy();

+	return pj_event_create(pool->pool_(), name, manual_reset, initial,

+                               &event_);

+    }

+

+    //

+    // Get pjlib compatible event object.

+    //

     pj_event_t *pj_event_t_()

     {

-	return (pj_event_t*)this;

+	return event_;

     }

 

-    pj_status_t destroy()

+    //

+    // Destroy event object.

+    //

+    void destroy()

     {

-	return pj_event_destroy(this->pj_event_t_());

+        if (event_) {

+	    pj_event_destroy(event_);

+            event_ = NULL;

+        }

     }

 

+    //

+    // Wait.

+    //

     pj_status_t wait()

     {

-	return pj_event_wait(this->pj_event_t_());

+	return pj_event_wait(event_);

     }

 

+    //

+    // Try wait.

+    //

     pj_status_t trywait()

     {

-	return pj_event_trywait(this->pj_event_t_());

+	return pj_event_trywait(event_);

     }

 

+    //

+    // Set event state to signalled.

+    //

     pj_status_t set()

     {

 	return pj_event_set(this->pj_event_t_());

     }

 

+    //

+    // Release one waiting thread.

+    //

     pj_status_t pulse()

     {

 	return pj_event_pulse(this->pj_event_t_());

     }

 

+    //

+    // Set a non-signalled.

+    //

     pj_status_t reset()

     {

 	return pj_event_reset(this->pj_event_t_());

     }

+

+private:

+    pj_event_t *event_;

 };

 

-class PJ_OS

+//

+// OS abstraction.

+//

+class Pj_OS_API

 {

 public:

-    static pj_status_t gettimeofday( PJ_Time_Val *tv )

+    //

+    // Get current time.

+    //

+    static pj_status_t gettimeofday( Pj_Time_Val *tv )

     {

 	return pj_gettimeofday(tv);

     }

 

-    static pj_status_t time_decode( const PJ_Time_Val *tv, pj_parsed_time *pt )

+    //

+    // Parse to time of day.

+    //

+    static pj_status_t time_decode( const Pj_Time_Val *tv, 

+                                    pj_parsed_time *pt )

     {

 	return pj_time_decode(tv, pt);

     }

 

-    static pj_status_t time_encode(const pj_parsed_time *pt, PJ_Time_Val *tv)

+    //

+    // Parse from time of day.

+    //

+    static pj_status_t time_encode( const pj_parsed_time *pt, 

+                                    Pj_Time_Val *tv)

     {

 	return pj_time_encode(pt, tv);

     }

 

-    static pj_status_t time_local_to_gmt( PJ_Time_Val *tv )

+    //

+    // Convert to GMT.

+    //

+    static pj_status_t time_local_to_gmt( Pj_Time_Val *tv )

     {

 	return pj_time_local_to_gmt( tv );

     }

 

-    static pj_status_t time_gmt_to_local( PJ_Time_Val *tv) 

+    //

+    // Convert time to local.

+    //

+    static pj_status_t time_gmt_to_local( Pj_Time_Val *tv) 

     {

 	return pj_time_gmt_to_local( tv );

     }

 };

 

-

-inline pj_status_t PJ_Time_Val::gettimeofday()

+//

+// Timeval inlines.

+//

+inline pj_status_t Pj_Time_Val::gettimeofday()

 {

-    return PJ_OS::gettimeofday(this);

+    return Pj_OS_API::gettimeofday(this);

 }

 

-inline pj_parsed_time PJ_Time_Val::decode()

+inline pj_parsed_time Pj_Time_Val::decode()

 {

     pj_parsed_time pt;

-    PJ_OS::time_decode(this, &pt);

+    Pj_OS_API::time_decode(this, &pt);

     return pt;

 }

 

-inline pj_status_t PJ_Time_Val::encode(const pj_parsed_time *pt)

+inline pj_status_t Pj_Time_Val::encode(const pj_parsed_time *pt)

 {

-    return PJ_OS::time_encode(pt, this);

+    return Pj_OS_API::time_encode(pt, this);

 }

 

-inline pj_status_t PJ_Time_Val::to_gmt()

+inline pj_status_t Pj_Time_Val::to_gmt()

 {

-    return PJ_OS::time_local_to_gmt(this);

+    return Pj_OS_API::time_local_to_gmt(this);

 }

 

-inline pj_status_t PJ_Time_Val::to_local()

+inline pj_status_t Pj_Time_Val::to_local()

 {

-    return PJ_OS::time_gmt_to_local(this);

+    return Pj_OS_API::time_gmt_to_local(this);

 }

 

 #endif	/* __PJPP_OS_H__ */

diff --git a/pjlib/include/pj++/pool.hpp b/pjlib/include/pj++/pool.hpp
index d2af77b..611cd7a 100644
--- a/pjlib/include/pj++/pool.hpp
+++ b/pjlib/include/pj++/pool.hpp
@@ -1,86 +1,244 @@
 /* $Id$
- *
  */

 #ifndef __PJPP_POOL_H__

 #define __PJPP_POOL_H__

 

 #include <pj/pool.h>

 

-class PJ_Pool

+class Pj_Pool;

+class Pj_Caching_Pool;

+

+//

+// Base class for all Pjlib objects

+//

+class Pj_Object

 {

 public:

-    const char *getobjname() const

-    {

-	return pj_pool_getobjname(this->pool_());

-    }

+    void *operator new(unsigned int class_size, Pj_Pool *pool);

+    void operator delete(void*);

+    void operator delete(void*, Pj_Pool*);

 

-    pj_pool_t *pool_()

-    {

-	return (pj_pool_t*)this;

-    }

+    //

+    // Inline implementations at the end of this file.

+    //

 

-    const pj_pool_t *pool_() const

-    {

-	return (const pj_pool_t*)this;

-    }

-

-    void release()

-    {

-	pj_pool_release(this->pool_());

-    }

-

-    void reset()

-    {

-	pj_pool_reset(this->pool_());

-    }

-

-    pj_size_t get_capacity()

-    {

-	pj_pool_get_capacity(this->pool_());

-    }

-

-    pj_size_t get_used_size()

-    {

-	pj_pool_get_used_size(this->pool_());

-    }

-

-    void *alloc(pj_size_t size)

-    {

-	return pj_pool_alloc(this->pool_(), size);

-    }

-

-    void *calloc(pj_size_t count, pj_size_t elem)

-    {

-	return pj_pool_calloc(this->pool_(), count, elem);

-    }

+private:

+    // Can not use normal new operator; must use pool.

+    // e.g.:

+    //   obj = new(pool) Pj_The_Object(pool, ...);

+    //

+    void *operator new(unsigned int)

+    {}

 };

 

-class PJ_Caching_Pool

+

+//

+// Pool.

+//

+class Pj_Pool : public Pj_Object

 {

 public:

-    void init(pj_size_t max_capacity,

-	      const pj_pool_factory_policy *pol=&pj_pool_factory_default_policy)

+    //

+    // Default constructor, initializes internal pool to NULL.

+    // Application must call attach() some time later.

+    //

+    Pj_Pool()

+        : p_(NULL)

     {

-	pj_caching_pool_init(&cp_, pol, max_capacity);

     }

 

-    void destroy()

+    //

+    // Create pool.

+    //

+    Pj_Pool(Pj_Caching_Pool &caching_pool,

+            pj_size_t initial_size, 

+            pj_size_t increment_size, 

+            const char *name = NULL, 

+            pj_pool_callback *callback = NULL);

+

+    //

+    // Construct from existing pool.

+    //

+    explicit Pj_Pool(pj_pool_t *pool)

+        : p_(pool)

+    {

+    }

+

+    //

+    // Attach existing pool.

+    //

+    void attach(pj_pool_t *pool)

+    {

+        p_ = pool;

+    }

+

+    //

+    // Destructor.

+    //

+    // Release pool back to factory. Remember: if you delete pool, then 

+    // make sure that all objects that have been allocated from this pool

+    // have been properly destroyed.

+    //

+    // This is where C++ is trickier than plain C!!

+    //

+    ~Pj_Pool()

+    {

+        if (p_)

+	    pj_pool_release(p_);

+    }

+

+    //

+    // Get name.

+    //

+    const char *getobjname() const

+    {

+	return pj_pool_getobjname(p_);

+    }

+

+    //

+    // Get pjlib compatible pool object.

+    //

+    pj_pool_t *pool_()

+    {

+	return p_;

+    }

+

+    //

+    // Get pjlib compatible pool object.

+    //

+    const pj_pool_t *pool_() const

+    {

+	return p_;

+    }

+

+    //

+    // Get pjlib compatible pool object.

+    //

+    pj_pool_t *pj_pool_t_()

+    {

+	return p_;

+    }

+

+    //

+    // Reset pool.

+    //

+    void reset()

+    {

+	pj_pool_reset(p_);

+    }

+

+    //

+    // Get current capacity.

+    //

+    pj_size_t get_capacity()

+    {

+	pj_pool_get_capacity(p_);

+    }

+

+    //

+    // Get current total bytes allocated from the pool.

+    //

+    pj_size_t get_used_size()

+    {

+	pj_pool_get_used_size(p_);

+    }

+

+    //

+    // Allocate.

+    //

+    void *alloc(pj_size_t size)

+    {

+	return pj_pool_alloc(p_, size);

+    }

+

+    //

+    // Allocate elements and zero fill the memory.

+    //

+    void *calloc(pj_size_t count, pj_size_t elem)

+    {

+	return pj_pool_calloc(p_, count, elem);

+    }

+

+    //

+    // Allocate and zero fill memory.

+    //

+    void *zalloc(pj_size_t size)

+    {

+        return pj_pool_zalloc(p_, size);

+    }

+

+private:

+    pj_pool_t *p_;

+};

+

+

+//

+// Caching pool.

+//

+class Pj_Caching_Pool

+{

+public:

+    //

+    // Construct caching pool.

+    //

+    Pj_Caching_Pool( pj_size_t cache_capacity = 0,

+	             const pj_pool_factory_policy *pol=&pj_pool_factory_default_policy)

+    {

+	pj_caching_pool_init(&cp_, pol, cache_capacity);

+    }

+

+    //

+    // Destroy caching pool.

+    //

+    ~Pj_Caching_Pool()

     {

 	pj_caching_pool_destroy(&cp_);

     }

 

-    PJ_Pool *create_pool(const char *name, pj_size_t initial_size, pj_size_t increment_size, pj_pool_callback *callback)

+    //

+    // Create pool.

+    //

+    pj_pool_t *create_pool( pj_size_t initial_size, 

+                            pj_size_t increment_size, 

+                            const char *name = NULL, 

+                            pj_pool_callback *callback = NULL)

     {

-	return (PJ_Pool*) (*cp_.factory.create_pool)(&cp_.factory, name, initial_size, increment_size, callback);

-    }

-

-    void release_pool( PJ_Pool *pool )

-    {

-	pj_pool_release(pool->pool_());

+	return (pj_pool_t*)(*cp_.factory.create_pool)(&cp_.factory, name, 

+                                                     initial_size, 

+                                                     increment_size, 

+                                                     callback);

     }

 

 private:

     pj_caching_pool cp_;

 };

 

+//

+// Inlines for Pj_Object

+//

+inline void *Pj_Object::operator new(unsigned int class_size, Pj_Pool *pool)

+{

+    return pool->alloc(class_size);

+}

+inline void Pj_Object::operator delete(void *ptr)

+{

+}

+inline void Pj_Object::operator delete(void *ptr, Pj_Pool*)

+{

+}

+

+//

+// Inlines for Pj_Pool

+//

+inline Pj_Pool::Pj_Pool( Pj_Caching_Pool &caching_pool,

+                         pj_size_t initial_size, 

+                         pj_size_t increment_size, 

+                         const char *name, 

+                         pj_pool_callback *callback)

+{

+    p_ = caching_pool.create_pool(initial_size, increment_size, name,

+                                  callback);

+}

+

+

 #endif	/* __PJPP_POOL_H__ */

diff --git a/pjlib/include/pj++/proactor.hpp b/pjlib/include/pj++/proactor.hpp
index cae9cf4..7021a5a 100644
--- a/pjlib/include/pj++/proactor.hpp
+++ b/pjlib/include/pj++/proactor.hpp
@@ -1,88 +1,481 @@
 /* $Id$
- *
  */

-#ifndef __PJPP_EVENT_HANDLER_H__

-#define __PJPP_EVENT_HANDLER_H__

+#ifndef __PJPP_PROACTOR_H__

+#define __PJPP_PROACTOR_H__

 

 #include <pj/ioqueue.h>

 #include <pj++/pool.hpp>

 #include <pj++/sock.hpp>

 #include <pj++/timer.hpp>

+#include <pj/errno.h>

 

-class PJ_Proactor;

+class Pj_Proactor;

+class Pj_Event_Handler;

 

 

-class PJ_Event_Handler

+//////////////////////////////////////////////////////////////////////////////

+// Asynchronous operation key.

+//

+// Applications may inheric this class to put their application

+// specific data.

+//

+class Pj_Async_Op : public pj_ioqueue_op_key_t

 {

-    friend class PJ_Proactor;

 public:

-    PJ_Event_Handler();

-    virtual ~PJ_Event_Handler();

+    //

+    // Constructor.

+    //

+    explicit Pj_Async_Op(Pj_Event_Handler *handler)

+        : handler_(handler)

+    {

+        pj_memset(this, 0, sizeof(pj_ioqueue_op_key_t));

+    }

 

-    virtual pj_oshandle_t get_handle() = 0;

+    //

+    // Check whether operation is still pending for this key.

+    //

+    bool is_pending();

 

-    bool read(void *buf, pj_size_t len);

-    bool recvfrom(void *buf, pj_size_t len, PJ_INET_Addr *addr);

-    bool write(const void *data, pj_size_t len);

-    bool sendto(const void *data, pj_size_t len, const PJ_INET_Addr &addr);

+    //

+    // Cancel the operation.

+    //

+    bool cancel(pj_ssize_t bytes_status=-PJ_ECANCELLED);

+

+protected:

+    Pj_Event_Handler *handler_;

+};

+

+

+//////////////////////////////////////////////////////////////////////////////

+// Event handler.

+//

+// Applications should inherit this class to receive various event

+// notifications.

+//

+// Applications should implement get_socket_handle().

+//

+class Pj_Event_Handler : public Pj_Object

+{

+    friend class Pj_Proactor;

+public:

+    //

+    // Default constructor.

+    //

+    Pj_Event_Handler()

+        : key_(NULL)

+    {

+        pj_memset(&timer_, 0, sizeof(timer_));

+        timer_.user_data = this;

+        timer_.cb = &timer_callback;

+    }

+    

+    //

+    // Destroy.

+    //

+    virtual ~Pj_Event_Handler()

+    {

+        unregister();

+    }

+

+    //

+    // Unregister this handler from the ioqueue.

+    //

+    void unregister()

+    {

+        if (key_) {

+            pj_ioqueue_unregister(key_);

+            key_ = NULL;

+        }

+    }

+

+    //

+    // Get socket handle associated with this.

+    //

+    virtual pj_sock_t get_socket_handle()

+    {

+        return PJ_INVALID_SOCKET;

+    }

+

+    //

+    // Receive data.

+    //

+    pj_status_t recv( Pj_Async_Op *op_key, 

+                      void *buf, pj_ssize_t *len, 

+                      unsigned flags)

+    {

+        return pj_ioqueue_recv( key_, op_key,

+                                buf, len, flags);

+    }

+

+    //

+    // Recvfrom()

+    //

+    pj_status_t recvfrom( Pj_Async_Op *op_key, 

+                          void *buf, pj_ssize_t *len, unsigned flags,

+                          Pj_Inet_Addr *addr)

+    {

+        addr->addrlen_ = sizeof(Pj_Inet_Addr);

+        return pj_ioqueue_recvfrom( key_, op_key, buf, len, flags,

+                                    addr, &addr->addrlen_ );

+    }

+

+    //

+    // send()

+    //

+    pj_status_t send( Pj_Async_Op *op_key, 

+                      const void *data, pj_ssize_t *len, 

+                      unsigned flags)

+    {

+        return pj_ioqueue_send( key_, op_key, data, len, flags);

+    }

+

+    //

+    // sendto()

+    //

+    pj_status_t sendto( Pj_Async_Op *op_key,

+                        const void *data, pj_ssize_t *len, unsigned flags,

+                        const Pj_Inet_Addr &addr)

+    {

+        return pj_ioqueue_sendto(key_, op_key, data, len, flags,

+                                 &addr, sizeof(addr));

+    }

+

 #if PJ_HAS_TCP

-    bool connect(const PJ_INET_Addr &addr);

-    bool accept(PJ_Socket *sock, PJ_INET_Addr *local=NULL, PJ_INET_Addr *remote=NULL);

+    //

+    // connect()

+    //

+    pj_status_t connect(const Pj_Inet_Addr &addr)

+    {

+        return pj_ioqueue_connect(key_, &addr, sizeof(addr));

+    }

+

+    //

+    // accept.

+    //

+    pj_status_t accept( Pj_Async_Op *op_key,

+                        Pj_Socket *sock, 

+                        Pj_Inet_Addr *local = NULL, 

+                        Pj_Inet_Addr *remote = NULL)

+    {

+        int *addrlen = local ? &local->addrlen_ : NULL;

+        return pj_ioqueue_accept( key_, op_key, &sock->sock_,

+                                  local, remote, addrlen );

+    }

+

 #endif

 

 protected:

-    //

+    //////////////////

     // Overridables

+    //////////////////

+

     //

-    virtual void on_timeout(int data) {}

-    virtual void on_read_complete(pj_ssize_t bytes_read) {}

-    virtual void on_write_complete(pj_ssize_t bytes_sent) {}

+    // Timeout callback.

+    //

+    virtual void on_timeout(int data) 

+    {

+    }

+

+    //

+    // On read complete callback.

+    //

+    virtual void on_read_complete( Pj_Async_Op *op_key,

+                                   pj_ssize_t bytes_read) 

+    {

+    }

+

+    //

+    // On write complete callback.

+    //

+    virtual void on_write_complete( Pj_Async_Op *op_key, 

+                                    pj_ssize_t bytes_sent) 

+    {

+    }

+

 #if PJ_HAS_TCP

-    virtual void on_connect_complete(int status) {}

-    virtual void on_accept_complete(int status) {}

+    //

+    // On connect complete callback.

+    //

+    virtual void on_connect_complete(pj_status_t status) 

+    {

+    }

+

+    //

+    // On new connection callback.

+    //

+    virtual void on_accept_complete( Pj_Async_Op *op_key,

+                                     pj_sock_t new_sock,

+                                     pj_status_t status) 

+    {

+    }

+

 #endif

 

+

 private:

-    PJ_Proactor	     *proactor_;

     pj_ioqueue_key_t *key_;

     pj_timer_entry    timer_;

-    int		      tmp_recvfrom_addr_len;

 

-public:

-    // Internal IO Queue/timer callback.

-    static void timer_callback( pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry);

-    static void read_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_read);

-    static void write_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent);

-    static void accept_complete_cb(pj_ioqueue_key_t *key, int status);

-    static void connect_complete_cb(pj_ioqueue_key_t *key, int status);

+    friend class Pj_Proactor;

+    friend class Pj_Async_Op;

+

+    //

+    // Static timer callback.

+    //

+    static void timer_callback( pj_timer_heap_t *timer_heap, 

+                                struct pj_timer_entry *entry)

+    {

+        Pj_Event_Handler *handler = 

+            (Pj_Event_Handler*) entry->user_data;

+

+        handler->on_timeout(entry->id);

+    }

 };

 

-class PJ_Proactor

+inline bool Pj_Async_Op::is_pending()

+{

+    return pj_ioqueue_is_pending(handler_->key_, this) != 0;

+}

+

+inline bool Pj_Async_Op::cancel(pj_ssize_t bytes_status)

+{

+    return pj_ioqueue_post_completion(handler_->key_, this, 

+                                      bytes_status) == PJ_SUCCESS;

+}

+

+//////////////////////////////////////////////////////////////////////////////

+// Proactor

+//

+class Pj_Proactor : public Pj_Object

 {

 public:

-    static PJ_Proactor *create(PJ_Pool *pool, pj_size_t max_fd, 

-			       pj_size_t timer_entry_count, unsigned timer_flags=0);

+    //

+    // Default constructor, initializes to NULL.

+    //

+    Pj_Proactor()

+        : ioq_(NULL), th_(NULL)

+    {

+        cb_.on_read_complete    = &read_complete_cb;

+        cb_.on_write_complete   = &write_complete_cb;

+        cb_.on_accept_complete  = &accept_complete_cb;

+        cb_.on_connect_complete = &connect_complete_cb;

+    }

 

-    void destroy();

+    //

+    // Construct proactor.

+    //

+    Pj_Proactor( Pj_Pool *pool, pj_size_t max_fd,

+                 pj_size_t max_timer_entries )

+    : ioq_(NULL), th_(NULL)

+    {

+        cb_.on_read_complete    = &read_complete_cb;

+        cb_.on_write_complete   = &write_complete_cb;

+        cb_.on_accept_complete  = &accept_complete_cb;

+        cb_.on_connect_complete = &connect_complete_cb;

+    }

 

-    bool register_handler(PJ_Pool *pool, PJ_Event_Handler *handler);

-    void unregister_handler(PJ_Event_Handler *handler);

+    //

+    // Destructor.

+    //

+    ~Pj_Proactor()

+    {

+        destroy();

+    }

 

-    static bool schedule_timer( pj_timer_heap_t *timer, PJ_Event_Handler *handler,

-				const PJ_Time_Val &delay, int id=-1);

-    bool schedule_timer(PJ_Event_Handler *handler, const PJ_Time_Val &delay, int id=-1);

-    bool cancel_timer(PJ_Event_Handler *handler);

+    //

+    // Create proactor.

+    //

+    pj_status_t create( Pj_Pool *pool, pj_size_t max_fd, 

+			pj_size_t timer_entry_count)

+    {

+        pj_status_t status;

 

-    bool handle_events(PJ_Time_Val *timeout);

+        destroy();

 

-    pj_ioqueue_t *get_io_queue();

-    pj_timer_heap_t *get_timer_heap();

+        status = pj_ioqueue_create(pool->pool_(), max_fd, &ioq_);

+        if (status != PJ_SUCCESS) 

+            return status;

+        

+        status = pj_timer_heap_create(pool->pool_(), 

+                                      timer_entry_count, &th_);

+        if (status != PJ_SUCCESS) {

+            pj_ioqueue_destroy(ioq_);

+            ioq_ = NULL;

+            return NULL;

+        }

+        

+        status;

+    }

+

+    //

+    // Destroy proactor.

+    //

+    void destroy()

+    {

+        if (ioq_) {

+            pj_ioqueue_destroy(ioq_);

+            ioq_ = NULL;

+        }

+        if (th_) {

+            pj_timer_heap_destroy(th_);

+            th_ = NULL;

+        }

+    }

+

+    //

+    // Register handler.

+    // This will call handler->get_socket_handle()

+    //

+    pj_status_t register_socket_handler(Pj_Pool *pool, 

+                                        Pj_Event_Handler *handler)

+    {

+        return   pj_ioqueue_register_sock( pool->pool_(), ioq_,

+                                           handler->get_socket_handle(),

+                                           handler, &cb_, &handler->key_ );

+    }

+

+    //

+    // Unregister handler.

+    //

+    static void unregister_handler(Pj_Event_Handler *handler)

+    {

+        if (handler->key_) {

+            pj_ioqueue_unregister( handler->key_ );

+            handler->key_ = NULL;

+        }

+    }

+

+    //

+    // Scheduler timer.

+    //

+    bool schedule_timer( Pj_Event_Handler *handler, 

+                         const Pj_Time_Val &delay, 

+                         int id=-1)

+    {

+        return schedule_timer(th_, handler, delay, id);

+    }

+

+    //

+    // Cancel timer.

+    //

+    bool cancel_timer(Pj_Event_Handler *handler)

+    {

+        return pj_timer_heap_cancel(th_, &handler->timer_) == 1;

+    }

+

+    //

+    // Handle events.

+    //

+    int handle_events(Pj_Time_Val *max_timeout)

+    {

+        Pj_Time_Val timeout(0, 0);

+        int timer_count;

+

+        timer_count = pj_timer_heap_poll( th_, &timeout );

+

+        if (timeout.get_sec() < 0) 

+            timeout.sec = PJ_MAXINT32;

+

+        /* If caller specifies maximum time to wait, then compare the value 

+         * with the timeout to wait from timer, and use the minimum value.

+         */

+        if (max_timeout && timeout >= *max_timeout) {

+	    timeout = *max_timeout;

+        }

+

+        /* Poll events in ioqueue. */

+        int ioqueue_count;

+

+        ioqueue_count = pj_ioqueue_poll(ioq_, &timeout);

+        if (ioqueue_count < 0)

+	    return ioqueue_count;

+

+        return ioqueue_count + timer_count;

+    }

+

+    //

+    // Get the internal ioqueue object.

+    //

+    pj_ioqueue_t *get_io_queue()

+    {

+        return ioq_;

+    }

+

+    //

+    // Get the internal timer heap object.

+    //

+    pj_timer_heap_t *get_timer_heap()

+    {

+        return th_;

+    }

 

 private:

     pj_ioqueue_t *ioq_;

     pj_timer_heap_t *th_;

+    pj_ioqueue_callback cb_;

 

-    PJ_Proactor() {}

+    static bool schedule_timer( pj_timer_heap_t *timer, 

+                                Pj_Event_Handler *handler,

+				const Pj_Time_Val &delay, 

+                                int id=-1)

+    {

+        handler->timer_.id = id;

+        return pj_timer_heap_schedule(timer, &handler->timer_, &delay) == 0;

+    }

+

+

+    //

+    // Static read completion callback.

+    //

+    static void read_complete_cb( pj_ioqueue_key_t *key, 

+                                  pj_ioqueue_op_key_t *op_key, 

+                                  pj_ssize_t bytes_read)

+    {

+        Pj_Event_Handler *handler = 

+	    (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);

+

+        handler->on_read_complete((Pj_Async_Op*)op_key, bytes_read);

+    }

+

+    //

+    // Static write completion callback.

+    //

+    static void write_complete_cb(pj_ioqueue_key_t *key, 

+                                  pj_ioqueue_op_key_t *op_key,

+                                  pj_ssize_t bytes_sent)

+    {

+        Pj_Event_Handler *handler = 

+	    (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);

+

+        handler->on_write_complete((Pj_Async_Op*)op_key, bytes_sent);

+    }

+

+    //

+    // Static accept completion callback.

+    //

+    static void accept_complete_cb(pj_ioqueue_key_t *key, 

+                                   pj_ioqueue_op_key_t *op_key,

+                                   pj_sock_t new_sock,

+                                   pj_status_t status)

+    {

+        Pj_Event_Handler *handler = 

+	    (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);

+

+        handler->on_accept_complete((Pj_Async_Op*)op_key, new_sock, status);

+    }

+

+    //

+    // Static connect completion callback.

+    //

+    static void connect_complete_cb(pj_ioqueue_key_t *key, 

+                                    pj_status_t status)

+    {

+        Pj_Event_Handler *handler = 

+	    (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);

+

+        handler->on_connect_complete(status);

+    }

+

 };

 

-#endif	/* __PJPP_EVENT_HANDLER_H__ */

+#endif	/* __PJPP_PROACTOR_H__ */

diff --git a/pjlib/include/pj++/scanner.hpp b/pjlib/include/pj++/scanner.hpp
index 80ac0a8..9ddac09 100644
--- a/pjlib/include/pj++/scanner.hpp
+++ b/pjlib/include/pj++/scanner.hpp
@@ -4,13 +4,13 @@
 #ifndef __PJPP_SCANNER_H__

 #define __PJPP_SCANNER_H__

 

-#include <pj/scanner.h>

+#include <pjlib-util/scanner.h>

 #include <pj++/string.hpp>

 

-class PJ_CharSpec

+class Pj_Char_Spec

 {

 public:

-    PJ_CharSpec() { pj_cs_init(cs__); }

+    Pj_Char_Spec() { pj_cs_init(cs__); }

 

     void set(int c) { pj_cs_set(cs__, c); }

     void add_range(int begin, int end) { pj_cs_add_range(cs__, begin, end); }

@@ -36,10 +36,10 @@
     pj_char_spec cs__;

 };

 

-class PJ_Scanner

+class Pj_Scanner

 {

 public:

-    PJ_Scanner() {}

+    Pj_Scanner() {}

 

     enum

     {

@@ -67,30 +67,30 @@
 

     int peek_char() const

     {

-	return *scanner_.current;

+	return *scanner_.curptr;

     }

 

-    int peek(const PJ_CharSpec *cs, PJ_String *out)

+    int peek(const Pj_Char_Spec *cs, Pj_String *out)

     {

 	return pj_scan_peek(&scanner_,  cs->cs_(), out);

     }

 

-    int peek_n(pj_size_t len, PJ_String *out)

+    int peek_n(pj_size_t len, Pj_String *out)

     {

 	return pj_scan_peek_n(&scanner_, len, out);

     }

 

-    int peek_until(const PJ_CharSpec *cs, PJ_String *out)

+    int peek_until(const Pj_Char_Spec *cs, Pj_String *out)

     {

 	return pj_scan_peek_until(&scanner_, cs->cs_(), out);

     }

 

-    void get(const PJ_CharSpec *cs, PJ_String *out)

+    void get(const Pj_Char_Spec *cs, Pj_String *out)

     {

 	pj_scan_get(&scanner_, cs->cs_(), out);

     }

 

-    void get_n(unsigned N, PJ_String *out)

+    void get_n(unsigned N, Pj_String *out)

     {

 	pj_scan_get_n(&scanner_, N, out);

     }

@@ -100,7 +100,7 @@
 	return pj_scan_get_char(&scanner_);

     }

 

-    void get_quote(int begin_quote, int end_quote, PJ_String *out)

+    void get_quote(int begin_quote, int end_quote, Pj_String *out)

     {

 	pj_scan_get_quote(&scanner_, begin_quote, end_quote, out);

     }

@@ -110,17 +110,17 @@
 	pj_scan_get_newline(&scanner_);

     }

 

-    void get_until(const PJ_CharSpec *cs, PJ_String *out)

+    void get_until(const Pj_Char_Spec *cs, Pj_String *out)

     {

 	pj_scan_get_until(&scanner_, cs->cs_(), out);

     }

 

-    void get_until_ch(int until_ch, PJ_String *out)

+    void get_until_ch(int until_ch, Pj_String *out)

     {

 	pj_scan_get_until_ch(&scanner_, until_ch, out);

     }

 

-    void get_until_chr(const char *spec, PJ_String *out)

+    void get_until_chr(const char *spec, Pj_String *out)

     {

 	pj_scan_get_until_chr(&scanner_, spec, out);

     }

diff --git a/pjlib/include/pj++/sock.hpp b/pjlib/include/pj++/sock.hpp
index a38fd22..1c6c2dd 100644
--- a/pjlib/include/pj++/sock.hpp
+++ b/pjlib/include/pj++/sock.hpp
@@ -1,196 +1,426 @@
 /* $Id$
- *
  */

 #ifndef __PJPP_SOCK_H__

 #define __PJPP_SOCK_H__

 

 #include <pj/sock.h>

+#include <pj/string.h>

 

-class PJ_Addr

+class Pj_Event_Handler;

+

+//

+// Base class for address.

+//

+class Pj_Addr

 {

 };

 

-class PJ_INET_Addr : public pj_sockaddr_in, public PJ_Addr

+//

+// Internet address.

+//

+class Pj_Inet_Addr : public pj_sockaddr_in, public Pj_Addr

 {

 public:

+    //

+    // Get port number.

+    //

     pj_uint16_t get_port_number() const

     {

-	return pj_sockaddr_get_port(this);

+	return pj_sockaddr_in_get_port(this);

     }

 

+    //

+    // Set port number.

+    //

     void set_port_number(pj_uint16_t port)

     {

 	sin_family = PJ_AF_INET;

-	pj_sockaddr_set_port(this, port);

+	pj_sockaddr_in_set_port(this, port);

     }

 

+    //

+    // Get IP address.

+    //

     pj_uint32_t get_ip_address() const

     {

-	return pj_sockaddr_get_addr(this);

+	return pj_sockaddr_in_get_addr(this).s_addr;

     }

 

+    //

+    // Get address string.

+    //

     const char *get_address() const

     {

-	return pj_sockaddr_get_str_addr(this);

+	return pj_inet_ntoa(sin_addr);

     }

 

+    //

+    // Set IP address.

+    //

     void set_ip_address(pj_uint32_t addr)

     {

 	sin_family = PJ_AF_INET;

-	pj_sockaddr_set_addr(this, addr);

+	pj_sockaddr_in_set_addr(this, addr);

     }

 

+    //

+    // Set address.

+    //

     pj_status_t set_address(const pj_str_t *addr)

     {

-	return pj_sockaddr_set_str_addr(this, addr);

+	return pj_sockaddr_in_set_str_addr(this, addr);

     }

 

+    //

+    // Set address.

+    //

     pj_status_t set_address(const char *addr)

     {

-	return pj_sockaddr_set_str_addr2(this, addr);

+        pj_str_t s;

+	return pj_sockaddr_in_set_str_addr(this, pj_cstr(&s, addr));

     }

 

-    int cmp(const PJ_INET_Addr &rhs) const

+    //

+    // Compare for equality.

+    //

+    bool operator==(const Pj_Inet_Addr &rhs) const

     {

-	return pj_sockaddr_cmp(this, &rhs);

+	return sin_family == rhs.sin_family &&

+               sin_addr.s_addr == rhs.sin_addr.s_addr &&

+               sin_port == rhs.sin_port;

     }

 

-    bool operator==(const PJ_INET_Addr &rhs) const

-    {

-	return cmp(rhs) == 0;

-    }

+private:

+    //

+    // Dummy length used in pj_ioqueue_recvfrom() etc

+    //

+    friend class Pj_Event_Handler;

+    friend class Pj_Socket;

+    friend class Pj_Sock_Stream;

+    friend class Pj_Sock_Dgram;

+

+    int addrlen_;

 };

 

-class PJ_Socket

+

+//

+// Socket base class.

+//

+// Note:

+//  socket will not automatically be closed on destructor.

+//

+class Pj_Socket

 {

 public:

-    PJ_Socket() {}

-    PJ_Socket(const PJ_Socket &rhs) : sock_(rhs.sock_) {}

+    //

+    // Default constructor.

+    //

+    Pj_Socket()

+        : sock_(PJ_INVALID_SOCKET) 

+    {

+    }

 

+    //

+    // Initialize from a socket handle.

+    //

+    explicit Pj_Socket(pj_sock_t sock)

+        : sock_(sock)

+    {

+    }

+

+    //

+    // Copy constructor.

+    //

+    Pj_Socket(const Pj_Socket &rhs) 

+        : sock_(rhs.sock_) 

+    {

+    }

+

+    //

+    // Destructor will not close the socket.

+    // You must call close() explicitly.

+    //

+    ~Pj_Socket()

+    {

+    }

+

+    //

+    // Set socket handle.

+    //

     void set_handle(pj_sock_t sock)

     {

 	sock_ = sock;

     }

 

+    //

+    // Get socket handle.

+    //

     pj_sock_t get_handle() const

     {

 	return sock_;

     }

 

+    //

+    // Get socket handle.

+    //

     pj_sock_t& get_handle()

     {

 	return sock_;

     }

 

-    bool socket(int af, int type, int proto, pj_uint32_t flag=0)

+    //

+    // See if the socket is valid.

+    //

+    bool is_valid() const

     {

-	sock_ = pj_sock_socket(af, type, proto, flag);

-	return sock_ != -1;

+        return sock_ != PJ_INVALID_SOCKET;

     }

 

-    bool bind(const PJ_INET_Addr &addr)

+    //

+    // Create the socket.

+    //

+    pj_status_t create(int af, int type, int proto)

     {

-	return pj_sock_bind(sock_, &addr, sizeof(PJ_INET_Addr)) == 0;

+	return pj_sock_socket(af, type, proto, &sock_);

     }

 

-    bool close()

+    //

+    // Bind socket.

+    //

+    pj_status_t bind(const Pj_Inet_Addr &addr)

     {

-	return pj_sock_close(sock_) == 0;

+	return pj_sock_bind(sock_, &addr, sizeof(Pj_Inet_Addr));

     }

 

-    bool getpeername(PJ_INET_Addr *addr)

+    //

+    // Close socket.

+    //

+    pj_status_t close()

     {

-	int namelen;

-	return pj_sock_getpeername(sock_, addr, &namelen) == 0;

+	pj_sock_close(sock_);

     }

 

-    bool getsockname(PJ_INET_Addr *addr)

+    //

+    // Get peer socket name.

+    //

+    pj_status_t getpeername(Pj_Inet_Addr *addr)

     {

-	int namelen;

-	return pj_sock_getsockname(sock_, addr, &namelen) == 0;

+	return pj_sock_getpeername(sock_, addr, &addr->addrlen_);

     }

 

-    bool getsockopt(int level, int optname, void *optval, int *optlen)

+    //

+    // getsockname

+    //

+    pj_status_t getsockname(Pj_Inet_Addr *addr)

     {

-	return pj_sock_getsockopt(sock_, level, optname, optval, optlen) == 0;

+	return pj_sock_getsockname(sock_, addr, &addr->addrlen_);

     }

 

-    bool setsockopt(int level, int optname, const void *optval, int optlen)

+    //

+    // getsockopt.

+    //

+    pj_status_t getsockopt(int level, int optname, 

+                           void *optval, int *optlen)

     {

-	return pj_sock_setsockopt(sock_, level, optname, optval, optlen) == 0;

+	return pj_sock_getsockopt(sock_, level, optname, optval, optlen);

     }

 

-    bool ioctl(long cmd, pj_uint32_t *val)

+    //

+    // setsockopt

+    // 

+    pj_status_t setsockopt(int level, int optname, 

+                           const void *optval, int optlen)

     {

-	return pj_sock_ioctl(sock_, cmd, val) == 0;

+	return pj_sock_setsockopt(sock_, level, optname, optval, optlen);

     }

 

-    int recv(void *buf, int len, int flag = 0)

+    //

+    // receive data.

+    //

+    pj_ssize_t recv(void *buf, pj_size_t len, int flag = 0)

     {

-	return pj_sock_recv(sock_, buf, len, flag);

+        pj_ssize_t bytes = len;

+	if (pj_sock_recv(sock_, buf, &bytes, flag) != PJ_SUCCESS)

+            return -1;

+        return bytes;

     }

 

-    int send(const void *buf, int len, int flag = 0)

+    //

+    // send data.

+    //

+    pj_ssize_t send(const void *buf, pj_ssize_t len, int flag = 0)

     {

-	return pj_sock_send(sock_, buf, len, flag);

+        pj_ssize_t bytes = len;

+	if (pj_sock_send(sock_, buf, &bytes, flag) != PJ_SUCCESS)

+            return -1;

+        return bytes;

+    }

+

+    //

+    // connect.

+    //

+    pj_status_t connect(const Pj_Inet_Addr &addr)

+    {

+	return pj_sock_connect(sock_, &addr, sizeof(Pj_Inet_Addr));

+    }

+

+    //

+    // assignment.

+    //

+    Pj_Socket &operator=(const Pj_Socket &rhs)

+    {

+        sock_ = rhs.sock_;

+        return *this;

     }

 

 protected:

+    friend class Pj_Event_Handler;

     pj_sock_t sock_;

 };

 

+

 #if PJ_HAS_TCP

-class PJ_Sock_Stream : public PJ_Socket

+//

+// Stream socket.

+//

+class Pj_Sock_Stream : public Pj_Socket

 {

 public:

-    PJ_Sock_Stream() {}

-    PJ_Sock_Stream(const PJ_Sock_Stream &rhs) : PJ_Socket(rhs) {}

-    PJ_Sock_Stream &operator=(const PJ_Sock_Stream &rhs) { sock_ = rhs.sock_; return *this; }

-

-    bool listen(int backlog = 5)

+    //

+    // Default constructor.

+    //

+    Pj_Sock_Stream() 

     {

-	return pj_sock_listen(sock_, backlog) == 0;

     }

 

-    bool accept(PJ_Sock_Stream *new_sock, PJ_INET_Addr *addr, int *addrlen)

+    //

+    // Initialize from a socket handle.

+    //

+    explicit Pj_Sock_Stream(pj_sock_t sock)

+        : Pj_Socket(sock)

     {

-	pj_sock_t s = pj_sock_accept(sock_, addr, addrlen);

-	if (s == -1)

-	    return false;

-	new_sock->set_handle(s);

-	return true;

     }

 

-    bool connect(const PJ_INET_Addr &addr)

+    //

+    // Copy constructor.

+    //

+    Pj_Sock_Stream(const Pj_Sock_Stream &rhs) : Pj_Socket(rhs) 

     {

-	return pj_sock_connect(sock_, &addr, sizeof(PJ_INET_Addr)) == 0;

     }

 

-    bool shutdown(int how)

+    //

+    // Assignment.

+    //

+    Pj_Sock_Stream &operator=(const Pj_Sock_Stream &rhs) 

+    { 

+        sock_ = rhs.sock_; 

+        return *this; 

+    }

+

+    //

+    // listen()

+    //

+    pj_status_t listen(int backlog = 5)

     {

-	return pj_sock_shutdown(sock_, how) == 0;

+	return pj_sock_listen(sock_, backlog);

+    }

+

+    //

+    // blocking accept()

+    //

+    Pj_Sock_Stream accept(Pj_Inet_Addr *remote_addr = NULL)

+    {

+        pj_sock_t newsock;

+        int *addrlen = remote_addr ? &remote_addr->addrlen_ : NULL;

+        pj_status_t status;

+        

+        status = pj_sock_accept(sock_, &newsock, remote_addr, addrlen);

+        if (status != PJ_SUCCESS)

+            return Pj_Sock_Stream(-1);

+

+        return Pj_Sock_Stream(newsock);

+    }

+

+    //

+    // shutdown()

+    //

+    pj_status_t shutdown(int how = PJ_SHUT_RDWR)

+    {

+	return pj_sock_shutdown(sock_, how);

     }

 

 };

 #endif

 

-class PJ_Sock_Dgram : public PJ_Socket

+//

+// Datagram socket.

+//

+class Pj_Sock_Dgram : public Pj_Socket

 {

 public:

-    PJ_Sock_Dgram() {}

-    PJ_Sock_Dgram(const PJ_Sock_Dgram &rhs) : PJ_Socket(rhs) {}

-    PJ_Sock_Dgram &operator=(const PJ_Sock_Dgram &rhs) { sock_ = rhs.sock_; return *this; }

-

-    int recvfrom(void *buf, int len, int flag, PJ_INET_Addr *fromaddr)

+    //

+    // Default constructor.

+    //

+    Pj_Sock_Dgram() 

     {

-	int addrlen;

-	return pj_sock_recvfrom(sock_, buf, len, flag, fromaddr, &addrlen);

     }

 

-    int sendto(const void *buf, int len, int flag, const PJ_INET_Addr &addr)

+    //

+    // Initialize from a socket handle.

+    //

+    explicit Pj_Sock_Dgram(pj_sock_t sock)

+        : Pj_Socket(sock)

     {

-	return pj_sock_sendto(sock_, buf, len, flag, &addr, sizeof(PJ_INET_Addr));

+    }

+

+    //

+    // Copy constructor.

+    //

+    Pj_Sock_Dgram(const Pj_Sock_Dgram &rhs) 

+        : Pj_Socket(rhs) 

+    {

+    }

+

+    //

+    // Assignment.

+    //

+    Pj_Sock_Dgram &operator=(const Pj_Sock_Dgram &rhs) 

+    { 

+        Pj_Socket::operator =(rhs);

+        return *this; 

+    }

+

+    //

+    // recvfrom()

+    //

+    pj_ssize_t recvfrom( void *buf, pj_size_t len, int flag = 0, 

+                         Pj_Inet_Addr *fromaddr = NULL)

+    {

+        pj_ssize_t bytes = len;

+        int *addrlen = fromaddr ? &fromaddr->addrlen_ : NULL;

+	if (pj_sock_recvfrom( sock_, buf, &bytes, flag, 

+                              fromaddr, addrlen) != PJ_SUCCESS)

+        {

+            return -1;

+        }

+        return bytes;

+    }

+

+    //

+    // sendto()

+    //

+    pj_ssize_t sendto( const void *buf, pj_size_t len, int flag, 

+                       const Pj_Inet_Addr &addr)

+    {

+        pj_ssize_t bytes = len;

+	if (pj_sock_sendto( sock_, buf, &bytes, flag, 

+                            &addr, sizeof(pj_sockaddr_in)) != PJ_SUCCESS)

+        {

+            return -1;

+        }

+        return bytes;

     }

 };

 

+

 #endif	/* __PJPP_SOCK_H__ */

diff --git a/pjlib/include/pj++/string.hpp b/pjlib/include/pj++/string.hpp
index d55e737..456e1ff 100644
--- a/pjlib/include/pj++/string.hpp
+++ b/pjlib/include/pj++/string.hpp
@@ -1,249 +1,408 @@
 /* $Id$
- *
  */

 #ifndef __PJPP_STRING_H__

 #define __PJPP_STRING_H__

 

 #include <pj/string.h>

 #include <pj++/pool.hpp>

+#include <pj/assert.h>

 

-class PJ_String : public pj_str_t

+//

+// String wrapper class for pj_str_t.

+//

+class Pj_String : public pj_str_t

 {

 public:

-    PJ_String() 

+    //

+    // Default constructor.

+    //

+    Pj_String() 

     { 

-	pj_assert(sizeof(PJ_String) == sizeof(pj_str_t));

-	ptr=NULL; slen=0; 

+	pj_assert(sizeof(Pj_String) == sizeof(pj_str_t));

+	ptr=NULL; 

+        slen=0; 

     }

 

-    explicit PJ_String(char *str) 

+    //

+    // Construct the buffer from a char*.

+    //

+    explicit Pj_String(char *str) 

     { 

 	set(str);

     }

 

-    PJ_String(PJ_Pool *pool, const char *src)

+    //

+    // Construct from a const char*.

+    //

+    Pj_String(Pj_Pool *pool, const char *src)

     {

 	set(pool, src);

     }

 

-    explicit PJ_String(pj_str_t *s)

+    //

+    // Construct from pj_str_t*.

+    //

+    explicit Pj_String(pj_str_t *s)

     {

 	set(s);

     }

 

-    PJ_String(PJ_Pool *pool, const pj_str_t *s)

+    //

+    // Construct by copying from const pj_str_t*.

+    //

+    Pj_String(Pj_Pool *pool, const pj_str_t *s)

     {

 	set(pool, s);

     }

 

-    explicit PJ_String(PJ_String &rhs)

+    //

+    // Construct from another Pj_String

+    //

+    explicit Pj_String(Pj_String &rhs)

     {

 	set(rhs);

     }

 

-    PJ_String(PJ_Pool *pool, const PJ_String &rhs)

+    //

+    // Construct by copying from Pj_String

+    //

+    Pj_String(Pj_Pool *pool, const Pj_String &rhs)

     {

 	set(pool, rhs);

     }

 

-    PJ_String(char *str, pj_size_t len)

+    //

+    // Construct from a char* and a length.

+    //

+    Pj_String(char *str, pj_size_t len)

     {

 	set(str, len);

     }

 

-    PJ_String(char *begin, char *end)

+    //

+    // Construct from pair of pointer.

+    //

+    Pj_String(char *begin, char *end)

     {

 	pj_strset3(this, begin, end);

     }

 

+    //

+    // Get the length of the string.

+    //

     pj_size_t length() const

     {

 	return pj_strlen(this);

     }

 

+    //

+    // Get the length of the string.

+    //

     pj_size_t size() const

     {

 	return length();

     }

 

+    //

+    // Get the string buffer.

+    //

     const char *buf() const

     {

 	return ptr;

     }

 

+    //

+    // Initialize buffer from char*.

+    //

     void set(char *str)

     {

 	pj_strset2(this, str);

     }

 

-    void set(PJ_Pool *pool, const char *s)

+    //

+    // Initialize by copying from a const char*.

+    //

+    void set(Pj_Pool *pool, const char *s)

     {

 	pj_strdup2(pool->pool_(), this, s);

     }

 

+    //

+    // Initialize from pj_str_t*.

+    //

     void set(pj_str_t *s)

     {

 	pj_strassign(this, s);

     }

 

-    void set(PJ_Pool *pool, const pj_str_t *s)

+    //

+    // Initialize by copying from const pj_str_t*.

+    //

+    void set(Pj_Pool *pool, const pj_str_t *s)

     {

 	pj_strdup(pool->pool_(), this, s);

     }

 

+    //

+    // Initialize from char* and length.

+    //

     void set(char *str, pj_size_t len)

     {

 	pj_strset(this, str, len);

     }

 

+    //

+    // Initialize from pair of pointers.

+    //

     void set(char *begin, char *end)

     {

 	pj_strset3(this, begin, end);

     }

 

-    void set(PJ_String &rhs)

+    //

+    // Initialize from other Pj_String.

+    //

+    void set(Pj_String &rhs)

     {

 	pj_strassign(this, &rhs);

     }

 

-    void set(PJ_Pool *pool, const PJ_String *s)

+    //

+    // Initialize by copying from a Pj_String*.

+    //

+    void set(Pj_Pool *pool, const Pj_String *s)

     {

 	pj_strdup(pool->pool_(), this, s);

     }

 

-    void set(PJ_Pool *pool, const PJ_String &s)

+    //

+    // Initialize by copying from other Pj_String.

+    //

+    void set(Pj_Pool *pool, const Pj_String &s)

     {

 	pj_strdup(pool->pool_(), this, &s);

     }

 

+    //

+    // Copy the contents of other string.

+    //

     void strcpy(const pj_str_t *s)

     {

 	pj_strcpy(this, s);

     }

 

-    void strcpy(const PJ_String &rhs)

+    //

+    // Copy the contents of other string.

+    //

+    void strcpy(const Pj_String &rhs)

     {

 	pj_strcpy(this, &rhs);

     }

 

+    //

+    // Copy the contents of other string.

+    //

     void strcpy(const char *s)

     {

 	pj_strcpy2(this, s);

     }

 

+    //

+    // Compare string.

+    //

     int strcmp(const char *s) const

     {

 	return pj_strcmp2(this, s);

     }

 

+    //

+    // Compare string.

+    //

     int strcmp(const pj_str_t *s) const

     {

 	return pj_strcmp(this, s);

     }

 

-    int strcmp(const PJ_String &rhs) const

+    //

+    // Compare string.

+    //

+    int strcmp(const Pj_String &rhs) const

     {

 	return pj_strcmp(this, &rhs);

     }

 

+    //

+    // Compare string.

+    //

     int strncmp(const char *s, pj_size_t len) const

     {

 	return pj_strncmp2(this, s, len);

     }

 

+    //

+    // Compare string.

+    //

     int strncmp(const pj_str_t *s, pj_size_t len) const

     {

 	return pj_strncmp(this, s, len);

     }

 

-    int strncmp(const PJ_String &rhs, pj_size_t len) const

+    //

+    // Compare string.

+    //

+    int strncmp(const Pj_String &rhs, pj_size_t len) const

     {

 	return pj_strncmp(this, &rhs, len);

     }

 

+    //

+    // Compare string.

+    //

     int stricmp(const char *s) const

     {

 	return pj_stricmp2(this, s);

     }

 

+    //

+    // Compare string.

+    //

     int stricmp(const pj_str_t *s) const

     {

 	return pj_stricmp(this, s);

     }

 

-    int stricmp(const PJ_String &rhs) const

+    //

+    // Compare string.

+    //

+    int stricmp(const Pj_String &rhs) const

     {

 	return stricmp(&rhs);

     }

 

+    //

+    // Compare string.

+    //

     int strnicmp(const char *s, pj_size_t len) const

     {

 	return pj_strnicmp2(this, s, len);

     }

 

+    //

+    // Compare string.

+    //

     int strnicmp(const pj_str_t *s, pj_size_t len) const

     {

 	return pj_strnicmp(this, s, len);

     }

 

-    int strnicmp(const PJ_String &rhs, pj_size_t len) const

+    //

+    // Compare string.

+    //

+    int strnicmp(const Pj_String &rhs, pj_size_t len) const

     {

 	return strnicmp(&rhs, len);

     }

 

+    //

+    // Compare contents for equality.

+    //

     bool operator==(const char *s) const

     {

 	return strcmp(s) == 0;

     }

 

+    //

+    // Compare contents for equality.

+    //

     bool operator==(const pj_str_t *s) const

     {

 	return strcmp(s) == 0;

     }

 

-    bool operator==(const PJ_String &rhs) const

+    //

+    // Compare contents for equality.

+    //

+    bool operator==(const Pj_String &rhs) const

     {

 	return pj_strcmp(this, &rhs) == 0;

     }

 

+    //

+    // Find a character in the string.

+    //

     char *strchr(int chr)

     {

 	return pj_strchr(this, chr);

     }

 

+    //

+    // Find a character in the string.

+    //

     char *find(int chr)

     {

 	return strchr(chr);

     }

 

-    void strcat(const PJ_String &rhs)

+    //

+    // Concatenate string.

+    //

+    void strcat(const Pj_String &rhs)

     {

 	pj_strcat(this, &rhs);

     }

 

+    //

+    // Left trim.

+    //

     void ltrim()

     {

 	pj_strltrim(this);

     }

 

+    //

+    // Right trim.

+    //

     void rtrim()

     {

 	pj_strrtrim(this);

     }

 

+    //

+    // Left and right trim.

+    //

     void trim()

     {

 	pj_strtrim(this);

     }

 

-    unsigned long toul() const

+    //

+    // Convert to unsigned long.

+    //

+    unsigned long to_ulong() const

     {

 	return pj_strtoul(this);

     }

 

+    //

+    // Convert from unsigned long.

+    //

+    void from_ulong(unsigned long value)

+    {

+        slen = pj_utoa(value, ptr);

+    }

+

+    //

+    // Convert from unsigned long with padding.

+    //

+    void from_ulong_with_pad(unsigned long value, int min_dig=0, int pad=' ')

+    {

+        slen = pj_utoa_pad(value, ptr, min_dig, pad);

+    }

+

+

 private:

-    //PJ_String(const PJ_String &rhs) {}

-    void operator=(const PJ_String &rhs) { pj_assert(false); }

+    //Pj_String(const Pj_String &rhs) {}

+    void operator=(const Pj_String &rhs) { pj_assert(false); }

 };

 

 #endif	/* __PJPP_STRING_H__ */

diff --git a/pjlib/include/pj++/timer.hpp b/pjlib/include/pj++/timer.hpp
index 8357a19..b107042 100644
--- a/pjlib/include/pj++/timer.hpp
+++ b/pjlib/include/pj++/timer.hpp
@@ -1,101 +1,174 @@
 /* $Id$
- *
  */

 #ifndef __PJPP_TIMER_H__

 #define __PJPP_TIMER_H__

 

 #include <pj/timer.h>

 #include <pj++/types.hpp>

+#include <pj/assert.h>

+#include <pj++/lock.hpp>

 

-class PJ_Timer_Heap;

+class Pj_Timer_Heap;

 

-class PJ_Timer_Entry : private pj_timer_entry

+//////////////////////////////////////////////////////////////////////////////

+// Timer entry.

+//

+// How to use:

+//  Derive class from Pj_Timer_Entry and override on_timeout().

+//  Scheduler timer in Pj_Timer_Heap.

+//

+class Pj_Timer_Entry : public Pj_Object

 {

-    friend class PJ_Timer_Heap;

+    friend class Pj_Timer_Heap;

 

 public:

-    static void timer_heap_callback(pj_timer_heap_t *, pj_timer_entry *);

-

-    PJ_Timer_Entry() { cb = &timer_heap_callback; }

-    PJ_Timer_Entry(int arg_id, void *arg_user_data)

-    {

-	cb = &timer_heap_callback; 

-	init(arg_id, arg_user_data);

+    //

+    // Default constructor.

+    //

+    Pj_Timer_Entry() 

+    { 

+        entry_.user_data = this;

+        entry_.cb = &timer_heap_callback; 

     }

 

-    virtual void on_timeout() = 0;

-

-    void init(int arg_id, void *arg_user_data)

+    //

+    // Destructor, do nothing.

+    //

+    ~Pj_Timer_Entry()

     {

-	id = arg_id;

-	user_data = arg_user_data;

     }

 

-    int get_id() const

+    //

+    // Override this to get the timeout notification.

+    //

+    virtual void on_timeout(int id) = 0;

+

+private:

+    pj_timer_entry entry_;

+

+    static void timer_heap_callback(pj_timer_heap_t *th, pj_timer_entry *e)

     {

-	return id;

+        Pj_Timer_Entry *entry = (Pj_Timer_Entry*) e->user_data;

+        entry->on_timeout(e->id);

     }

 

-    void set_id(int arg_id)

-    {

-	id = arg_id;

-    }

-

-    void set_user_data(void *arg_user_data)

-    {

-	user_data = arg_user_data;

-    }

-

-    void *get_user_data() const

-    {

-	return user_data;

-    }

-

-    const PJ_Time_Val &get_timeout() const

-    {

-	pj_assert(sizeof(PJ_Time_Val) == sizeof(pj_time_val));

-	return (PJ_Time_Val&)_timer_value;

-    }

 };

 

-class PJ_Timer_Heap

+//////////////////////////////////////////////////////////////////////////////

+// Timer heap.

+//

+class Pj_Timer_Heap : public Pj_Object

 {

 public:

-    PJ_Timer_Heap() {}

-

-    bool create(PJ_Pool *pool, pj_size_t initial_count, 

-		unsigned flag = PJ_TIMER_HEAP_SYNCHRONIZE)

+    //

+    // Default constructor.

+    //

+    Pj_Timer_Heap() 

+        : ht_(NULL) 

     {

-	ht_ = pj_timer_heap_create(pool->pool_(), initial_count, flag);

-	return ht_ != NULL;

     }

 

+    //

+    // Construct timer heap.

+    //

+    Pj_Timer_Heap(Pj_Pool *pool, pj_size_t initial_count)

+        : ht_(NULL)

+    {

+        create(pool, initial_count);

+    }

+

+    //

+    // Destructor.

+    //

+    ~Pj_Timer_Heap()

+    {

+        destroy();

+    }

+

+    //

+    // Create

+    // 

+    pj_status_t create(Pj_Pool *pool, pj_size_t initial_count)

+    {

+        destroy();

+	return pj_timer_heap_create(pool->pool_(), initial_count, &ht_);

+    }

+

+    //

+    // Destroy

+    //

+    void destroy()

+    {

+        if (ht_) {

+            pj_timer_heap_destroy(ht_);

+            ht_ = NULL;

+        }

+    }

+

+    //

+    // Get pjlib compatible timer heap object.

+    //

     pj_timer_heap_t *get_timer_heap()

     {

 	return ht_;

     }

 

-    bool schedule( PJ_Timer_Entry *ent, const PJ_Time_Val &delay)

+    //

+    // Set the lock object.

+    //

+    void set_lock( Pj_Lock *lock, bool auto_delete )

     {

-	return pj_timer_heap_schedule(ht_, ent, &delay) == 0;

+        pj_timer_heap_set_lock( ht_, lock->pj_lock_t_(), auto_delete);

     }

 

-    bool cancel(PJ_Timer_Entry *ent)

+    //

+    // Set maximum number of timed out entries to be processed per poll.

+    //

+    unsigned set_max_timed_out_per_poll(unsigned count)

     {

-	return pj_timer_heap_cancel(ht_, ent) == 1;

+        return pj_timer_heap_set_max_timed_out_per_poll(ht_, count);

     }

 

+    //

+    // Schedule a timer.

+    //

+    bool schedule( Pj_Timer_Entry *ent, const Pj_Time_Val &delay,

+                   int id)

+    {

+        ent->entry_.id = id;

+	return pj_timer_heap_schedule(ht_, &ent->entry_, &delay) == 0;

+    }

+

+    //

+    // Cancel a timer.

+    //

+    bool cancel(Pj_Timer_Entry *ent)

+    {

+	return pj_timer_heap_cancel(ht_, &ent->entry_) == 1;

+    }

+

+    //

+    // Get current number of timers

+    //

     pj_size_t count()

     {

 	return pj_timer_heap_count(ht_);

     }

 

-    void earliest_time(PJ_Time_Val *t)

+    //

+    // Get the earliest time.

+    // Return false if no timer is found.

+    //

+    bool earliest_time(Pj_Time_Val *t)

     {

-	pj_timer_heap_earliest_time(ht_, t);

+	return pj_timer_heap_earliest_time(ht_, t) == PJ_SUCCESS;

     }

 

-    int poll(PJ_Time_Val *next_delay = NULL)

+    //

+    // Poll the timer.

+    // Return number of timed out entries has been called.

+    //

+    unsigned poll(Pj_Time_Val *next_delay = NULL)

     {

 	return pj_timer_heap_poll(ht_, next_delay);

     }

diff --git a/pjlib/include/pj++/tree.hpp b/pjlib/include/pj++/tree.hpp
index db5e8d2..7d30c67 100644
--- a/pjlib/include/pj++/tree.hpp
+++ b/pjlib/include/pj++/tree.hpp
@@ -6,6 +6,9 @@
 

 #include <pj/rbtree.h>

 

+//

+// Tree.

+//

 class PJ_Tree

 {

 public:

diff --git a/pjlib/include/pj++/types.hpp b/pjlib/include/pj++/types.hpp
index efa7439..637c122 100644
--- a/pjlib/include/pj++/types.hpp
+++ b/pjlib/include/pj++/types.hpp
@@ -6,55 +6,138 @@
 

 #include <pj/types.h>

 

-class PJ_Pool;

-class PJ_Socket;

+class Pj_Pool;

+class Pj_Socket ;

+class Pj_Lock;

 

 

-class PJ_Time_Val : public pj_time_val

+//

+// PJLIB initializer.

+//

+class Pjlib

 {

 public:

-    PJ_Time_Val() {}

-    PJ_Time_Val(const PJ_Time_Val &rhs) { sec=rhs.sec; msec=rhs.msec; }

-    explicit PJ_Time_Val(const pj_time_val &tv) { sec = tv.sec; msec = tv.msec; }

+    Pjlib()

+    {

+        pj_init();

+    }

+};

 

-    long get_sec()  const    { return sec; }

-    long get_msec() const    { return msec; }

-    void set_sec (long s)    { sec = s; }

-    void set_msec(long ms)   { msec = ms; normalize(); }

-    long to_msec() const { return PJ_TIME_VAL_MSEC((*this)); }

+//

+// Class Pj_Object is declared in pool.hpp

+//

 

-    bool operator == (const PJ_Time_Val &rhs) const { return PJ_TIME_VAL_EQ((*this), rhs);  }

-    bool operator >  (const PJ_Time_Val &rhs) const { return PJ_TIME_VAL_GT((*this), rhs);  }

-    bool operator >= (const PJ_Time_Val &rhs) const { return PJ_TIME_VAL_GTE((*this), rhs); }

-    bool operator <  (const PJ_Time_Val &rhs) const { return PJ_TIME_VAL_LT((*this), rhs);  }

-    bool operator <= (const PJ_Time_Val &rhs) const { return PJ_TIME_VAL_LTE((*this), rhs); }

+//

+// Time value wrapper.

+//

+class Pj_Time_Val : public pj_time_val

+{

+public:

+    Pj_Time_Val()

+    {

+    }

 

-    PJ_Time_Val & operator = (const PJ_Time_Val &rhs) {

+    Pj_Time_Val(long init_sec, long init_msec)

+    {

+        sec = init_sec;

+        msec = init_msec;

+    }

+

+    Pj_Time_Val(const Pj_Time_Val &rhs) 

+    { 

+        sec=rhs.sec; 

+        msec=rhs.msec; 

+    }

+

+    explicit Pj_Time_Val(const pj_time_val &tv) 

+    { 

+        sec = tv.sec; 

+        msec = tv.msec; 

+    }

+

+    long get_sec()  const    

+    { 

+        return sec; 

+    }

+

+    long get_msec() const    

+    { 

+        return msec; 

+    }

+

+    void set_sec (long s)    

+    { 

+        sec = s; 

+    }

+

+    void set_msec(long ms)   

+    { 

+        msec = ms; 

+        normalize(); 

+    }

+

+    long to_msec() const 

+    { 

+        return PJ_TIME_VAL_MSEC((*this)); 

+    }

+

+    bool operator == (const Pj_Time_Val &rhs) const 

+    { 

+        return PJ_TIME_VAL_EQ((*this), rhs);  

+    }

+

+    bool operator >  (const Pj_Time_Val &rhs) const 

+    { 

+        return PJ_TIME_VAL_GT((*this), rhs);  

+    }

+

+    bool operator >= (const Pj_Time_Val &rhs) const 

+    { 

+        return PJ_TIME_VAL_GTE((*this), rhs); 

+    }

+

+    bool operator <  (const Pj_Time_Val &rhs) const 

+    { 

+        return PJ_TIME_VAL_LT((*this), rhs);  

+    }

+

+    bool operator <= (const Pj_Time_Val &rhs) const 

+    { 

+        return PJ_TIME_VAL_LTE((*this), rhs); 

+    }

+

+    Pj_Time_Val & operator = (const Pj_Time_Val &rhs) 

+    {

 	sec = rhs.sec;

 	msec = rhs.msec;

 	return *this;

     }

  

-    PJ_Time_Val & operator += (const PJ_Time_Val &rhs) {

+    Pj_Time_Val & operator += (const Pj_Time_Val &rhs) 

+    {

 	PJ_TIME_VAL_ADD((*this), rhs);

 	return *this;

     }

 

-    PJ_Time_Val & operator -= (const PJ_Time_Val &rhs) {

+    Pj_Time_Val & operator -= (const Pj_Time_Val &rhs) 

+    {

 	PJ_TIME_VAL_SUB((*this), rhs);

 	return *this;

     }

 

     /* Must include os.hpp to use these, otherwise unresolved in linking */

-    pj_status_t	   gettimeofday();

-    pj_parsed_time decode();

-    pj_status_t    encode(const pj_parsed_time *pt);

-    pj_status_t    to_gmt();

-    pj_status_t    to_local();

+    inline pj_status_t	   gettimeofday();

+    inline pj_parsed_time  decode();

+    inline pj_status_t     encode(const pj_parsed_time *pt);

+    inline pj_status_t     to_gmt();

+    inline pj_status_t     to_local();

 

 

 private:

-    void normalize() { pj_time_val_normalize(this); }

+    void normalize() 

+    { 

+        pj_time_val_normalize(this); 

+    }

 

 };

 

diff --git a/pjlib/include/pj/errno.h b/pjlib/include/pj/errno.h
index 11fab3e..e7b3ab9 100644
--- a/pjlib/include/pj/errno.h
+++ b/pjlib/include/pj/errno.h
@@ -210,6 +210,11 @@
  * Invalid operation.
  */
 #define PJ_EINVALIDOP	    (PJ_ERRNO_START_STATUS + 13)
+/**

+ * @hideinitializer

+ * Operation is cancelled.

+ */

+#define PJ_ECANCELLED	    (PJ_ERRNO_START_STATUS + 14)

 
 /** @} */   /* pj_errnum */
 
diff --git a/pjlib/include/pj/ioqueue.h b/pjlib/include/pj/ioqueue.h
index 1ecec1b..c44b7ce 100644
--- a/pjlib/include/pj/ioqueue.h
+++ b/pjlib/include/pj/ioqueue.h
@@ -297,14 +297,19 @@
 
 /**
  * Unregister from the I/O Queue framework. Caller must make sure that
- * the key doesn't have any pending operation before calling this function,
- * or otherwise the behaviour is undefined (either callback will be called
- * later when the data is sent/received, or the callback will not be called,
- * or even something else).
+ * the key doesn't have any pending operations before calling this function,
+ * by calling #pj_ioqueue_is_pending() for all previously submitted

+ * operations except asynchronous connect, and if necessary call

+ * #pj_ioqueue_post_completion() to cancel the pending operations.

+ *

+ * Note that asynchronous connect operation will automatically be 

+ * cancelled during the unregistration.
  *
  * @param key	    The key that was previously obtained from registration.
  *
- * @return          PJ_SUCCESS on success or the error code.
+ * @return          PJ_SUCCESS on success or the error code.

+ *

+ * @see pj_ioqueue_is_pending
  */
 PJ_DECL(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key );
 
@@ -334,6 +339,41 @@
                                                void *user_data,
                                                void **old_data);
 
+

+/**

+ * Check if operation is pending on the specified operation key.

+ * The \c op_key must have been submitted as pending operation before,

+ * or otherwise the result is undefined.

+ *

+ * @param key       The key.

+ * @param op_key    The operation key, previously submitted to any of

+ *                  the I/O functions and has returned PJ_EPENDING.

+ *

+ * @return          Non-zero if operation is still pending.

+ */

+PJ_DECL(pj_bool_t) pj_ioqueue_is_pending( pj_ioqueue_key_t *key,

+                                          pj_ioqueue_op_key_t *op_key );

+

+

+/**

+ * Post completion status to the specified operation key and call the

+ * appropriate callback. When the callback is called, the number of bytes 

+ * received in read/write callback or the status in accept/connect callback

+ * will be set from the \c bytes_status parameter.

+ *

+ * @param key           The key.

+ * @param op_key        Pending operation key.

+ * @param bytes_status  Number of bytes or status to be set. A good value

+ *                      to put here is -PJ_ECANCELLED.

+ *

+ * @return              PJ_SUCCESS if completion status has been successfully

+ *                      sent.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key,

+                                                 pj_ioqueue_op_key_t *op_key,

+                                                 pj_ssize_t bytes_status );

+

+

 
 #if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0
 /**
diff --git a/pjlib/include/pj/os.h b/pjlib/include/pj/os.h
index 536992f..a1fef6b 100644
--- a/pjlib/include/pj/os.h
+++ b/pjlib/include/pj/os.h
@@ -324,12 +324,30 @@
  */
 PJ_DECL(void) pj_atomic_inc(pj_atomic_t *atomic_var);
 
+/**

+ * Increment the value of an atomic type and get the result.

+ *

+ * @param atomic_var	the atomic variable.

+ *

+ * @return              The incremented value.

+ */

+PJ_DECL(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var);

+

 /**
  * Decrement the value of an atomic type.
  *
  * @param atomic_var	the atomic variable.
  */
 PJ_DECL(void) pj_atomic_dec(pj_atomic_t *atomic_var);
+

+/**

+ * Decrement the value of an atomic type and get the result.

+ *

+ * @param atomic_var	the atomic variable.

+ *

+ * @return              The decremented value.

+ */

+PJ_DECL(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var);

 
 /**
  * Add a value to an atomic type.
@@ -339,6 +357,17 @@
  */
 PJ_DECL(void) pj_atomic_add( pj_atomic_t *atomic_var,
 			     pj_atomic_value_t value);
+

+/**

+ * Add a value to an atomic type and get the result.

+ *

+ * @param atomic_var	The atomic variable.

+ * @param value		Value to be added.

+ *

+ * @return              The result after the addition.

+ */

+PJ_DECL(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var,

+			                          pj_atomic_value_t value);

 
 /**
  * @}
diff --git a/pjlib/include/pj/timer.h b/pjlib/include/pj/timer.h
index 3f1402a..e8772f2 100644
--- a/pjlib/include/pj/timer.h
+++ b/pjlib/include/pj/timer.h
@@ -110,18 +110,6 @@
 
 
 /**
- * Default flag for timer heap, indicates that synchronization will be
- * used.
- */
-#define PJ_TIMER_HEAP_SYNCHRONIZE	(0)
-
-/**
- * Flag to indicate that thread synchronization is NOT needed for the 
- * timer heap.
- */
-#define PJ_TIMER_HEAP_NO_SYNCHRONIZE	(1)
-
-/**
  * Calculate memory size required to create a timer heap.
  *
  * @param count     Number of timer entries to be supported.
@@ -140,16 +128,45 @@
  * @param count     The maximum number of timer entries to be supported 
  *                  initially. If the application registers more entries 
  *                  during runtime, then the timer heap will resize.
- * @param flag      Creation flag, currently only PJ_TIMER_HEAP_NO_SYNCHRONIZE
- *                  is recognized..
  * @param ht        Pointer to receive the created timer heap.
  *
  * @return          PJ_SUCCESS, or the appropriate error code.
  */
 PJ_DECL(pj_status_t) pj_timer_heap_create( pj_pool_t *pool,
 					   pj_size_t count,
-					   unsigned flag,
                                            pj_timer_heap_t **ht);
+

+/**

+ * Destroy the timer heap.

+ *

+ * @param ht        The timer heap.

+ */

+PJ_DECL(void) pj_timer_heap_destroy( pj_timer_heap_t *ht );

+

+

+/**

+ * Set lock object to be used by the timer heap. By default, the timer heap

+ * uses dummy synchronization.

+ *

+ * @param ht        The timer heap.

+ * @param lock      The lock object to be used for synchronization.

+ * @param auto_del  If nonzero, the lock object will be destroyed when

+ *                  the timer heap is destroyed.

+ */

+PJ_DECL(void) pj_timer_heap_set_lock( pj_timer_heap_t *ht,

+                                      pj_lock_t *lock,

+                                      pj_bool_t auto_del );

+

+/**

+ * Set maximum number of timed out entries to process in a single poll.

+ *

+ * @param ht        The timer heap.

+ * @param count     Number of entries.

+ *

+ * @return          The old number.

+ */

+PJ_DECL(unsigned) pj_timer_heap_set_max_timed_out_per_poll(pj_timer_heap_t *ht,

+                                                           unsigned count );

 
 /**
  * Initialize a timer entry. Application should call this function at least
@@ -215,19 +232,21 @@
  * @return          PJ_SUCCESS, or PJ_ENOTFOUND if no entry is scheduled.
  */
 PJ_DECL(pj_status_t) pj_timer_heap_earliest_time( pj_timer_heap_t *ht, 
-					   pj_time_val *timeval);
+					          pj_time_val *timeval);
 
 /**
  * Poll the timer heap, check for expired timers and call the callback for
  * each of the expired timers.
  *
- * @param ht        The timer heap.
+ * @param ht         The timer heap.
  * @param next_delay If this parameter is not NULL, it will be filled up with
  *		     the time delay until the next timer elapsed, or -1 in
- *		     the sec part if no entry exist.
- * @return          The number of timers expired.
+ *		     the sec part if no entry exist.

+ *
+ * @return           The number of timers expired.
  */
-PJ_DECL(int) pj_timer_heap_poll( pj_timer_heap_t *ht, pj_time_val *next_delay);
+PJ_DECL(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht, 

+                                      pj_time_val *next_delay);
 
 /**
  * @}
diff --git a/pjlib/src/pj++/compiletest.cpp b/pjlib/src/pj++/compiletest.cpp
deleted file mode 100644
index 5bc4f8b..0000000
--- a/pjlib/src/pj++/compiletest.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/* $Id$
- *
- */

-#include <pjlib++.hpp>

-

-

-#if 0

-struct MyNode

-{

-    PJ_DECL_LIST_MEMBER(struct MyNode)

-    int data;

-};

-

-int test()

-{

-    typedef PJ_List<MyNode> MyList;

-    MyList list;

-    MyList::iterator it, end = list.end();

-

-    for (it=list.begin(); it!=end; ++it) {

-	MyNode *n = *it;

-    }

-

-    return 0;

-}

-

-int test_scan()

-{

-    PJ_Scanner scan;

-    PJ_String s;

-    PJ_CharSpec cs;

-

-    scan.get(&cs, &s);

-    return 0;

-}

-

-int test_scan_c()

-{

-    pj_scanner scan;

-    pj_str_t s;

-    pj_char_spec cs;

-

-    pj_scan_get(&scan, cs, &s);

-    return 0;

-}

-#endif

diff --git a/pjlib/src/pj++/pj++.cpp b/pjlib/src/pj++/pj++.cpp
deleted file mode 100644
index 4544209..0000000
--- a/pjlib/src/pj++/pj++.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $Id$
- *
- */

-#include <pj++/scanner.hpp>

-#include <pj++/timer.hpp>

-#include <pj/except.h>

-

-void PJ_Scanner::syntax_error_handler_throw_pj(pj_scanner *)

-{

-    PJ_THROW( PJ_Scanner::SYNTAX_ERROR );

-}

-

-void PJ_Timer_Entry::timer_heap_callback(pj_timer_heap_t *, pj_timer_entry *e)

-{

-    PJ_Timer_Entry *entry = static_cast<PJ_Timer_Entry*>(e);

-    entry->on_timeout();

-}

diff --git a/pjlib/src/pj++/proactor.cpp b/pjlib/src/pj++/proactor.cpp
deleted file mode 100644
index dba9370..0000000
--- a/pjlib/src/pj++/proactor.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/* $Id$
- *
- */

-#include <pj++/proactor.hpp>

-#include <pj/string.h>	// memset

-

-static struct pj_ioqueue_callback ioqueue_cb =

-{

-    &PJ_Event_Handler::read_complete_cb,

-    &PJ_Event_Handler::write_complete_cb,

-    &PJ_Event_Handler::accept_complete_cb,

-    &PJ_Event_Handler::connect_complete_cb,

-};

-

-PJ_Event_Handler::PJ_Event_Handler()

-: proactor_(NULL), key_(NULL)

-{

-    pj_memset(&timer_, 0, sizeof(timer_));

-    timer_.user_data = this;

-    timer_.cb = &timer_callback;

-}

-

-PJ_Event_Handler::~PJ_Event_Handler()

-{

-}

-

-#if PJ_HAS_TCP

-bool PJ_Event_Handler::connect(const PJ_INET_Addr &addr)

-{

-    pj_assert(key_ != NULL && proactor_ != NULL);

-

-    if (key_ == NULL || proactor_ == NULL)

-	return false;

-

-    int status = pj_ioqueue_connect(proactor_->get_io_queue(), key_, 

-				    &addr, sizeof(PJ_INET_Addr));

-    if (status == 0) {

-	on_connect_complete(0);

-	return true;

-    } else if (status == PJ_IOQUEUE_PENDING) {

-	return true;

-    } else {

-	return false;

-    }

-}

-

-bool PJ_Event_Handler::accept(PJ_Socket *sock, PJ_INET_Addr *local, PJ_INET_Addr *remote)

-{

-    pj_assert(key_ != NULL && proactor_ != NULL);

-

-    if (key_ == NULL || proactor_ == NULL)

-	return false;

-

-    int status = pj_ioqueue_accept(proactor_->get_io_queue(), key_, 

-				   &sock->get_handle(), 

-				   local_addr, remote, 

-				   (remote? sizeof(*remote) : 0));

-    if (status == 0) {

-	on_accept_complete(0);

-	return true;

-    } else if (status == PJ_IOQUEUE_PENDING) {

-	return true;

-    } else {

-	return false;

-    }

-}

-

-#endif

-

-bool PJ_Event_Handler::read(void *buf, pj_size_t len)

-{

-    pj_assert(key_ != NULL && proactor_ != NULL);

-

-    if (key_ == NULL || proactor_ == NULL)

-	return false;

-

-    int bytes_status = pj_ioqueue_read(proactor_->get_io_queue(), 

-				       key_, buf, len);

-    if (bytes_status >= 0) {

-	on_read_complete(bytes_status);

-	return true;

-    } else if (bytes_status == PJ_IOQUEUE_PENDING) {

-	return true;

-    } else {

-	return false;

-    }

-}

-

-bool PJ_Event_Handler::recvfrom(void *buf, pj_size_t len, PJ_INET_Addr *addr)

-{

-    pj_assert(key_ != NULL && proactor_ != NULL);

-

-    if (key_ == NULL || proactor_ == NULL)

-	return false;

-

-

-    tmp_recvfrom_addr_len = sizeof(PJ_INET_Addr);

-

-    int bytes_status = pj_ioqueue_recvfrom(proactor_->get_io_queue(), 

-					   key_, buf, len,

-					   addr,

-					   (addr? &tmp_recvfrom_addr_len : NULL));

-    if (bytes_status >= 0) {

-	on_read_complete(bytes_status);

-	return true;

-    } else if (bytes_status == PJ_IOQUEUE_PENDING) {

-	return true;

-    } else {

-	return false;

-    }

-}

-

-bool PJ_Event_Handler::write(const void *data, pj_size_t len)

-{

-    pj_assert(key_ != NULL && proactor_ != NULL);

-

-    if (key_ == NULL || proactor_ == NULL)

-	return false;

-

-    int bytes_status = pj_ioqueue_write(proactor_->get_io_queue(), 

-					key_, data, len);

-    if (bytes_status >= 0) {

-	on_write_complete(bytes_status);

-	return true;

-    } else if (bytes_status == PJ_IOQUEUE_PENDING) {

-	return true;

-    } else {

-	return false;

-    }

-}

-

-bool PJ_Event_Handler::sendto(const void *data, pj_size_t len, const PJ_INET_Addr &addr)

-{

-    pj_assert(key_ != NULL && proactor_ != NULL);

-

-    if (key_ == NULL || proactor_ == NULL)

-	return false;

-

-    int bytes_status = pj_ioqueue_sendto(proactor_->get_io_queue(), 

-					 key_, data, len, 

-					 &addr, sizeof(PJ_INET_Addr));

-    if (bytes_status >= 0) {

-	on_write_complete(bytes_status);

-	return true;

-    } else if (bytes_status == PJ_IOQUEUE_PENDING) {

-	return true;

-    } else {

-	return false;

-    }

-}

-

-

-void PJ_Event_Handler::read_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_read)

-{

-    PJ_Event_Handler *handler = 

-	(PJ_Event_Handler*) pj_ioqueue_get_user_data(key);

-

-    handler->on_read_complete(bytes_read);

-}

-

-void PJ_Event_Handler::write_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent)

-{

-    PJ_Event_Handler *handler = 

-	(PJ_Event_Handler*) pj_ioqueue_get_user_data(key);

-

-    handler->on_write_complete(bytes_sent);

-}

-

-void PJ_Event_Handler::accept_complete_cb(pj_ioqueue_key_t *key, int status)

-{

-#if PJ_HAS_TCP

-    PJ_Event_Handler *handler = 

-	(PJ_Event_Handler*) pj_ioqueue_get_user_data(key);

-

-    handler->on_accept_complete(status);

-#endif

-}

-

-void PJ_Event_Handler::connect_complete_cb(pj_ioqueue_key_t *key, int status)

-{

-#if PJ_HAS_TCP

-    PJ_Event_Handler *handler = 

-	(PJ_Event_Handler*) pj_ioqueue_get_user_data(key);

-

-    handler->on_connect_complete(status);

-#endif

-}

-

-void PJ_Event_Handler::timer_callback( pj_timer_heap_t *timer_heap,

-				       struct pj_timer_entry *entry)

-{

-    PJ_Event_Handler *handler = (PJ_Event_Handler*) entry->user_data;

-    handler->on_timeout(entry->id);

-}

-

-

-PJ_Proactor *PJ_Proactor::create(PJ_Pool *pool, pj_size_t max_fd, 

-				 pj_size_t timer_entry_count, unsigned timer_flags)

-{

-    PJ_Proactor *p = (PJ_Proactor*) pool->calloc(1, sizeof(PJ_Proactor));

-    if (!p) return NULL;

-

-    p->ioq_ = pj_ioqueue_create(pool->pool_(), max_fd);

-    if (!p->ioq_) return NULL;

-

-    p->th_ = pj_timer_heap_create(pool->pool_(), timer_entry_count, timer_flags);

-    if (!p->th_) return NULL;

-

-    return p;

-}

-

-void PJ_Proactor::destroy()

-{

-    pj_ioqueue_destroy(ioq_);

-}

-

-bool PJ_Proactor::register_handler(PJ_Pool *pool, PJ_Event_Handler *handler)

-{

-    pj_assert(handler->key_ == NULL && handler->proactor_ == NULL);

-

-    if (handler->key_ != NULL) 

-	return false;

-

-    handler->key_ = pj_ioqueue_register_sock(pool->pool_(), ioq_, 

-                                             handler->get_handle(), 

-					     handler, &ioqueue_cb);

-    if (handler->key_ != NULL) {

-	handler->proactor_ = this;

-	return true;

-    } else {

-	return false;

-    }

-}

-

-void PJ_Proactor::unregister_handler(PJ_Event_Handler *handler)

-{

-    if (handler->key_ == NULL) return;

-    pj_ioqueue_unregister(ioq_, handler->key_);

-    handler->key_ = NULL;

-    handler->proactor_ = NULL;

-}

-

-bool PJ_Proactor::schedule_timer( pj_timer_heap_t *timer, PJ_Event_Handler *handler,

-				  const PJ_Time_Val &delay, int id)

-{

-    handler->timer_.id = id;

-    return pj_timer_heap_schedule(timer, &handler->timer_, &delay) == 0;

-}

-

-bool PJ_Proactor::schedule_timer(PJ_Event_Handler *handler, const PJ_Time_Val &delay, 

-				 int id)

-{

-    return schedule_timer(th_, handler, delay, id);

-}

-

-bool PJ_Proactor::cancel_timer(PJ_Event_Handler *handler)

-{

-    return pj_timer_heap_cancel(th_, &handler->timer_) == 1;

-}

-

-bool PJ_Proactor::handle_events(PJ_Time_Val *max_timeout)

-{

-    pj_time_val timeout;

-

-    timeout.sec = timeout.msec = 0; /* timeout is 'out' var. */

-

-    if (pj_timer_heap_poll( th_, &timeout ) > 0)

-	return true;

-

-    if (timeout.sec < 0) timeout.sec = PJ_MAXINT32;

-

-    /* If caller specifies maximum time to wait, then compare the value with

-     * the timeout to wait from timer, and use the minimum value.

-     */

-    if (max_timeout && PJ_TIME_VAL_GT(timeout, *max_timeout)) {

-	timeout = *max_timeout;

-    }

-

-    /* Poll events in ioqueue. */

-    int result;

-

-    result = pj_ioqueue_poll(ioq_, &timeout);

-    if (result != 1)

-	return false;

-

-    return true;

-}

-

-pj_ioqueue_t *PJ_Proactor::get_io_queue()

-{

-    return ioq_;

-}

-

-pj_timer_heap_t *PJ_Proactor::get_timer_heap()

-{

-    return th_;

-}

-

diff --git a/pjlib/src/pj/errno.c b/pjlib/src/pj/errno.c
index 682d9b6..25bf5b7 100644
--- a/pjlib/src/pj/errno.c
+++ b/pjlib/src/pj/errno.c
@@ -29,7 +29,8 @@
     { PJ_ETOOMANY,      "Too many objects of the specified type"},
     { PJ_EBUSY,         "Object is busy"},
     { PJ_ENOTSUP,	"Option/operation is not supported"},
-    { PJ_EINVALIDOP,	"Invalid operation"}
+    { PJ_EINVALIDOP,	"Invalid operation"},

+    { PJ_ECANCELLED,    "Operation cancelled"}
 };
 
 /*
diff --git a/pjlib/src/pj/file_io_ansi.c b/pjlib/src/pj/file_io_ansi.c
index f95c74a..0946edd 100644
--- a/pjlib/src/pj/file_io_ansi.c
+++ b/pjlib/src/pj/file_io_ansi.c
@@ -66,7 +66,8 @@
 
     clearerr((FILE*)fd);
     written = fwrite(data, 1, *size, (FILE*)fd);
-    if (ferror((FILE*)fd)) {
+    if (ferror((FILE*)fd)) {

+        *size = -1;
         return PJ_RETURN_OS_ERROR(errno);
     }
 
@@ -82,7 +83,8 @@
 
     clearerr((FILE*)fd);
     bytes = fread(data, 1, *size, (FILE*)fd);
-    if (ferror((FILE*)fd)) {
+    if (ferror((FILE*)fd)) {

+        *size = -1;
         return PJ_RETURN_OS_ERROR(errno);
     }
 
diff --git a/pjlib/src/pj/ioqueue_common_abs.c b/pjlib/src/pj/ioqueue_common_abs.c
index 4cffcae..75774ed 100644
--- a/pjlib/src/pj/ioqueue_common_abs.c
+++ b/pjlib/src/pj/ioqueue_common_abs.c
@@ -227,7 +227,9 @@
          * so that send() can work in parallel.
          */
         if (h->fd_type == PJ_SOCK_DGRAM) {
-            pj_list_erase(write_op);
+            pj_list_erase(write_op);

+            write_op->op = 0;

+
             if (pj_list_empty(&h->write_list))
                 ioqueue_remove_from_set(ioqueue, h->fd, WRITEABLE_EVENT);
 
@@ -267,7 +269,8 @@
         {
             if (h->fd_type != PJ_SOCK_DGRAM) {
                 /* Write completion of the whole stream. */
-                pj_list_erase(write_op);
+                pj_list_erase(write_op);

+                write_op->op = 0;
 
                 /* Clear operation if there's no more data to send. */
                 if (pj_list_empty(&h->write_list))
@@ -313,7 +316,8 @@
 	
         /* Get one accept operation from the list. */
 	accept_op = h->accept_list.next;
-        pj_list_erase(accept_op);
+        pj_list_erase(accept_op);

+        accept_op->op = 0;
 
 	/* Clear bit in fdset if there is no more pending accept */
         if (pj_list_empty(&h->accept_list))
@@ -346,7 +350,8 @@
 
         /* Get one pending read operation from the list. */
         read_op = h->read_list.next;
-        pj_list_erase(read_op);
+        pj_list_erase(read_op);

+        read_op->op = 0;
 
         /* Clear fdset if there is no pending read. */
         if (pj_list_empty(&h->read_list))
@@ -475,6 +480,9 @@
 
     PJ_ASSERT_RETURN(key && op_key && buffer && length, PJ_EINVAL);
     PJ_CHECK_STACK();
+

+    read_op = (struct read_operation*)op_key;

+    read_op->op = 0;

 
     /* Try to see if there's data immediately available. 
      */
@@ -496,8 +504,6 @@
      * No data is immediately available.
      * Must schedule asynchronous operation to the ioqueue.
      */
-    read_op = (struct read_operation*)op_key;
-
     read_op->op = PJ_IOQUEUE_OP_RECV;
     read_op->buf = buffer;
     read_op->size = *length;
@@ -530,6 +536,9 @@
 
     PJ_ASSERT_RETURN(key && op_key && buffer && length, PJ_EINVAL);
     PJ_CHECK_STACK();
+

+    read_op = (struct read_operation*)op_key;

+    read_op->op = 0;

 
     /* Try to see if there's data immediately available. 
      */
@@ -552,8 +561,6 @@
      * No data is immediately available.
      * Must schedule asynchronous operation to the ioqueue.
      */
-    read_op = (struct read_operation*)op_key;
-
     read_op->op = PJ_IOQUEUE_OP_RECV_FROM;
     read_op->buf = buffer;
     read_op->size = *length;
@@ -586,6 +593,9 @@
 
     PJ_ASSERT_RETURN(key && op_key && data && length, PJ_EINVAL);
     PJ_CHECK_STACK();
+

+    write_op = (struct write_operation*)op_key;

+    write_op->op = 0;

 
     /* Fast track:
      *   Try to send data immediately, only if there's no pending write!
@@ -624,7 +634,6 @@
     /*
      * Schedule asynchronous send.
      */
-    write_op = (struct write_operation*)op_key;
     write_op->op = PJ_IOQUEUE_OP_SEND;
     write_op->buf = (void*)data;
     write_op->size = *length;
@@ -659,6 +668,9 @@
 
     PJ_ASSERT_RETURN(key && op_key && data && length, PJ_EINVAL);
     PJ_CHECK_STACK();
+

+    write_op = (struct write_operation*)op_key;

+    write_op->op = 0;

 
     /* Fast track:
      *   Try to send data immediately, only if there's no pending write!
@@ -702,7 +714,6 @@
     /*
      * Schedule asynchronous send.
      */
-    write_op = (struct write_operation*)op_key;
     write_op->op = PJ_IOQUEUE_OP_SEND_TO;
     write_op->buf = (void*)data;
     write_op->size = *length;
@@ -735,6 +746,9 @@
 
     /* check parameters. All must be specified! */
     PJ_ASSERT_RETURN(key && op_key && new_sock, PJ_EINVAL);
+

+    accept_op = (struct accept_operation*)op_key;

+    accept_op->op = 0;

 
     /* Fast track:
      *  See if there's new connection available immediately.
@@ -767,8 +781,6 @@
      * Schedule accept() operation to be completed when there is incoming
      * connection available.
      */
-    accept_op = (struct accept_operation*)op_key;
-
     accept_op->op = PJ_IOQUEUE_OP_ACCEPT;
     accept_op->accept_fd = new_sock;
     accept_op->rmt_addr = remote;
@@ -821,3 +833,82 @@
 }
 #endif	/* PJ_HAS_TCP */
 
+/*

+ * pj_ioqueue_is_pending()

+ */

+PJ_DEF(pj_bool_t) pj_ioqueue_is_pending( pj_ioqueue_key_t *key,

+                                         pj_ioqueue_op_key_t *op_key )

+{

+    struct generic_operation *op_rec;

+

+    PJ_UNUSED_ARG(key);

+

+    op_rec = (struct generic_operation*)op_key;

+    return op_rec->op != 0;

+}

+

+

+/*

+ * pj_ioqueue_post_completion()

+ */

+PJ_DEF(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key,

+                                                pj_ioqueue_op_key_t *op_key,

+                                                pj_ssize_t bytes_status )

+{

+    struct generic_operation *op_rec;

+

+    /*

+     * Find the operation key in all pending operation list to

+     * really make sure that it's still there; then call the callback.

+     */

+    pj_mutex_lock(key->mutex);

+

+    /* Find the operation in the pending read list. */

+    op_rec = (struct generic_operation*)key->read_list.next;

+    while (op_rec != (void*)&key->read_list) {

+        if (op_rec == (void*)op_key) {

+            pj_list_erase(op_rec);

+            op_rec->op = 0;

+            pj_mutex_unlock(key->mutex);

+

+            (*key->cb.on_read_complete)(key, op_key, bytes_status);

+            return PJ_SUCCESS;

+        }

+        op_rec = op_rec->next;

+    }

+

+    /* Find the operation in the pending write list. */

+    op_rec = (struct generic_operation*)key->write_list.next;

+    while (op_rec != (void*)&key->write_list) {

+        if (op_rec == (void*)op_key) {

+            pj_list_erase(op_rec);

+            op_rec->op = 0;

+            pj_mutex_unlock(key->mutex);

+

+            (*key->cb.on_write_complete)(key, op_key, bytes_status);

+            return PJ_SUCCESS;

+        }

+        op_rec = op_rec->next;

+    }

+

+    /* Find the operation in the pending accept list. */

+    op_rec = (struct generic_operation*)key->accept_list.next;

+    while (op_rec != (void*)&key->accept_list) {

+        if (op_rec == (void*)op_key) {

+            pj_list_erase(op_rec);

+            op_rec->op = 0;

+            pj_mutex_unlock(key->mutex);

+

+            (*key->cb.on_accept_complete)(key, op_key, 

+                                          PJ_INVALID_SOCKET,

+                                          bytes_status);

+            return PJ_SUCCESS;

+        }

+        op_rec = op_rec->next;

+    }

+

+    pj_mutex_unlock(key->mutex);

+    

+    return PJ_EINVALIDOP;

+}

+

diff --git a/pjlib/src/pj/ioqueue_winnt.c b/pjlib/src/pj/ioqueue_winnt.c
index 7944953..93cbb6d 100644
--- a/pjlib/src/pj/ioqueue_winnt.c
+++ b/pjlib/src/pj/ioqueue_winnt.c
@@ -891,3 +891,37 @@
 }
 #endif	/* #if PJ_HAS_TCP */
 
+

+

+PJ_DEF(pj_bool_t) pj_ioqueue_is_pending( pj_ioqueue_key_t *key,

+                                         pj_ioqueue_op_key_t *op_key )

+{

+    BOOL rc;

+    DWORD bytesTransfered;

+

+    rc = GetOverlappedResult( key->hnd, (LPOVERLAPPED)op_key,

+                              &bytesTransfered, FALSE );

+

+    if (rc == FALSE) {

+        return GetLastError()==ERROR_IO_INCOMPLETE;

+    }

+

+    return FALSE;

+}

+

+

+PJ_DEF(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key,

+                                                pj_ioqueue_op_key_t *op_key,

+                                                pj_ssize_t bytes_status )

+{

+    BOOL rc;

+

+    rc = PostQueuedCompletionStatus(key->ioqueue->iocp, bytes_status,

+                                    (long)key, (OVERLAPPED*)op_key );

+    if (rc == FALSE) {

+        return PJ_RETURN_OS_ERROR(GetLastError());

+    }

+

+    return PJ_SUCCESS;

+}

+

diff --git a/pjlib/src/pj/os_core_unix.c b/pjlib/src/pj/os_core_unix.c
index 3892b64..cc57aab 100644
--- a/pjlib/src/pj/os_core_unix.c
+++ b/pjlib/src/pj/os_core_unix.c
@@ -558,54 +558,91 @@
     return oldval;
 }
 
+/*

+ * pj_atomic_inc_and_get()

+ */

+PJ_DEF(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var)

+{

+    pj_atomic_value_t new_value;

+

+    PJ_CHECK_STACK();

+

+#if PJ_HAS_THREADS

+    pj_mutex_lock( atomic_var->mutex );

+#endif

+    new_value = ++atomic_var->value;

+#if PJ_HAS_THREADS

+    pj_mutex_unlock( atomic_var->mutex);

+#endif

+

+    return new_value;

+}

 /*
  * pj_atomic_inc()
  */
 PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
 {
-    PJ_CHECK_STACK();
-
-#if PJ_HAS_THREADS
-    pj_mutex_lock( atomic_var->mutex );
-#endif
-    ++atomic_var->value;
-#if PJ_HAS_THREADS
-    pj_mutex_unlock( atomic_var->mutex);
-#endif
+    pj_atomic_inc_and_get(atomic_var);
 }
 
 /*
- * pj_atomic_dec()
+ * pj_atomic_dec_and_get()
  */
-PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
-{
+PJ_DEF(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var)
+{

+    pj_atomic_value_t new_value;

+
     PJ_CHECK_STACK();
 
 #if PJ_HAS_THREADS
     pj_mutex_lock( atomic_var->mutex );
 #endif
-    --atomic_var->value;
+    new_value = --atomic_var->value;
 #if PJ_HAS_THREADS
     pj_mutex_unlock( atomic_var->mutex);
-#endif
+#endif

+

+    return new_value;
 }
+

+/*

+ * pj_atomic_dec()

+ */

+PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)

+{

+    pj_atomic_dec_and_get(atomic_var);

+}

 
 /*
- * pj_atomic_add()
+ * pj_atomic_add_and_get()
  */ 
-PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var, pj_atomic_value_t value )
-{
+PJ_DEF(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var, 

+                                                 pj_atomic_value_t value )
+{

+    pj_atomic_value_t new_value;

+
 #if PJ_HAS_THREADS
     pj_mutex_lock(atomic_var->mutex);
 #endif
     
-    atomic_var->value += value;
+    atomic_var->value += value;

+    new_value = atomic_var->value;
 
 #if PJ_HAS_THREADS
     pj_mutex_unlock(atomic_var->mutex);
-#endif
+#endif

+

+    return new_value;
 }
 
+/*

+ * pj_atomic_add()

+ */ 

+PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var, 

+                            pj_atomic_value_t value )

+{

+    pj_atomic_add_and_get(atomic_var, value);

+}

 
 ///////////////////////////////////////////////////////////////////////////////
 /*
diff --git a/pjlib/src/pj/os_core_win32.c b/pjlib/src/pj/os_core_win32.c
index 68416c6..be770d5 100644
--- a/pjlib/src/pj/os_core_win32.c
+++ b/pjlib/src/pj/os_core_win32.c
@@ -512,32 +512,48 @@
     return atomic_var->value;
 }
 
+/*

+ * pj_atomic_inc_and_get()

+ */

+PJ_DEF(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var)

+{

+    PJ_CHECK_STACK();

+

+#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400

+    return InterlockedIncrement(&atomic_var->value);

+#else

+#   error Fix Me

+#endif

+}

+

 /*
  * pj_atomic_inc()
  */
 PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
-{
-    PJ_CHECK_STACK();
-
-#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400
-    InterlockedIncrement(&atomic_var->value);
-#else
-#   error Fix Me
-#endif
+{

+    pj_atomic_inc_and_get(atomic_var);
 }
-
+

+/*

+ * pj_atomic_dec_and_get()

+ */

+PJ_DEF(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var)

+{

+    PJ_CHECK_STACK();

+

+#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400

+    return InterlockedDecrement(&atomic_var->value);

+#else

+#   error Fix me

+#endif

+}

+

 /*
  * pj_atomic_dec()
  */
 PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
 {
-    PJ_CHECK_STACK();
-
-#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400
-    InterlockedDecrement(&atomic_var->value);
-#else
-#   error Fix me
-#endif
+    pj_atomic_dec_and_get(atomic_var);
 }
 
 /*
@@ -546,10 +562,27 @@
 PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var,
 			    pj_atomic_value_t value )
 {
-    InterlockedExchangeAdd( &atomic_var->value, value );
+#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400

+    InterlockedExchangeAdd( &atomic_var->value, value );

+#else

+#   error Fix me

+#endif
+}
+

+/*

+ * pj_atomic_add_and_get()

+ */

+PJ_DEF(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var,

+			                         pj_atomic_value_t value)

+{

+#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400

+    long oldValue = InterlockedExchangeAdd( &atomic_var->value, value);

+    return oldValue + value;

+#else

+#   error Fix me

+#endif

 }
 
-	
 ///////////////////////////////////////////////////////////////////////////////
 /*
  * pj_thread_local_alloc()
diff --git a/pjlib/src/pj/timer.c b/pjlib/src/pj/timer.c
index 9fa190a..ffec1f4 100644
--- a/pjlib/src/pj/timer.c
+++ b/pjlib/src/pj/timer.c
@@ -14,9 +14,13 @@
 #include <pj/string.h>
 #include <pj/assert.h>
 #include <pj/errno.h>
+#include <pj/lock.h>

 
 #define HEAP_PARENT(X)	(X == 0 ? 0 : (((X) - 1) / 2))
 #define HEAP_LEFT(X)	(((X)+(X))+1)
+

+

+#define DEFAULT_MAX_TIMED_OUT_PER_POLL  (64)

 
 
 /**
@@ -32,9 +36,15 @@
 
     /** Current size of the heap. */
     pj_size_t cur_size;
+

+    /** Max timed out entries to process per poll. */

+    unsigned max_entries_per_poll;

 
-    /** Mutex for synchronization, or NULL */
-    pj_mutex_t *mutex;
+    /** Lock object. */
+    pj_lock_t *lock;
+

+    /** Autodelete lock. */

+    pj_bool_t auto_delete_lock;

 
     /**
      * Current contents of the Heap, which is organized as a "heap" of
@@ -71,15 +81,15 @@
 
 PJ_INLINE(void) lock_timer_heap( pj_timer_heap_t *ht )
 {
-    if (ht->mutex) {
-	pj_mutex_lock(ht->mutex);
+    if (ht->lock) {
+	pj_lock_acquire(ht->lock);
     }
 }
 
 PJ_INLINE(void) unlock_timer_heap( pj_timer_heap_t *ht )
 {
-    if (ht->mutex) {
-	pj_mutex_unlock(ht->mutex);
+    if (ht->lock) {
+	pj_lock_release(ht->lock);
     }
 }
 
@@ -319,7 +329,7 @@
            sizeof(pj_timer_heap_t) + 
            /* size of each entry: */
            (count+2) * (sizeof(pj_timer_entry*)+sizeof(pj_timer_id_t)) +
-           /* mutex, pool etc: */
+           /* lock, pool etc: */
            132;
 }
 
@@ -328,7 +338,6 @@
  */
 PJ_DEF(pj_status_t) pj_timer_heap_create( pj_pool_t *pool,
 					  pj_size_t size,
-					  unsigned flag,
                                           pj_timer_heap_t **p_heap)
 {
     pj_timer_heap_t *ht;
@@ -348,23 +357,14 @@
 
     /* Initialize timer heap sizes */
     ht->max_size = size;
-    ht->cur_size = 0;
+    ht->cur_size = 0;

+    ht->max_entries_per_poll = DEFAULT_MAX_TIMED_OUT_PER_POLL;
     ht->timer_ids_freelist = 1;
-    ht->pool = pool;
+    ht->pool = pool;

 
-    /* Mutex. */
-    if (flag & PJ_TIMER_HEAP_NO_SYNCHRONIZE) {
-	ht->mutex = NULL;
-    } else {
-        pj_status_t rc;
-
-	/* Mutex must be the recursive types. 
-         * See commented code inside pj_timer_heap_poll() 
-         */
-	rc = pj_mutex_create(pool, "tmhp%p", PJ_MUTEX_RECURSE, &ht->mutex);
-	if (rc != PJ_SUCCESS)
-	    return rc;
-    }
+    /* Lock. */
+    ht->lock = NULL;

+    ht->auto_delete_lock = 0;

 
     // Create the heap array.
     ht->heap = pj_pool_alloc(pool, sizeof(pj_timer_entry*) * size);
@@ -385,6 +385,34 @@
     *p_heap = ht;
     return PJ_SUCCESS;
 }
+

+PJ_DEF(void) pj_timer_heap_destroy( pj_timer_heap_t *ht )

+{

+    if (ht->lock && ht->auto_delete_lock) {

+        pj_lock_destroy(ht->lock);

+        ht->lock = NULL;

+    }

+}

+

+PJ_DEF(void) pj_timer_heap_set_lock(  pj_timer_heap_t *ht,

+                                      pj_lock_t *lock,

+                                      pj_bool_t auto_del )

+{

+    if (ht->lock && ht->auto_delete_lock)

+        pj_lock_destroy(ht->lock);

+

+    ht->lock = lock;

+    ht->auto_delete_lock = auto_del;

+}

+

+

+PJ_DEF(unsigned) pj_timer_heap_set_max_timed_out_per_poll(pj_timer_heap_t *ht,

+                                                          unsigned count )

+{

+    unsigned old_count = ht->max_entries_per_poll;

+    ht->max_entries_per_poll = count;

+    return old_count;

+}

 
 PJ_DEF(pj_timer_entry*) pj_timer_entry_init( pj_timer_entry *entry,
                                              int id,
@@ -433,12 +461,13 @@
     return count;
 }
 
-PJ_DEF(int) pj_timer_heap_poll( pj_timer_heap_t *ht, pj_time_val *next_delay )
+PJ_DEF(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht, 

+                                     pj_time_val *next_delay )
 {
     pj_time_val now;
-    int count;
+    unsigned count;
 
-    PJ_ASSERT_RETURN(ht, -1);
+    PJ_ASSERT_RETURN(ht, 0);
 
     if (!ht->cur_size && next_delay) {
 	next_delay->sec = next_delay->msec = PJ_MAXINT32;
@@ -450,16 +479,15 @@
 
     lock_timer_heap(ht);
     while ( ht->cur_size && 
-	    PJ_TIME_VAL_LTE(ht->heap[0]->_timer_value, now) ) 
+	    PJ_TIME_VAL_LTE(ht->heap[0]->_timer_value, now) &&

+            count < ht->max_entries_per_poll ) 
     {
 	pj_timer_entry *node = remove_node(ht, 0);
 	++count;
 
-	//Better not to temporarily release mutex to save some syscalls.
-	//But then make sure the mutex must be the recursive types (PJ_MUTEX_RECURSE)!
-	//unlock_timer_heap(ht);
+	unlock_timer_heap(ht);
 	(*node->cb)(ht, node);
-	//lock_timer_heap(ht);
+	lock_timer_heap(ht);
     }
     if (ht->cur_size && next_delay) {
 	*next_delay = ht->heap[0]->_timer_value;
@@ -473,7 +501,9 @@
 }
 
 PJ_DEF(pj_size_t) pj_timer_heap_count( pj_timer_heap_t *ht )
-{
+{

+    PJ_ASSERT_RETURN(ht, 0);

+
     return ht->cur_size;
 }
 
diff --git a/pjlib/src/pjlib++-test/main.cpp b/pjlib/src/pjlib++-test/main.cpp
new file mode 100644
index 0000000..4a6d0aa
--- /dev/null
+++ b/pjlib/src/pjlib++-test/main.cpp
@@ -0,0 +1,29 @@
+#include <pj++/file.hpp>

+#include <pj++/list.hpp>

+#include <pj++/lock.hpp>

+#include <pj++/hash.hpp>

+#include <pj++/os.hpp>

+#include <pj++/proactor.hpp>

+#include <pj++/sock.hpp>

+#include <pj++/string.hpp>

+#include <pj++/timer.hpp>

+#include <pj++/tree.hpp>

+

+int main()

+{

+    Pjlib lib;

+    Pj_Caching_Pool mem;

+    Pj_Pool the_pool;

+    Pj_Pool *pool = &the_pool;

+    

+    the_pool.attach(mem.create_pool(4000,4000));

+

+    Pj_Semaphore_Lock lsem(pool);

+    Pj_Semaphore_Lock *plsem;

+

+    plsem = new(pool) Pj_Semaphore_Lock(pool);

+    delete plsem;

+

+    return 0;

+}

+