Index: pjproject/main/pjlib/build/pjlib++-test.dsp
===================================================================
--- pjproject/main/pjlib/build/pjlib++-test.dsp	(revision 36)
+++ pjproject/main/pjlib/build/pjlib++-test.dsp	(revision 36)
@@ -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
Index: pjproject/main/pjlib/build/pjlib++.dsp
===================================================================
--- pjproject/main/pjlib/build/pjlib++.dsp	(revision 36)
+++ pjproject/main/pjlib/build/pjlib++.dsp	(revision 36)
@@ -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
Index: pjproject/main/pjlib/build/pjlib++.vcproj
===================================================================
--- pjproject/main/pjlib/build/pjlib++.vcproj	(revision 36)
+++ pjproject/main/pjlib/build/pjlib++.vcproj	(revision 36)
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="pjlibpp"
+	SccProjectName=""
+	SccAuxPath=""
+	SccLocalPath=""
+	SccProvider="">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory=".\output\pjlibpp-i386-win32-vc7-release"
+			IntermediateDirectory=".\output\pjlibpp-i386-win32-vc7-release"
+			ConfigurationType="4"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="../src"
+				PreprocessorDefinitions="NDEBUG;WIN32;_LIB;PJ_WIN32;PJ_M_I386"
+				StringPooling="TRUE"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="TRUE"
+				PrecompiledHeaderFile=".\output\pjlibpp-i386-win32-vc7-release/pjlibpp.pch"
+				AssemblerListingLocation=".\output\pjlibpp-i386-win32-vc7-release/"
+				ObjectFile=".\output\pjlibpp-i386-win32-vc7-release/"
+				ProgramDataBaseFileName=".\output\pjlibpp-i386-win32-vc7-release/"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"
+				CompileAs="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="../lib/pjlibp_vc6s.lib"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1033"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory=".\output\pjlibpp-i386-win32-vc7-debug"
+			IntermediateDirectory=".\output\pjlibpp-i386-win32-vc7-debug"
+			ConfigurationType="4"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../src"
+				PreprocessorDefinitions="_DEBUG;WIN32;_LIB;PJ_WIN32;PJ_M_I386"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				PrecompiledHeaderFile=".\output\pjlibpp-i386-win32-vc7-debug/pjlibpp.pch"
+				AssemblerListingLocation=".\output\pjlibpp-i386-win32-vc7-debug/"
+				ObjectFile=".\output\pjlibpp-i386-win32-vc7-debug/"
+				ProgramDataBaseFileName=".\output\pjlibpp-i386-win32-vc7-debug/"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"
+				DebugInformationFormat="4"
+				CompileAs="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="../lib/pjlibp_vc6sd.lib"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1033"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+			<File
+				RelativePath="..\src\pj++\compiletest.cpp">
+				<FileConfiguration
+					Name="Release|Win32">
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="2"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32">
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="0"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+						BasicRuntimeChecks="3"/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\src\pj++\pj++.cpp">
+				<FileConfiguration
+					Name="Release|Win32">
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="2"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32">
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="0"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+						BasicRuntimeChecks="3"/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\src\pj++\proactor.cpp">
+				<FileConfiguration
+					Name="Release|Win32">
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="2"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32">
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="0"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+						BasicRuntimeChecks="3"/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl">
+			<File
+				RelativePath="..\src\pj++\hash.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pj++\ioqueue.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pj++\list.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pj++\os.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pjlib++.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pj++\pool.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pj++\proactor.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pj++\scanner.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pj++\sock.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pj++\string.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pj++\timer.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pj++\tree.hpp">
+			</File>
+			<File
+				RelativePath="..\src\pj++\types.hpp">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: pjproject/main/pjlib/build/pjlib.dsp
===================================================================
--- pjproject/main/pjlib/build/pjlib.dsp	(revision 35)
+++ pjproject/main/pjlib/build/pjlib.dsp	(revision 36)
@@ -235,4 +235,11 @@
 
 SOURCE=..\src\pj\ioqueue_winnt.c
+
+!IF  "$(CFG)" == "pjlib - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "pjlib - Win32 Debug"
+
+!ENDIF 
+
 # End Source File
 # Begin Source File
Index: pjproject/main/pjlib/build/pjlib.dsw
===================================================================
--- pjproject/main/pjlib/build/pjlib.dsw	(revision 35)
+++ pjproject/main/pjlib/build/pjlib.dsw	(revision 36)
@@ -4,12 +4,8 @@
 ###############################################################################
 
-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
 }}}
 
@@ -20,12 +16,20 @@
 ###############################################################################
 
-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>
+{{{
 }}}
 
@@ -39,12 +43,8 @@
 ###############################################################################
 
-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
 }}}
 
@@ -58,16 +58,18 @@
 ###############################################################################
 
-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
 }}}
 
@@ -78,8 +80,4 @@
 Package=<5>
 {{{
-    begin source code control
-    "$/pjproject-0.3/pjlib/build", EJDAAAAA
-    .
-    end source code control
 }}}
 
Index: pjproject/main/pjlib/build/pjlibpp.dsp
===================================================================
--- pjproject/main/pjlib/build/pjlibpp.dsp	(revision 35)
+++ 	(revision )
@@ -1,158 +1,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
Index: pjproject/main/pjlib/build/pjlibpp.vcproj
===================================================================
--- pjproject/main/pjlib/build/pjlibpp.vcproj	(revision 35)
+++ 	(revision )
@@ -1,230 +1,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="7.10"
-	Name="pjlibpp"
-	SccProjectName=""
-	SccAuxPath=""
-	SccLocalPath=""
-	SccProvider="">
-	<Platforms>
-		<Platform
-			Name="Win32"/>
-	</Platforms>
-	<Configurations>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory=".\output\pjlibpp-i386-win32-vc7-release"
-			IntermediateDirectory=".\output\pjlibpp-i386-win32-vc7-release"
-			ConfigurationType="4"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE"
-			CharacterSet="2">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="../src"
-				PreprocessorDefinitions="NDEBUG;WIN32;_LIB;PJ_WIN32;PJ_M_I386"
-				StringPooling="TRUE"
-				RuntimeLibrary="2"
-				EnableFunctionLevelLinking="TRUE"
-				PrecompiledHeaderFile=".\output\pjlibpp-i386-win32-vc7-release/pjlibpp.pch"
-				AssemblerListingLocation=".\output\pjlibpp-i386-win32-vc7-release/"
-				ObjectFile=".\output\pjlibpp-i386-win32-vc7-release/"
-				ProgramDataBaseFileName=".\output\pjlibpp-i386-win32-vc7-release/"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"
-				CompileAs="0"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLibrarianTool"
-				OutputFile="../lib/pjlibp_vc6s.lib"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1033"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"/>
-			<Tool
-				Name="VCManagedWrapperGeneratorTool"/>
-			<Tool
-				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory=".\output\pjlibpp-i386-win32-vc7-debug"
-			IntermediateDirectory=".\output\pjlibpp-i386-win32-vc7-debug"
-			ConfigurationType="4"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE"
-			CharacterSet="2">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="../src"
-				PreprocessorDefinitions="_DEBUG;WIN32;_LIB;PJ_WIN32;PJ_M_I386"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
-				PrecompiledHeaderFile=".\output\pjlibpp-i386-win32-vc7-debug/pjlibpp.pch"
-				AssemblerListingLocation=".\output\pjlibpp-i386-win32-vc7-debug/"
-				ObjectFile=".\output\pjlibpp-i386-win32-vc7-debug/"
-				ProgramDataBaseFileName=".\output\pjlibpp-i386-win32-vc7-debug/"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"
-				DebugInformationFormat="4"
-				CompileAs="0"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLibrarianTool"
-				OutputFile="../lib/pjlibp_vc6sd.lib"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG"
-				Culture="1033"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"/>
-			<Tool
-				Name="VCManagedWrapperGeneratorTool"/>
-			<Tool
-				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
-			<File
-				RelativePath="..\src\pj++\compiletest.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="2"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="0"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""
-						BasicRuntimeChecks="3"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\src\pj++\pj++.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="2"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="0"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""
-						BasicRuntimeChecks="3"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\src\pj++\proactor.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="2"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="0"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""
-						BasicRuntimeChecks="3"/>
-				</FileConfiguration>
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl">
-			<File
-				RelativePath="..\src\pj++\hash.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pj++\ioqueue.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pj++\list.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pj++\os.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pjlib++.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pj++\pool.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pj++\proactor.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pj++\scanner.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pj++\sock.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pj++\string.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pj++\timer.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pj++\tree.hpp">
-			</File>
-			<File
-				RelativePath="..\src\pj++\types.hpp">
-			</File>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
Index: pjproject/main/pjlib/include/pj++/file.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/file.hpp	(revision 36)
+++ pjproject/main/pjlib/include/pj++/file.hpp	(revision 36)
@@ -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__ */
+
Index: pjproject/main/pjlib/include/pj++/hash.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/hash.hpp	(revision 35)
+++ pjproject/main/pjlib/include/pj++/hash.hpp	(revision 36)
@@ -1,4 +1,3 @@
 /* $Id$
- *
  */
 #ifndef __PJPP_HASH_H__
@@ -6,18 +5,43 @@
 
 #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_;
@@ -25,49 +49,91 @@
 	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__ */
+
Index: pjproject/main/pjlib/include/pj++/ioqueue.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/ioqueue.hpp	(revision 35)
+++ 	(revision )
@@ -1,174 +1,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__ */
Index: pjproject/main/pjlib/include/pj++/list.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/list.hpp	(revision 35)
+++ pjproject/main/pjlib/include/pj++/list.hpp	(revision 36)
@@ -1,4 +1,3 @@
 /* $Id$
- *
  */
 #ifndef __PJPP_LIST_H__
@@ -6,46 +5,107 @@
 
 #include <pj/list.h>
-
-template <typename T>
-struct PJ_List_Node
-{
-    PJ_DECL_LIST_MEMBER(T)
-};
-
-
-template <class Node>
-class PJ_List
+#include <pj++/pool.hpp>
+
+
+//
+// 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
     {
@@ -53,4 +113,7 @@
     }
 
+    //
+    // Get first element.
+    //
     iterator begin()
     {
@@ -58,4 +121,7 @@
     }
 
+    //
+    // Get first element.
+    //
     const_iterator begin() const
     {
@@ -63,44 +129,71 @@
     }
 
+    //
+    // 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_);
-    }
-
-    void insert_before (iterator &pos, Node *node)
+	return iterator((List_Node*)&root_);
+    }
+
+    //
+    // 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)
     {
@@ -108,14 +201,23 @@
     }
 
-    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()
     {
@@ -123,14 +225,23 @@
     }
 
-    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()
     {
@@ -138,26 +249,41 @@
     }
 
-    iterator find(Node *node)
-    {
-	Node *n = pj_list_find_node(&root_, node);
+    //
+    // Find a node.
+    //
+    iterator find(List_Node *node)
+    {
+	List_Node *n = pj_list_find_node(&root_, node);
 	return n ? iterator(n) : end();
     }
 
-    const_iterator find(Node *node) const
-    {
-	Node *n = pj_list_find_node(&root_, node);
+    //
+    // Find a node.
+    //
+    const_iterator find(List_Node *node) const
+    {
+	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()
     {
@@ -169,5 +295,5 @@
     struct RootNode
     {
-	PJ_DECL_LIST_MEMBER(Node)
+	PJ_DECL_LIST_MEMBER(List_Node);
     } root_;
 
@@ -175,6 +301,6 @@
     {
 	// 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;
     }
Index: pjproject/main/pjlib/include/pj++/lock.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/lock.hpp	(revision 36)
+++ pjproject/main/pjlib/include/pj++/lock.hpp	(revision 36)
@@ -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__ */
+
Index: pjproject/main/pjlib/include/pj++/os.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/os.hpp	(revision 35)
+++ pjproject/main/pjlib/include/pj++/os.hpp	(revision 36)
@@ -1,4 +1,3 @@
 /* $Id$
- *
  */
 #ifndef __PJPP_OS_H__
@@ -9,5 +8,94 @@
 #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:
@@ -17,132 +105,303 @@
     };
 
-    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)
-    {
-	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)
-    {
-	return (PJ_Thread*) pj_thread_register(name, desc);
-    }
-
-    static PJ_Thread *get_current_thread()
-    {
-	return (PJ_Thread*) pj_thread_this();
-    }
-
-    static pj_status_t sleep(unsigned msec)
-    {
-	return pj_thread_sleep(msec);
-    }
-
-    static pj_status_t usleep(unsigned usec)
-    {
-	return pj_thread_usleep(usec);
-    }
-
+    //
+    // Default constructor.
+    //
+    Pj_Thread()
+        : thread_(NULL)
+    {
+    }
+
+    //
+    // Destroy thread.
+    //
+    ~Pj_Thread()
+    {
+        destroy();
+    }
+
+    //
+    // 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)
+    {
+        destroy();
+        return Pj_Thread_API::create( pool, &thread_, &thread_proc, this,
+                                      flags, thread_name);
+    }
+
+    //
+    // 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_() );
-    }
-};
-
-
-class PJ_Thread_Local
-{
-public:
-    static PJ_Thread_Local *alloc()
-    {
-	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
-    {
-	return (long)this;
-    }
-
-    void set(void *value)
-    {
-	pj_thread_local_set( this->tls_(), value );
-    }
-
-    void *get()
-    {
-	return pj_thread_local_get( this->tls_() );
-    }
-};
-
-
-class PJ_Atomic
-{
-public:
-    static PJ_Atomic *create(PJ_Pool *pool, long initial)
-    {
-	return (PJ_Atomic*) pj_atomic_create(pool->pool_(), initial);
-    }
-
+        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();
+    }
+};
+
+
+//
+// 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:
+    Pj_External_Thread()
+    {
+    }
+
+    //
+    // Register external thread so that pjlib functions can work
+    // in that thread.
+    //
+    pj_status_t register_this_thread( const char *name=NULL )
+    {
+        return Pj_Thread_API::register_this_thread(desc_, &thread_,name);
+    }
+
+private:
+    pj_thread_desc desc_;
+};
+
+
+//
+// Thread specific data/thread local storage/TLS.
+//
+class Pj_Thread_Local_API
+{
+public:
+    //
+    // Allocate thread local storage (TLS) index.
+    //
+    static pj_status_t alloc(long *index)
+    {
+        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;
-    }
-
-    pj_status_t destroy()
-    {
-	return pj_atomic_destroy( this->pj_atomic_t_() );
-    }
-
-    long set(long val)
-    {
-	return pj_atomic_set( this->pj_atomic_t_(), val);
-    }
-
-    long get()
-    {
-	return pj_atomic_get( this->pj_atomic_t_() );
-    }
-
-    long inc()
-    {
-	return pj_atomic_inc( this->pj_atomic_t_() );
-    }
-
-    long dec()
-    {
-	return pj_atomic_dec( this->pj_atomic_t_() );
-    }
-};
-
-
-class PJ_Mutex
-{
-public:
+	return var_;
+    }
+
+    //
+    // Set the value.
+    //
+    void set(pj_atomic_value_t val)
+    {
+	pj_atomic_set(var_, val);
+    }
+
+    //
+    // Get the value.
+    //
+    pj_atomic_value_t get()
+    {
+	return pj_atomic_get(var_);
+    }
+
+    //
+    // Increment.
+    //
+    void inc()
+    {
+	pj_atomic_inc(var_);
+    }
+
+    //
+    // Increment and get the result.
+    //
+    pj_atomic_value_t inc_and_get()
+    {
+        return pj_atomic_inc_and_get(var_);
+    }
+
+    //
+    // Decrement.
+    //
+    void dec()
+    {
+	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_;
+};
+
+
+//
+// Mutex
+//
+class Pj_Mutex : public Pj_Object
+{
+public:
+    //
+    // Mutex type.
+    //
     enum Type
     {
@@ -152,51 +411,143 @@
     };
 
-    static PJ_Mutex *create( PJ_Pool *pool, const char *name, Type type)
-    {
-	return (PJ_Mutex*) pj_mutex_create( pool->pool_(), name, type);
-    }
-
-    pj_mutex_t *pj_mutex_()
-    {
-	return (pj_mutex_t*)this;
-    }
-
-    pj_status_t destroy()
-    {
-	return pj_mutex_destroy( this->pj_mutex_() );
-    }
-
-    pj_status_t lock()
-    {
-	return pj_mutex_lock( this->pj_mutex_() );
-    }
-
-    pj_status_t unlock()
-    {
-	return pj_mutex_unlock( this->pj_mutex_() );
-    }
-
-    pj_status_t trylock()
-    {
-	return pj_mutex_trylock( this->pj_mutex_() );
-    }
-
-#if PJ_DEBUG
-    pj_status_t is_locked()
-    {
-	return pj_mutex_is_locked( this->pj_mutex_() );
-    }
-#endif
-};
-
-
-class PJ_Semaphore
-{
-public:
-    static PJ_Semaphore *create( PJ_Pool *pool, const char *name, unsigned initial, unsigned max)
-    {
-	return (PJ_Semaphore*) pj_sem_create( pool->pool_(), name, initial, max);
-    }
-
+    //
+    // Default constructor will create default mutex.
+    //
+    explicit Pj_Mutex(Pj_Pool *pool, Type type = DEFAULT,
+                      const char *name = NULL)
+        : mutex_(NULL)
+    {
+        create(pool, type, name);
+    }
+
+    //
+    // Destructor.
+    //
+    ~Pj_Mutex()
+    {
+        destroy();
+    }
+
+    //
+    // Create mutex.
+    //
+    pj_status_t create( Pj_Pool *pool, Type type, const char *name = NULL)
+    {
+        destroy();
+	return pj_mutex_create( pool->pool_(), name, type,
+                                &mutex_ );
+    }
+
+    //
+    // Create simple mutex.
+    //
+    pj_status_t create_simple( Pj_Pool *pool,const char *name = NULL)
+    {
+        return create(pool, SIMPLE, name);
+    }
+
+    //
+    // Create recursive mutex.
+    //
+    pj_status_t create_recursive( Pj_Pool *pool, const char *name = NULL )
+    {
+        return create(pool, RECURSE, name);
+    }
+
+    //
+    // Get pjlib compatible mutex object.
+    //
+    pj_mutex_t *pj_mutex_t_()
+    {
+	return mutex_;
+    }
+
+    //
+    // Destroy mutex.
+    //
+    void destroy()
+    {
+        if (mutex_) {
+	    pj_mutex_destroy(mutex_);
+            mutex_ = NULL;
+        }
+    }
+
+    //
+    // 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_;
+};
+
+
+//
+// Semaphore
+//
+class Pj_Semaphore : public Pj_Object
+{
+public:
+    //
+    // Construct semaphore
+    //
+    Pj_Semaphore(Pj_Pool *pool, unsigned max,
+                 unsigned initial = 0, const char *name = NULL)
+    : sem_(NULL)
+    {
+    }
+
+    //
+    // 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_()
     {
@@ -204,9 +555,7 @@
     }
 
-    pj_status_t destroy()
-    {
-	return pj_sem_destroy(this->pj_sem_t_());
-    }
-
+    //
+    // Wait semaphore.
+    //
     pj_status_t wait()
     {
@@ -214,9 +563,15 @@
     }
 
-    pj_status_t lock()
+    //
+    // Wait semaphore.
+    //
+    pj_status_t acquire()
     {
 	return wait();
     }
 
+    //
+    // Try wait semaphore.
+    //
     pj_status_t trywait()
     {
@@ -224,9 +579,15 @@
     }
 
-    pj_status_t trylock()
+    //
+    // Try wait semaphore.
+    //
+    pj_status_t tryacquire()
     {
 	return trywait();
     }
 
+    //
+    // Post semaphore.
+    //
     pj_status_t post()
     {
@@ -234,39 +595,90 @@
     }
 
-    pj_status_t unlock()
+    //
+    // Post semaphore.
+    //
+    pj_status_t release()
     {
 	return post();
     }
-};
-
-
-class PJ_Event
-{
-public:
-    static PJ_Event *create( PJ_Pool *pool, const char *name, bool manual_reset, bool initial)
-    {
-	return (PJ_Event*) pj_event_create(pool->pool_(), name, manual_reset, initial);
-    }
-
+
+private:
+    pj_sem_t *sem_;
+};
+
+
+//
+// Event object.
+//
+class Pj_Event
+{
+public:
+    //
+    // Construct event object.
+    //
+    Pj_Event( Pj_Pool *pool, bool manual_reset = false,
+              bool initial = false, const char *name = NULL )
+    : event_(NULL)
+    {
+        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;
-    }
-
-    pj_status_t destroy()
-    {
-	return pj_event_destroy(this->pj_event_t_());
-    }
-
+	return event_;
+    }
+
+    //
+    // Destroy event object.
+    //
+    void destroy()
+    {
+        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()
     {
@@ -274,4 +686,7 @@
     }
 
+    //
+    // Release one waiting thread.
+    //
     pj_status_t pulse()
     {
@@ -279,34 +694,60 @@
     }
 
+    //
+    // Set a non-signalled.
+    //
     pj_status_t reset()
     {
 	return pj_event_reset(this->pj_event_t_());
     }
-};
-
-class PJ_OS
-{
-public:
-    static pj_status_t gettimeofday( PJ_Time_Val *tv )
+
+private:
+    pj_event_t *event_;
+};
+
+//
+// OS abstraction.
+//
+class Pj_OS_API
+{
+public:
+    //
+    // 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 );
@@ -314,30 +755,32 @@
 };
 
-
-inline pj_status_t PJ_Time_Val::gettimeofday()
-{
-    return PJ_OS::gettimeofday(this);
+//
+// Timeval inlines.
+//
+inline pj_status_t Pj_Time_Val::gettimeofday()
+{
+    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)
-{
-    return PJ_OS::time_encode(pt, this);
+inline pj_status_t Pj_Time_Val::encode(const pj_parsed_time *pt)
+{
+    return Pj_OS_API::time_encode(pt, this);
 }
 
-inline pj_status_t PJ_Time_Val::to_gmt()
-{
-    return PJ_OS::time_local_to_gmt(this);
+inline pj_status_t Pj_Time_Val::to_gmt()
+{
+    return Pj_OS_API::time_local_to_gmt(this);
 }
 
-inline pj_status_t PJ_Time_Val::to_local()
-{
-    return PJ_OS::time_gmt_to_local(this);
+inline pj_status_t Pj_Time_Val::to_local()
+{
+    return Pj_OS_API::time_gmt_to_local(this);
 }
 
Index: pjproject/main/pjlib/include/pj++/pool.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/pool.hpp	(revision 35)
+++ pjproject/main/pjlib/include/pj++/pool.hpp	(revision 36)
@@ -1,4 +1,3 @@
 /* $Id$
- *
  */
 #ifndef __PJPP_POOL_H__
@@ -7,75 +6,206 @@
 #include <pj/pool.h>
 
-class PJ_Pool
+class Pj_Pool;
+class Pj_Caching_Pool;
+
+//
+// Base class for all Pjlib objects
+//
+class Pj_Object
 {
 public:
+    void *operator new(unsigned int class_size, Pj_Pool *pool);
+    void operator delete(void*);
+    void operator delete(void*, Pj_Pool*);
+
+    //
+    // Inline implementations at the end of this file.
+    //
+
+private:
+    // Can not use normal new operator; must use pool.
+    // e.g.:
+    //   obj = new(pool) Pj_The_Object(pool, ...);
+    //
+    void *operator new(unsigned int)
+    {}
+};
+
+
+//
+// Pool.
+//
+class Pj_Pool : public Pj_Object
+{
+public:
+    //
+    // Default constructor, initializes internal pool to NULL.
+    // Application must call attach() some time later.
+    //
+    Pj_Pool()
+        : p_(NULL)
+    {
+    }
+
+    //
+    // 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(this->pool_());
-    }
-
+	return pj_pool_getobjname(p_);
+    }
+
+    //
+    // Get pjlib compatible pool object.
+    //
     pj_pool_t *pool_()
     {
-	return (pj_pool_t*)this;
-    }
-
+	return p_;
+    }
+
+    //
+    // Get pjlib compatible pool object.
+    //
     const pj_pool_t *pool_() const
     {
-	return (const pj_pool_t*)this;
-    }
-
-    void release()
-    {
-	pj_pool_release(this->pool_());
-    }
-
+	return p_;
+    }
+
+    //
+    // Get pjlib compatible pool object.
+    //
+    pj_pool_t *pj_pool_t_()
+    {
+	return p_;
+    }
+
+    //
+    // Reset pool.
+    //
     void reset()
     {
-	pj_pool_reset(this->pool_());
-    }
-
+	pj_pool_reset(p_);
+    }
+
+    //
+    // Get current capacity.
+    //
     pj_size_t get_capacity()
     {
-	pj_pool_get_capacity(this->pool_());
-    }
-
+	pj_pool_get_capacity(p_);
+    }
+
+    //
+    // Get current total bytes allocated from the pool.
+    //
     pj_size_t get_used_size()
     {
-	pj_pool_get_used_size(this->pool_());
-    }
-
+	pj_pool_get_used_size(p_);
+    }
+
+    //
+    // Allocate.
+    //
     void *alloc(pj_size_t size)
     {
-	return pj_pool_alloc(this->pool_(), 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(this->pool_(), count, 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_;
 };
 
-class PJ_Caching_Pool
+
+//
+// Caching pool.
+//
+class Pj_Caching_Pool
 {
 public:
-    void init(pj_size_t max_capacity,
-	      const pj_pool_factory_policy *pol=&pj_pool_factory_default_policy)
-    {
-	pj_caching_pool_init(&cp_, pol, max_capacity);
-    }
-
-    void destroy()
+    //
+    // 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)
-    {
-	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_());
+    //
+    // 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_t*)(*cp_.factory.create_pool)(&cp_.factory, name, 
+                                                     initial_size, 
+                                                     increment_size, 
+                                                     callback);
     }
 
@@ -84,3 +214,31 @@
 };
 
+//
+// 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__ */
Index: pjproject/main/pjlib/include/pj++/proactor.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/proactor.hpp	(revision 35)
+++ pjproject/main/pjlib/include/pj++/proactor.hpp	(revision 36)
@@ -1,7 +1,6 @@
 /* $Id$
- *
  */
-#ifndef __PJPP_EVENT_HANDLER_H__
-#define __PJPP_EVENT_HANDLER_H__
+#ifndef __PJPP_PROACTOR_H__
+#define __PJPP_PROACTOR_H__
 
 #include <pj/ioqueue.h>
@@ -9,80 +8,474 @@
 #include <pj++/sock.hpp>
 #include <pj++/timer.hpp>
-
-class PJ_Proactor;
-
-
-class PJ_Event_Handler
+#include <pj/errno.h>
+
+class Pj_Proactor;
+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();
-
-    virtual pj_oshandle_t get_handle() = 0;
-
-    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);
+    //
+    // Constructor.
+    //
+    explicit Pj_Async_Op(Pj_Event_Handler *handler)
+        : handler_(handler)
+    {
+        pj_memset(this, 0, sizeof(pj_ioqueue_op_key_t));
+    }
+
+    //
+    // Check whether operation is still pending for this key.
+    //
+    bool is_pending();
+
+    //
+    // 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);
-
-    void destroy();
-
-    bool register_handler(PJ_Pool *pool, PJ_Event_Handler *handler);
-    void unregister_handler(PJ_Event_Handler *handler);
-
-    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);
-
-    bool handle_events(PJ_Time_Val *timeout);
-
-    pj_ioqueue_t *get_io_queue();
-    pj_timer_heap_t *get_timer_heap();
+    //
+    // 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;
+    }
+
+    //
+    // 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;
+    }
+
+    //
+    // Destructor.
+    //
+    ~Pj_Proactor()
+    {
+        destroy();
+    }
+
+    //
+    // Create proactor.
+    //
+    pj_status_t create( Pj_Pool *pool, pj_size_t max_fd, 
+			pj_size_t timer_entry_count)
+    {
+        pj_status_t status;
+
+        destroy();
+
+        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_Proactor() {}
+    pj_ioqueue_callback cb_;
+
+    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__ */
Index: pjproject/main/pjlib/include/pj++/scanner.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/scanner.hpp	(revision 35)
+++ pjproject/main/pjlib/include/pj++/scanner.hpp	(revision 36)
@@ -5,11 +5,11 @@
 #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); }
@@ -37,8 +37,8 @@
 };
 
-class PJ_Scanner
+class Pj_Scanner
 {
 public:
-    PJ_Scanner() {}
+    Pj_Scanner() {}
 
     enum
@@ -68,28 +68,28 @@
     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);
@@ -101,5 +101,5 @@
     }
 
-    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);
@@ -111,15 +111,15 @@
     }
 
-    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);
Index: pjproject/main/pjlib/include/pj++/sock.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/sock.hpp	(revision 35)
+++ pjproject/main/pjlib/include/pj++/sock.hpp	(revision 36)
@@ -1,4 +1,3 @@
 /* $Id$
- *
  */
 #ifndef __PJPP_SOCK_H__
@@ -6,66 +5,147 @@
 
 #include <pj/sock.h>
-
-class PJ_Addr
+#include <pj/string.h>
+
+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);
-    }
-
-    int cmp(const PJ_INET_Addr &rhs) const
-    {
-	return pj_sockaddr_cmp(this, &rhs);
-    }
-
-    bool operator==(const PJ_INET_Addr &rhs) const
-    {
-	return cmp(rhs) == 0;
-    }
+        pj_str_t s;
+	return pj_sockaddr_in_set_str_addr(this, pj_cstr(&s, addr));
+    }
+
+    //
+    // Compare for equality.
+    //
+    bool operator==(const Pj_Inet_Addr &rhs) const
+    {
+	return sin_family == rhs.sin_family &&
+               sin_addr.s_addr == rhs.sin_addr.s_addr &&
+               sin_port == rhs.sin_port;
+    }
+
+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)
     {
@@ -73,4 +153,7 @@
     }
 
+    //
+    // Get socket handle.
+    //
     pj_sock_t get_handle() const
     {
@@ -78,4 +161,7 @@
     }
 
+    //
+    // Get socket handle.
+    //
     pj_sock_t& get_handle()
     {
@@ -83,91 +169,183 @@
     }
 
-    bool socket(int af, int type, int proto, pj_uint32_t flag=0)
-    {
-	sock_ = pj_sock_socket(af, type, proto, flag);
-	return sock_ != -1;
-    }
-
-    bool bind(const PJ_INET_Addr &addr)
-    {
-	return pj_sock_bind(sock_, &addr, sizeof(PJ_INET_Addr)) == 0;
-    }
-
-    bool close()
-    {
-	return pj_sock_close(sock_) == 0;
-    }
-
-    bool getpeername(PJ_INET_Addr *addr)
-    {
-	int namelen;
-	return pj_sock_getpeername(sock_, addr, &namelen) == 0;
-    }
-
-    bool getsockname(PJ_INET_Addr *addr)
-    {
-	int namelen;
-	return pj_sock_getsockname(sock_, addr, &namelen) == 0;
-    }
-
-    bool getsockopt(int level, int optname, void *optval, int *optlen)
-    {
-	return pj_sock_getsockopt(sock_, level, optname, optval, optlen) == 0;
-    }
-
-    bool setsockopt(int level, int optname, const void *optval, int optlen)
-    {
-	return pj_sock_setsockopt(sock_, level, optname, optval, optlen) == 0;
-    }
-
-    bool ioctl(long cmd, pj_uint32_t *val)
-    {
-	return pj_sock_ioctl(sock_, cmd, val) == 0;
-    }
-
-    int recv(void *buf, int len, int flag = 0)
-    {
-	return pj_sock_recv(sock_, buf, len, flag);
-    }
-
-    int send(const void *buf, int len, int flag = 0)
-    {
-	return pj_sock_send(sock_, buf, len, flag);
+    //
+    // See if the socket is valid.
+    //
+    bool is_valid() const
+    {
+        return sock_ != PJ_INVALID_SOCKET;
+    }
+
+    //
+    // Create the socket.
+    //
+    pj_status_t create(int af, int type, int proto)
+    {
+	return pj_sock_socket(af, type, proto, &sock_);
+    }
+
+    //
+    // Bind socket.
+    //
+    pj_status_t bind(const Pj_Inet_Addr &addr)
+    {
+	return pj_sock_bind(sock_, &addr, sizeof(Pj_Inet_Addr));
+    }
+
+    //
+    // Close socket.
+    //
+    pj_status_t close()
+    {
+	pj_sock_close(sock_);
+    }
+
+    //
+    // Get peer socket name.
+    //
+    pj_status_t getpeername(Pj_Inet_Addr *addr)
+    {
+	return pj_sock_getpeername(sock_, addr, &addr->addrlen_);
+    }
+
+    //
+    // getsockname
+    //
+    pj_status_t getsockname(Pj_Inet_Addr *addr)
+    {
+	return pj_sock_getsockname(sock_, addr, &addr->addrlen_);
+    }
+
+    //
+    // getsockopt.
+    //
+    pj_status_t getsockopt(int level, int optname, 
+                           void *optval, int *optlen)
+    {
+	return pj_sock_getsockopt(sock_, level, optname, optval, optlen);
+    }
+
+    //
+    // setsockopt
+    // 
+    pj_status_t setsockopt(int level, int optname, 
+                           const void *optval, int optlen)
+    {
+	return pj_sock_setsockopt(sock_, level, optname, optval, optlen);
+    }
+
+    //
+    // receive data.
+    //
+    pj_ssize_t recv(void *buf, pj_size_t len, int flag = 0)
+    {
+        pj_ssize_t bytes = len;
+	if (pj_sock_recv(sock_, buf, &bytes, flag) != PJ_SUCCESS)
+            return -1;
+        return bytes;
+    }
+
+    //
+    // send data.
+    //
+    pj_ssize_t send(const void *buf, pj_ssize_t len, int flag = 0)
+    {
+        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)
-    {
-	return pj_sock_listen(sock_, backlog) == 0;
-    }
-
-    bool accept(PJ_Sock_Stream *new_sock, PJ_INET_Addr *addr, int *addrlen)
-    {
-	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)
-    {
-	return pj_sock_connect(sock_, &addr, sizeof(PJ_INET_Addr)) == 0;
-    }
-
-    bool shutdown(int how)
-    {
-	return pj_sock_shutdown(sock_, how) == 0;
+    //
+    // Default constructor.
+    //
+    Pj_Sock_Stream() 
+    {
+    }
+
+    //
+    // Initialize from a socket handle.
+    //
+    explicit Pj_Sock_Stream(pj_sock_t sock)
+        : Pj_Socket(sock)
+    {
+    }
+
+    //
+    // Copy constructor.
+    //
+    Pj_Sock_Stream(const Pj_Sock_Stream &rhs) : Pj_Socket(rhs) 
+    {
+    }
+
+    //
+    // 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_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);
     }
 
@@ -175,22 +353,74 @@
 #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)
-    {
-	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)
-    {
-	return pj_sock_sendto(sock_, buf, len, flag, &addr, sizeof(PJ_INET_Addr));
+    //
+    // Default constructor.
+    //
+    Pj_Sock_Dgram() 
+    {
+    }
+
+    //
+    // Initialize from a socket handle.
+    //
+    explicit Pj_Sock_Dgram(pj_sock_t sock)
+        : Pj_Socket(sock)
+    {
+    }
+
+    //
+    // 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__ */
Index: pjproject/main/pjlib/include/pj++/string.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/string.hpp	(revision 35)
+++ pjproject/main/pjlib/include/pj++/string.hpp	(revision 36)
@@ -1,4 +1,3 @@
 /* $Id$
- *
  */
 #ifndef __PJPP_STRING_H__
@@ -7,54 +6,89 @@
 #include <pj/string.h>
 #include <pj++/pool.hpp>
-
-class PJ_String : public pj_str_t
+#include <pj/assert.h>
+
+//
+// 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; 
-    }
-
-    explicit PJ_String(char *str) 
+	pj_assert(sizeof(Pj_String) == sizeof(pj_str_t));
+	ptr=NULL; 
+        slen=0; 
+    }
+
+    //
+    // 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
     {
@@ -62,4 +96,7 @@
     }
 
+    //
+    // Get the length of the string.
+    //
     pj_size_t size() const
     {
@@ -67,4 +104,7 @@
     }
 
+    //
+    // Get the string buffer.
+    //
     const char *buf() const
     {
@@ -72,4 +112,7 @@
     }
 
+    //
+    // Initialize buffer from char*.
+    //
     void set(char *str)
     {
@@ -77,9 +120,15 @@
     }
 
-    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)
     {
@@ -87,9 +136,15 @@
     }
 
-    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)
     {
@@ -97,4 +152,7 @@
     }
 
+    //
+    // Initialize from pair of pointers.
+    //
     void set(char *begin, char *end)
     {
@@ -102,19 +160,31 @@
     }
 
-    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)
     {
@@ -122,9 +192,15 @@
     }
 
-    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)
     {
@@ -132,4 +208,7 @@
     }
 
+    //
+    // Compare string.
+    //
     int strcmp(const char *s) const
     {
@@ -137,4 +216,7 @@
     }
 
+    //
+    // Compare string.
+    //
     int strcmp(const pj_str_t *s) const
     {
@@ -142,9 +224,15 @@
     }
 
-    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
     {
@@ -152,4 +240,7 @@
     }
 
+    //
+    // Compare string.
+    //
     int strncmp(const pj_str_t *s, pj_size_t len) const
     {
@@ -157,9 +248,15 @@
     }
 
-    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
     {
@@ -167,4 +264,7 @@
     }
 
+    //
+    // Compare string.
+    //
     int stricmp(const pj_str_t *s) const
     {
@@ -172,9 +272,15 @@
     }
 
-    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
     {
@@ -182,4 +288,7 @@
     }
 
+    //
+    // Compare string.
+    //
     int strnicmp(const pj_str_t *s, pj_size_t len) const
     {
@@ -187,9 +296,15 @@
     }
 
-    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
     {
@@ -197,4 +312,7 @@
     }
 
+    //
+    // Compare contents for equality.
+    //
     bool operator==(const pj_str_t *s) const
     {
@@ -202,9 +320,15 @@
     }
 
-    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)
     {
@@ -212,4 +336,7 @@
     }
 
+    //
+    // Find a character in the string.
+    //
     char *find(int chr)
     {
@@ -217,9 +344,15 @@
     }
 
-    void strcat(const PJ_String &rhs)
+    //
+    // Concatenate string.
+    //
+    void strcat(const Pj_String &rhs)
     {
 	pj_strcat(this, &rhs);
     }
 
+    //
+    // Left trim.
+    //
     void ltrim()
     {
@@ -227,4 +360,7 @@
     }
 
+    //
+    // Right trim.
+    //
     void rtrim()
     {
@@ -232,4 +368,7 @@
     }
 
+    //
+    // Left and right trim.
+    //
     void trim()
     {
@@ -237,12 +376,32 @@
     }
 
-    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); }
 };
 
Index: pjproject/main/pjlib/include/pj++/timer.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/timer.hpp	(revision 35)
+++ pjproject/main/pjlib/include/pj++/timer.hpp	(revision 36)
@@ -1,4 +1,3 @@
 /* $Id$
- *
  */
 #ifndef __PJPP_TIMER_H__
@@ -7,68 +6,107 @@
 #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)
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// Timer heap.
+//
+class Pj_Timer_Heap : public Pj_Object
+{
+public:
+    //
+    // Default constructor.
+    //
+    Pj_Timer_Heap() 
+        : ht_(NULL) 
     {
-	id = arg_id;
     }
 
-    void set_user_data(void *arg_user_data)
+    //
+    // Construct timer heap.
+    //
+    Pj_Timer_Heap(Pj_Pool *pool, pj_size_t initial_count)
+        : ht_(NULL)
     {
-	user_data = arg_user_data;
+        create(pool, initial_count);
     }
 
-    void *get_user_data() const
+    //
+    // Destructor.
+    //
+    ~Pj_Timer_Heap()
     {
-	return user_data;
+        destroy();
     }
 
-    const PJ_Time_Val &get_timeout() const
+    //
+    // Create
+    // 
+    pj_status_t create(Pj_Pool *pool, pj_size_t initial_count)
     {
-	pj_assert(sizeof(PJ_Time_Val) == sizeof(pj_time_val));
-	return (PJ_Time_Val&)_timer_value;
-    }
-};
-
-class PJ_Timer_Heap
-{
-public:
-    PJ_Timer_Heap() {}
-
-    bool create(PJ_Pool *pool, pj_size_t initial_count, 
-		unsigned flag = PJ_TIMER_HEAP_SYNCHRONIZE)
-    {
-	ht_ = pj_timer_heap_create(pool->pool_(), initial_count, flag);
-	return ht_ != NULL;
+        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()
     {
@@ -76,14 +114,41 @@
     }
 
-    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()
     {
@@ -91,10 +156,18 @@
     }
 
-    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);
Index: pjproject/main/pjlib/include/pj++/tree.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/tree.hpp	(revision 35)
+++ pjproject/main/pjlib/include/pj++/tree.hpp	(revision 36)
@@ -7,4 +7,7 @@
 #include <pj/rbtree.h>
 
+//
+// Tree.
+//
 class PJ_Tree
 {
Index: pjproject/main/pjlib/include/pj++/types.hpp
===================================================================
--- pjproject/main/pjlib/include/pj++/types.hpp	(revision 35)
+++ pjproject/main/pjlib/include/pj++/types.hpp	(revision 36)
@@ -7,28 +7,106 @@
 #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;
@@ -36,10 +114,12 @@
     }
  
-    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;
@@ -47,13 +127,16 @@
 
     /* 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); 
+    }
 
 };
Index: pjproject/main/pjlib/include/pj/errno.h
===================================================================
--- pjproject/main/pjlib/include/pj/errno.h	(revision 35)
+++ pjproject/main/pjlib/include/pj/errno.h	(revision 36)
@@ -211,4 +211,9 @@
  */
 #define PJ_EINVALIDOP	    (PJ_ERRNO_START_STATUS + 13)
+/**
+ * @hideinitializer
+ * Operation is cancelled.
+ */
+#define PJ_ECANCELLED	    (PJ_ERRNO_START_STATUS + 14)
 
 /** @} */   /* pj_errnum */
Index: pjproject/main/pjlib/include/pj/ioqueue.h
===================================================================
--- pjproject/main/pjlib/include/pj/ioqueue.h	(revision 35)
+++ pjproject/main/pjlib/include/pj/ioqueue.h	(revision 36)
@@ -298,12 +298,17 @@
 /**
  * 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.
+ *
+ * @see pj_ioqueue_is_pending
  */
 PJ_DECL(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key );
@@ -334,4 +339,39 @@
                                                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 );
+
 
 
Index: pjproject/main/pjlib/include/pj/os.h
===================================================================
--- pjproject/main/pjlib/include/pj/os.h	(revision 35)
+++ pjproject/main/pjlib/include/pj/os.h	(revision 36)
@@ -326,4 +326,13 @@
 
 /**
+ * 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.
  *
@@ -331,4 +340,13 @@
  */
 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);
 
 /**
@@ -340,4 +358,15 @@
 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);
 
 /**
Index: pjproject/main/pjlib/include/pj/timer.h
===================================================================
--- pjproject/main/pjlib/include/pj/timer.h	(revision 35)
+++ pjproject/main/pjlib/include/pj/timer.h	(revision 36)
@@ -111,16 +111,4 @@
 
 /**
- * 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.
  *
@@ -141,6 +129,4 @@
  *                  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.
  *
@@ -149,6 +135,37 @@
 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 );
 
 /**
@@ -216,5 +233,5 @@
  */
 PJ_DECL(pj_status_t) pj_timer_heap_earliest_time( pj_timer_heap_t *ht, 
-					   pj_time_val *timeval);
+					          pj_time_val *timeval);
 
 /**
@@ -222,11 +239,13 @@
  * 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.
- */
-PJ_DECL(int) pj_timer_heap_poll( pj_timer_heap_t *ht, pj_time_val *next_delay);
+ *
+ * @return           The number of timers expired.
+ */
+PJ_DECL(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht, 
+                                      pj_time_val *next_delay);
 
 /**
Index: pjproject/main/pjlib/src/pj/errno.c
===================================================================
--- pjproject/main/pjlib/src/pj/errno.c	(revision 35)
+++ pjproject/main/pjlib/src/pj/errno.c	(revision 36)
@@ -30,5 +30,6 @@
     { PJ_EBUSY,         "Object is busy"},
     { PJ_ENOTSUP,	"Option/operation is not supported"},
-    { PJ_EINVALIDOP,	"Invalid operation"}
+    { PJ_EINVALIDOP,	"Invalid operation"},
+    { PJ_ECANCELLED,    "Operation cancelled"}
 };
 
Index: pjproject/main/pjlib/src/pj/file_io_ansi.c
===================================================================
--- pjproject/main/pjlib/src/pj/file_io_ansi.c	(revision 35)
+++ pjproject/main/pjlib/src/pj/file_io_ansi.c	(revision 36)
@@ -68,4 +68,5 @@
     written = fwrite(data, 1, *size, (FILE*)fd);
     if (ferror((FILE*)fd)) {
+        *size = -1;
         return PJ_RETURN_OS_ERROR(errno);
     }
@@ -84,4 +85,5 @@
     bytes = fread(data, 1, *size, (FILE*)fd);
     if (ferror((FILE*)fd)) {
+        *size = -1;
         return PJ_RETURN_OS_ERROR(errno);
     }
Index: pjproject/main/pjlib/src/pj/ioqueue_common_abs.c
===================================================================
--- pjproject/main/pjlib/src/pj/ioqueue_common_abs.c	(revision 35)
+++ pjproject/main/pjlib/src/pj/ioqueue_common_abs.c	(revision 36)
@@ -229,4 +229,6 @@
         if (h->fd_type == PJ_SOCK_DGRAM) {
             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);
@@ -269,4 +271,5 @@
                 /* Write completion of the whole stream. */
                 pj_list_erase(write_op);
+                write_op->op = 0;
 
                 /* Clear operation if there's no more data to send. */
@@ -315,4 +318,5 @@
 	accept_op = h->accept_list.next;
         pj_list_erase(accept_op);
+        accept_op->op = 0;
 
 	/* Clear bit in fdset if there is no more pending accept */
@@ -348,4 +352,5 @@
         read_op = h->read_list.next;
         pj_list_erase(read_op);
+        read_op->op = 0;
 
         /* Clear fdset if there is no pending read. */
@@ -477,4 +482,7 @@
     PJ_CHECK_STACK();
 
+    read_op = (struct read_operation*)op_key;
+    read_op->op = 0;
+
     /* Try to see if there's data immediately available. 
      */
@@ -497,6 +505,4 @@
      * 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;
@@ -531,4 +537,7 @@
     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. 
@@ -553,6 +562,4 @@
      * 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;
@@ -587,4 +594,7 @@
     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:
@@ -625,5 +635,4 @@
      * Schedule asynchronous send.
      */
-    write_op = (struct write_operation*)op_key;
     write_op->op = PJ_IOQUEUE_OP_SEND;
     write_op->buf = (void*)data;
@@ -660,4 +669,7 @@
     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:
@@ -703,5 +715,4 @@
      * Schedule asynchronous send.
      */
-    write_op = (struct write_operation*)op_key;
     write_op->op = PJ_IOQUEUE_OP_SEND_TO;
     write_op->buf = (void*)data;
@@ -736,4 +747,7 @@
     /* 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:
@@ -768,6 +782,4 @@
      * connection available.
      */
-    accept_op = (struct accept_operation*)op_key;
-
     accept_op->op = PJ_IOQUEUE_OP_ACCEPT;
     accept_op->accept_fd = new_sock;
@@ -822,2 +834,81 @@
 #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;
+}
+
Index: pjproject/main/pjlib/src/pj/ioqueue_winnt.c
===================================================================
--- pjproject/main/pjlib/src/pj/ioqueue_winnt.c	(revision 35)
+++ pjproject/main/pjlib/src/pj/ioqueue_winnt.c	(revision 36)
@@ -892,2 +892,36 @@
 #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;
+}
+
Index: pjproject/main/pjlib/src/pj/os_core_unix.c
===================================================================
--- pjproject/main/pjlib/src/pj/os_core_unix.c	(revision 35)
+++ pjproject/main/pjlib/src/pj/os_core_unix.c	(revision 36)
@@ -560,8 +560,37 @@
 
 /*
+ * 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_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_atomic_value_t new_value;
+
     PJ_CHECK_STACK();
 
@@ -569,8 +598,10 @@
     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
+
+    return new_value;
 }
 
@@ -580,13 +611,27 @@
 PJ_DEF(void) pj_atomic_dec(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_dec_and_get(atomic_var);
+}
+
+/*
+ * 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 )
+{
+    pj_atomic_value_t new_value;
+
+#if PJ_HAS_THREADS
+    pj_mutex_lock(atomic_var->mutex);
+#endif
+    
+    atomic_var->value += value;
+    new_value = atomic_var->value;
+
+#if PJ_HAS_THREADS
+    pj_mutex_unlock(atomic_var->mutex);
+#endif
+
+    return new_value;
 }
 
@@ -594,17 +639,9 @@
  * pj_atomic_add()
  */ 
-PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var, pj_atomic_value_t value )
-{
-#if PJ_HAS_THREADS
-    pj_mutex_lock(atomic_var->mutex);
-#endif
-    
-    atomic_var->value += value;
-
-#if PJ_HAS_THREADS
-    pj_mutex_unlock(atomic_var->mutex);
-#endif
-}
-
+PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var, 
+                            pj_atomic_value_t value )
+{
+    pj_atomic_add_and_get(atomic_var, value);
+}
 
 ///////////////////////////////////////////////////////////////////////////////
Index: pjproject/main/pjlib/src/pj/os_core_win32.c
===================================================================
--- pjproject/main/pjlib/src/pj/os_core_win32.c	(revision 35)
+++ pjproject/main/pjlib/src/pj/os_core_win32.c	(revision 36)
@@ -514,12 +514,12 @@
 
 /*
- * pj_atomic_inc()
- */
-PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
+ * 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
-    InterlockedIncrement(&atomic_var->value);
+    return InterlockedIncrement(&atomic_var->value);
 #else
 #   error Fix Me
@@ -528,12 +528,20 @@
 
 /*
- * pj_atomic_dec()
- */
-PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
+ * pj_atomic_inc()
+ */
+PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
+{
+    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
-    InterlockedDecrement(&atomic_var->value);
+    return InterlockedDecrement(&atomic_var->value);
 #else
 #   error Fix me
@@ -542,4 +550,12 @@
 
 /*
+ * pj_atomic_dec()
+ */
+PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
+{
+    pj_atomic_dec_and_get(atomic_var);
+}
+
+/*
  * pj_atomic_add()
  */
@@ -547,8 +563,25 @@
 			    pj_atomic_value_t 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
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 /*
Index: pjproject/main/pjlib/src/pj/timer.c
===================================================================
--- pjproject/main/pjlib/src/pj/timer.c	(revision 35)
+++ pjproject/main/pjlib/src/pj/timer.c	(revision 36)
@@ -15,7 +15,11 @@
 #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)
 
 
@@ -34,6 +38,12 @@
     pj_size_t cur_size;
 
-    /** Mutex for synchronization, or NULL */
-    pj_mutex_t *mutex;
+    /** Max timed out entries to process per poll. */
+    unsigned max_entries_per_poll;
+
+    /** Lock object. */
+    pj_lock_t *lock;
+
+    /** Autodelete lock. */
+    pj_bool_t auto_delete_lock;
 
     /**
@@ -72,6 +82,6 @@
 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);
     }
 }
@@ -79,6 +89,6 @@
 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);
     }
 }
@@ -320,5 +330,5 @@
            /* size of each entry: */
            (count+2) * (sizeof(pj_timer_entry*)+sizeof(pj_timer_id_t)) +
-           /* mutex, pool etc: */
+           /* lock, pool etc: */
            132;
 }
@@ -329,5 +339,4 @@
 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)
 {
@@ -350,20 +359,11 @@
     ht->max_size = size;
     ht->cur_size = 0;
+    ht->max_entries_per_poll = DEFAULT_MAX_TIMED_OUT_PER_POLL;
     ht->timer_ids_freelist = 1;
     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.
@@ -387,4 +387,32 @@
 }
 
+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,
@@ -434,10 +462,11 @@
 }
 
-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;
-
-    PJ_ASSERT_RETURN(ht, -1);
+    unsigned count;
+
+    PJ_ASSERT_RETURN(ht, 0);
 
     if (!ht->cur_size && next_delay) {
@@ -451,14 +480,13 @@
     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) {
@@ -475,4 +503,6 @@
 PJ_DEF(pj_size_t) pj_timer_heap_count( pj_timer_heap_t *ht )
 {
+    PJ_ASSERT_RETURN(ht, 0);
+
     return ht->cur_size;
 }
Index: pjproject/main/pjlib/src/pjlib++-test/main.cpp
===================================================================
--- pjproject/main/pjlib/src/pjlib++-test/main.cpp	(revision 36)
+++ pjproject/main/pjlib/src/pjlib++-test/main.cpp	(revision 36)
@@ -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;
+}
+
