aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2007-05-22 19:25:59 +0000
committerVincent Richard <[email protected]>2007-05-22 19:25:59 +0000
commit8c6ba0e0587b4b28044385da90af408d72a0da01 (patch)
tree9a5ff41766dc96c9808bccc1777b305ed4d78022
parentFail if GNU TLS or GNU SASL dev packages are required but not installed. (diff)
downloadvmime-8c6ba0e0587b4b28044385da90af408d72a0da01.tar.gz
vmime-8c6ba0e0587b4b28044385da90af408d72a0da01.zip
Fixed bug #1721186: thread-safe reference counting.
-rw-r--r--ChangeLog5
-rw-r--r--SConstruct12
-rw-r--r--m4/acx_pthread.m4235
-rw-r--r--m4/ost_pthread.m4582
-rw-r--r--src/object.cpp4
-rw-r--r--src/utility/smartPtr.cpp131
-rw-r--r--src/utility/smartPtrInt.cpp301
-rw-r--r--vmime/utility/smartPtr.hpp60
-rw-r--r--vmime/utility/smartPtrInt.hpp107
9 files changed, 1266 insertions, 171 deletions
diff --git a/ChangeLog b/ChangeLog
index c603d3c3..14111224 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,11 @@
VERSION 0.8.2cvs
================
+2007-05-22 Vincent Richard <[email protected]>
+
+ * Implemented thread-safe reference counting for smart pointers,
+ whenever possible (GCC built-in functions / pthread / Win32).
+
2007-03-28 Vincent Richard <[email protected]>
* SMTPTransport.cpp: better parsing of ESMTP extensions.
diff --git a/SConstruct b/SConstruct
index b5020601..cc098b85 100644
--- a/SConstruct
+++ b/SConstruct
@@ -151,6 +151,7 @@ libvmime_sources = [
'utility/progressListener.cpp', 'utility/progressListener.hpp',
'utility/random.cpp', 'utility/random.hpp',
'utility/smartPtr.cpp', 'utility/smartPtr.hpp',
+ 'utility/smartPtrInt.cpp', 'utility/smartPtrInt.hpp',
'utility/stream.cpp', 'utility/stream.hpp',
'utility/stringProxy.cpp', 'utility/stringProxy.hpp',
'utility/stringUtils.cpp', 'utility/stringUtils.hpp',
@@ -634,6 +635,8 @@ if env['with_tls'] == 'yes':
env.ParseConfig('pkg-config --cflags --libs ' + libgnutls_pc)
+env.Append(CXXFLAGS = ['-pthread'])
+
# Generate help text for command line options
Help(opts.GenerateHelpText(env))
@@ -860,6 +863,7 @@ config_hpp.write("""
// Additional defines
#define VMIME_HAVE_GETADDRINFO 1
+#define VMIME_HAVE_PTHREAD 1
#endif // VMIME_CONFIG_HPP_INCLUDED
@@ -961,7 +965,7 @@ Default(libVmime)
if env['build_tests'] == 'yes':
if env['debug'] == 'yes':
env = env.Copy()
- env.Append(LIBS = ['cppunit', 'dl', packageVersionedGenericName + '-debug'])
+ env.Append(LIBS = ['cppunit', 'dl', packageVersionedGenericName + '-debug', 'pthread'])
env.Append(LIBPATH=['.'])
Default(
env.Program(
@@ -1320,6 +1324,8 @@ AM_PROG_CC_C_O
AM_ICONV
+OST_LIB_PTHREAD # from GNU Commons C++
+
#
# Some checks
@@ -1713,6 +1719,10 @@ if test "x$VMIME_DETECT_PLATFORM" = "xposix"; then
AC_CHECK_FUNC(getaddrinfo, [VMIME_ADDITIONAL_DEFINES="$VMIME_ADDITIONAL_DEFINES HAVE_GETADDRINFO"])
fi
+# -- pthreads (POSIX)
+
+ACX_PTHREAD([VMIME_ADDITIONAL_DEFINES="$VMIME_ADDITIONAL_DEFINES HAVE_PTHREAD"])
+
""")
diff --git a/m4/acx_pthread.m4 b/m4/acx_pthread.m4
new file mode 100644
index 00000000..b7f692a9
--- /dev/null
+++ b/m4/acx_pthread.m4
@@ -0,0 +1,235 @@
+dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl This macro figures out how to build C programs using POSIX threads.
+dnl It sets the PTHREAD_LIBS output variable to the threads library and
+dnl linker flags, and the PTHREAD_CFLAGS output variable to any special
+dnl C compiler flags that are needed. (The user can also force certain
+dnl compiler flags/libs to be tested by setting these environment
+dnl variables.)
+dnl
+dnl Also sets PTHREAD_CC to any special C compiler that is needed for
+dnl multi-threaded programs (defaults to the value of CC otherwise).
+dnl (This is necessary on AIX to use the special cc_r compiler alias.)
+dnl
+dnl NOTE: You are assumed to not only compile your program with these
+dnl flags, but also link it with them as well. e.g. you should link
+dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
+dnl $LIBS
+dnl
+dnl If you are only building threads programs, you may wish to use
+dnl these variables in your default LIBS, CFLAGS, and CC:
+dnl
+dnl LIBS="$PTHREAD_LIBS $LIBS"
+dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+dnl CC="$PTHREAD_CC"
+dnl
+dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
+dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
+dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
+dnl default action will define HAVE_PTHREAD.
+dnl
+dnl Please let the authors know if this macro fails on any platform, or
+dnl if you have any other suggestions or comments. This macro was based
+dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with
+dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros
+dnl posted by Alejandro Forero Cuervo to the autoconf macro repository.
+dnl We are also grateful for the helpful feedback of numerous users.
+dnl
+dnl @category InstalledPackages
+dnl @author Steven G. Johnson <[email protected]>
+dnl @version 2005-01-14
+dnl @license GPLWithACException
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test x"$acx_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+ *solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthread or
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+ ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
+ if test x"$acx_pthread_config" = xno; then continue; fi
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_TRY_LINK([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+ [acx_pthread_ok=yes])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test "x$acx_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ attr_name=unknown
+ for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ AC_TRY_LINK([#include <pthread.h>], [int attr=$attr;],
+ [attr_name=$attr; break])
+ done
+ AC_MSG_RESULT($attr_name)
+ if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+ [Define to necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case "${host_cpu}-${host_os}" in
+ *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+ *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with cc_r
+ AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+ PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ acx_pthread_ok=no
+ $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
diff --git a/m4/ost_pthread.m4 b/m4/ost_pthread.m4
new file mode 100644
index 00000000..d427c735
--- /dev/null
+++ b/m4/ost_pthread.m4
@@ -0,0 +1,582 @@
+dnl Copyright (C) 1999-2001 Open Source Telecom Corporation.
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+AC_DEFUN([OST_LIB_PTHREAD],
+[
+ AC_REQUIRE([OST_SYS_POSIX])
+ AC_REQUIRE([OST_CC_SYSTIME])
+ THREAD_FLAGS=""
+ THREAD_LIBS=""
+ ost_cv_thread_library="none"
+ ost_cv_rt_library="none"
+ ost_cv_cxx_mode=false
+
+ AC_ARG_WITH(pthread, [ --with-pthread[=lib] using specified pthread library],
+ [if test "$withval" != "" ; then ost_cv_thread_library=$withval ; fi]
+ )
+
+ AC_ARG_WITH(linuxthreads, [ --with-linuxthreads use linux kernel mode library],
+ [ost_cv_thread_library=lthread
+ AC_DEFINE(WITH_LINUXTHREADS, [1], [bsd system using linuxthreads])
+ if test "$withval" != "yes" ; then
+ THREAD_FLAGS="-D__USE_GNU -D__USE_UNIX98 -I$withval $THREAD_FLAGS"
+ CFLAGS="-D__USE_GNU -D__USE_UNIX98 -I$withval $CFLAGS"
+ else
+ THREAD_FLAGS="-D__USE_GNU -D__USE_UNIX98 -I/usr/local/include/pthread/linuxthreads $THREAD_FLAGS"
+ CFLAGS="-D__USE_GNU -D__USE_UNIX98 -I/usr/local/include/pthread/linuxthreads $CFLAGS"
+ fi
+ ])
+
+ AC_CHECK_HEADERS(pthread.h, [
+ AC_DEFINE(HAVE_PTHREAD_H, [1], [posix thread header])
+ ost_cv_posix_threads=yes],
+ ost_cv_posix_threads=no)
+
+ if test $ost_cv_posix_threads = no ; then
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ SAVE_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS -pthread"
+ AC_TRY_COMPILE([#include <pthread.h>],[],
+ AC_DEFINE(HAVE_PTHREAD_H, [1])
+ ost_cv_cxx_mode=true
+ ost_cv_posix_threads=yes)
+ CXXFLAGS="$SAVE_CXXFLAGS"
+ AC_LANG_RESTORE
+ fi
+
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+
+ ost_cv_posix_atomic=no
+ AC_CHECK_HEADERS(sys/atomic_op.h,[
+ AC_DEFINE(HAVE_ATOMIC_AIX, [1], [atomic aix operations])
+ ])
+ AC_CHECK_HEADERS([sys/atomic.h],
+ ost_cv_posix_sys_atomic=yes,
+ ost_cv_posix_sys_atomic=no)
+ if test $ost_cv_posix_sys_atomic = yes ; then
+ AC_MSG_CHECKING([for atomic_t])
+ AC_TRY_COMPILE([#include <sys/atomic.h>],
+ [
+ atomic_t at; at.counter = 1;
+ atomic_dec_and_test(&at);
+ atomic_sub(4, &at);
+ atomic_inc(&at);
+ atomic_add(3, &at);
+ ],
+ [ost_cv_posix_atomic=yes
+ AC_DEFINE(HAVE_WORKING_SYS_ATOMIC_H, [1], [has usable atomic functions])],
+ [ost_cv_posix_atomic=no])
+ AC_MSG_RESULT($ost_cv_posix_atomic)
+ fi
+
+ dnl check for gcc's bits/atomicity and the atomic functions therein
+ AC_CHECK_HEADERS([bits/atomicity.h],
+ ost_cv_bits_atomicity=yes,
+ ost_cv_bits_atomicity=no)
+ if test $ost_cv_bits_atomicity = yes ; then
+ AC_MSG_CHECKING([for _Atomic_word])
+ AC_TRY_COMPILE([#include <bits/atomicity.h>],
+ [
+ _Atomic_word i = 0;
+ __atomic_add(&i, 1);
+ __exchange_and_add(&i, 1);
+ ],
+ [ost_cv_gcc_atomic=yes
+ AC_DEFINE(HAVE_GCC_BITS_ATOMIC, [1], [has gcc atomic functions])],
+ [ost_cv_gcc_atomic=no])
+ AC_MSG_RESULT($ost_cv_gcc_atomic)
+
+ AC_MSG_CHECKING([for __gnu_cxx::_Atomic_word])
+ AC_TRY_COMPILE([#include <bits/atomicity.h>],
+ [
+ using namespace __gnu_cxx;
+ _Atomic_word i = 0;
+ __atomic_add(&i, 1);
+ __exchange_and_add(&i, 1);
+ ],
+ [ost_cv_gcc_cxx_atomic=yes
+ AC_DEFINE(HAVE_GCC_CXX_BITS_ATOMIC, [1],
+ [has __gnu_cxx atomic functions])],
+ [ost_cv_gcc_cxx_atomic=no])
+ AC_MSG_RESULT($ost_cv_gcc_cxx_atomic)
+ fi
+
+AC_LANG_RESTORE
+
+ if test "$target" = NONE ; then
+ targetdir=""
+ else
+ targetdir="$target"
+ fi
+
+ AC_CHECK_HEADERS(thread.h)
+ if test "$prefix" = NONE ; then
+ thrprefix="/usr/$targetdir/include"
+ if test -d /usr/$targetdir/sys-include ; then
+ thrprefix="$prefix/$targetdir/sys-include" ; fi
+ else
+ thrprefix="$prefix/$targetdir/include"
+ if test -d "$prefix/$targetdir/sys-include" ; then
+ thrprefix="$prefix/$targetdir/sys-include" ; fi
+ fi
+
+ if test ! -f $thrprefix/thread.h ; then
+ thrprefix=/usr/include
+ fi
+
+ AC_SUBST(thrprefix)
+
+ if test $ost_cv_posix_threads = yes ; then
+ if test "$ost_cv_thread_library" = "none" ; then
+
+ ost_cv_thread_flags=""
+ for flags in -kthread -pthread -mthreads -pthreads -Kthread --threadsafe -mt ; do
+
+ AC_MSG_CHECKING(whether ${CC-cc} accepts $flags)
+ echo 'void f(){}' >conftest.c
+ if test -z "`${CC-cc} $flags -c conftest.c 2>&1`"; then
+ ost_cv_thread_flags=$flags
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ rm -f conftest*
+ if test ! -z "$ost_cv_thread_flags" ; then break ; fi
+ done
+# if test "$ost_cv_prog_cc_pthread" = "no" ; then
+# AC_CACHE_CHECK(whether ${CC-cc} accepts -mthreads,
+# ost_cv_prog_cc_mthreads,
+# [echo 'void f(){}' >conftest.c
+# if test -z "`${CC-cc} -mthreads -c conftest.c 2>&1`"; then
+# ost_cv_prog_cc_mthreads=yes
+# else
+# ost_cv_prog_cc_mthreads=no
+# fi
+# rm -f conftest*
+# ])
+# fi
+ ost_cv_thread_library=none
+ AC_CHECK_LIB(pthread, pthread_self,
+ ost_cv_thread_library=pthread,
+ AC_CHECK_LIB(c_r, pthread_self,
+ ost_cv_thread_library=c_r,
+ AC_CHECK_LIB(pthread, pthread_kill,
+ ost_cv_thread_library=pthread,
+ AC_CHECK_LIB(pthreads, pthread_self,
+ ost_cv_thread_library=pthreads,
+ AC_CHECK_LIB(thread, pthread_self,
+ ost_cv_thread_library=thread)))))
+
+ if test $ost_cv_thread_library = none ; then
+ AC_CHECK_LIB(gthreads, pthread_self,[
+ AC_CHECK_LIB(malloc, malloc)
+ ost_cv_thread_library=gthreads])
+ fi
+ if test $ost_cv_thread_library = none ; then
+ AC_CHECK_LIB(cma, pthread_self,
+ ost_cv_thread_library=cma)
+ fi
+
+ if test $ost_cv_thread_library = none ; then
+ AC_CHECK_LIB(c, pthread_self,
+ ost_cv_thread_library=c)
+ fi
+
+ if test $ost_cv_thread_library = none ; then
+ AC_MSG_ERROR(no library for posix threads found!)
+ fi
+ else
+# ost_cv_prog_cc_pthread=no
+# ost_cv_prog_cc_mthreads=no
+ ost_cv_thread_flags=""
+ fi
+
+ AC_CHECK_LIB(${ost_cv_thread_library}, pthread_mach_thread_np,
+ AC_DEFINE(HAVE_PTHREAD_MACH_THREAD_NP, [1], [has mach link])
+ )
+
+ AC_CHECK_LIB(${ost_cv_thread_library}, nanosleep,
+ AC_DEFINE(HAVE_PTHREAD_NANOSLEEP, [1], [has nanosleep]),[
+ AC_CHECK_LIB(posix4, nanosleep,[
+ AC_DEFINE(HAVE_PTHREAD_NANOSLEEP, [1])
+ THREAD_LIBS="$THREAD_LIBS -lposix4"
+ ],[
+ AC_CHECK_LIB(rt, nanosleep,[
+ AC_DEFINE(HAVE_PTHREAD_NANOSLEEP, [1])
+ ost_cv_rt_library="-lrt"])
+ ])
+
+ ])
+
+ AC_CHECK_LIB(rt, clock_gettime,[
+ ost_cv_rt_library="-lrt"
+ AC_DEFINE(HAVE_HIRES_TIMER, [1], [have hires])
+ ],[
+ AC_CHECK_FUNCS(clock_gettime,[
+ AC_DEFINE(HAVE_HIRES_TIMER, [1], [have hires])
+ ])
+ ])
+
+ AC_CHECK_LIB(rt, mlockall,[
+ AC_DEFINE(HAVE_MLOCK, [1], [have mlock])
+ AC_DEFINE(HAVE_MLOCKALL, [1], [have memlockall])
+ ost_cv_rt_library="-lrt"],
+ [
+ AC_CHECK_FUNCS(mlock)
+ AC_CHECK_FUNCS(mlockall)
+ ])
+
+ if test "$ost_cv_rt_library" != "none" ; then
+ THREAD_LIBS="$THREAD_LIBS $ost_cv_rt_library" ; fi
+
+ if test ! -z "$ost_cv_thread_flags" ; then
+ THREAD_LIBS="$THREAD_LIBS $ost_cv_thread_flags"
+ else
+ THREAD_LIBS="$THREAD_LIBS -l$ost_cv_thread_library"
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case "${host_cpu}-${host_os}" in
+ *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";;
+ *solaris* | alpha*-osf*) flag="-D_REENTRANT";;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ THREAD_FLAGS="$flag"
+ fi
+
+ AC_SUBST(THREAD_FLAGS)
+ AC_SUBST(THREAD_LIBS)
+# LIBS="$THREAD_LIBS $LIBS"
+ if test "$ost_cv_thread_library" != "lthread" ; then
+ AC_CHECK_HEADERS(pthread_np.h)
+ fi
+ AC_CHECK_HEADERS(semaphore.h)
+ AC_CHECK_HEADERS(sched.h)
+ AC_CHECK_HEADERS(sys/sched.h)
+ AC_CHECK_FUNCS(sched_getscheduler)
+ AC_CACHE_CHECK([for recursive mutex type support], ost_cv_mutex_recursive,
+ [
+ ost_cv_mutex_recursive="none"
+
+ if test "$ost_cv_cxx_mode" = true ; then
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ SAVE_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS -pthread"
+ fi
+
+ AC_TRY_COMPILE(
+ [#include <pthread.h>],
+ [
+ #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
+ #ifdef PTHREAD_MUTEX_RECURSIVE
+ #define PTHREAD_MUTEXTYPE_RECURSIVE PTHREAD_MUTEX_RECURSIVE
+ #endif
+ #endif
+ return (int)PTHREAD_MUTEXTYPE_RECURSIVE;
+ ],
+ ost_cv_mutex_recursive="portable",
+ [
+ AC_EGREP_HEADER(PTHREAD_MUTEXTYPE_RECURSIVE_NP,pthread.h,
+ ost_cv_mutex_recursive=non-portable)
+ AC_EGREP_HEADER(PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP, pthread.h,
+ ost_cv_mutex_recursive=lthread)
+ AC_EGREP_HEADER(PTHREAD_MUTEX_RECURSIVE_NP,pthread.h,
+ ost_cv_mutex_recursive=linux)
+ AC_EGREP_HEADER(MUTEX_TYPE_COUNTING_FAST,pthread.h,
+ ost_cv_mutex_recursive=counting)
+ ])
+ if test $ost_cv_mutex_recursive = "none" ; then
+ if test $ost_cv_thread_library = "lthread" ; then
+ ost_cv_mutex_recursive=linux
+ fi
+ fi
+ rm -f conftest*
+ ])
+
+ if test $ost_cv_mutex_recursive = "none" ; then
+ AC_TRY_COMPILE(
+ [#include <pthread.h>],
+ [return MUTEX_TYPE_COUNTING_FAST;],
+ ost_cv_mutex_recursive=counting)
+ fi
+
+ if test "$ost_cv_cxx_mode" = true ; then
+ CXXFLAGS="$SAVE_CXXFLAGS"
+ AC_LANG_RESTORE
+ fi
+
+
+ case $ost_cv_mutex_recursive in
+ non-portable)
+ AC_DEFINE(PTHREAD_MUTEXTYPE_RECURSIVE,
+ PTHREAD_MUTEXTYPE_RECURSIVE_NP, [mutex type])
+ ;;
+ linux)
+ AC_DEFINE(PTHREAD_MUTEXTYPE_RECURSIVE,
+ PTHREAD_MUTEX_RECURSIVE_NP)
+ ;;
+ counting)
+ AC_DEFINE(PTHREAD_MUTEXTYPE_RECURSIVE,
+ MUTEX_TYPE_COUNTING_FAST)
+ ;;
+ esac
+
+ AC_CHECK_LIB(${ost_cv_thread_library}, pthread_mutexattr_settype,
+ AC_DEFINE(HAVE_PTHREAD_MUTEXATTR_SETTYPE, [1], [has setttype]),
+ [
+ AC_CHECK_LIB(${ost_cv_thread_library}, pthread_mutexattr_settype_np,
+ AC_DEFINE(HAVE_PTHREAD_MUTEXATTR_SETTYPE_NP,
+ [1], [has non portable settype]))
+ AC_CHECK_LIB(${ost_cv_thread_library}, pthread_mutexattr_setkind_np,
+ AC_DEFINE(HAVE_PTHREAD_MUTEXATTR_SETKIND_NP,
+ [1], [has non portable setkind]))
+ ]
+ )
+
+ ost_cv_thread_rwlock=false
+ AC_CHECK_LIB(${ost_cv_thread_library}, pthread_rwlock_init,[
+ ost_cv_thread_rwlock=true
+ AC_DEFINE(HAVE_PTHREAD_RWLOCK, [1], [has rwlock support])])
+
+ AC_CHECK_LIB(c, pread,[
+ AC_DEFINE(HAVE_PREAD_PWRITE, [1], [has pwrite])],[
+ AC_CHECK_LIB(${ost_cv_thread_library}, pread,[
+ AC_DEFINE(HAVE_PREAD_PWRITE, [1])],[
+ AC_CHECK_LIB(c_r, pread,[AC_DEFINE(HAVE_PREAD_PWRITE)])
+ ])
+ ])
+
+ AC_CHECK_LIB(${ost_cv_thread_library}, pthread_suspend,
+ AC_DEFINE(HAVE_PTHREAD_SUSPEND, [1], [has suspend]))
+
+ AC_CHECK_LIB(${ost_cv_thread_library}, pthread_attr_setstacksize,
+ AC_DEFINE(HAVE_PTHREAD_ATTR_SETSTACKSIZE, [1], [has stack size]))
+
+ AC_CHECK_LIB(${ost_cv_thread_library}, pthread_yield_np,
+ AC_DEFINE(HAVE_PTHREAD_YIELD_NP, [1], [has np yield]),[
+ AC_CHECK_LIB(${ost_cv_thread_library}, pthread_yield,
+ AC_DEFINE(HAVE_PTHREAD_YIELD, [1], [has yield]),[
+ AC_CHECK_LIB(${ost_cv_thread_library}, sched_yield,
+ AC_DEFINE(HAVE_PTHREAD_SCHED_YIELD, [1], [has sched yield]))
+ ])
+ ])
+
+ AC_CHECK_LIB(${ost_cv_thread_library}, pthread_cancel,[
+ AC_DEFINE(HAVE_PTHREAD_CANCEL, [1], [has cancel])
+ AC_CHECK_LIB(${ost_cv_thread_library},
+ pthread_setcanceltype,
+ AC_DEFINE(HAVE_PTHREAD_SETCANCELTYPE, [1], [has setcanceltype]),
+ AC_CHECK_LIB($ost_cv_thread_library, pthread_setcanel,
+ AC_DEFINE(HAVE_PTHREAD_SETCANCEL, [1], [has setcancel])))
+ ],[
+ AC_CHECK_LIB(${ost_cv_thread_library},
+ pthread_setcanceltype,[
+ AC_DEFINE(HAVE_PTHREAD_CANCEL)
+ AC_DEFINE(HAVE_PTHREAD_SETCANCELTYPE)])
+
+ ])
+
+ AC_CHECK_LIB(${ost_cv_thread_library}, pthread_delay_np,
+ AC_DEFINE(HAVE_PTHREAD_DELAY_NP, [1], [has non portable delay]))
+
+ fi
+
+ UNAME=`uname`
+ if test "$UNAME" = "AIX" ; then
+ AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+ CC=$PTHREAD_CC
+ AC_DEFINE(COMMON_AIX_FIXES, [1], [aix fixes needed])
+ fi
+
+AH_BOTTOM([
+#ifdef HAVE_THREAD_H
+#include "@thrprefix@/thread.h"
+#if defined(i386) && defined(__svr4__) && !defined(__sun)
+#define _THR_UNIXWARE
+#endif
+#if defined(__SVR4) && defined(__sun)
+#define _THR_SUNOS5
+#else
+#if defined(__SVR4__) && defined(__SUN__)
+#define _THR_SUNOS5
+#endif
+#endif
+#endif
+
+#ifdef HAVE_WORKING_SYS_ATOMIC_H
+#include <sys/atomic.h>
+#define HAVE_ATOMIC
+#elif defined(HAVE_ATOMIC_AIX)
+#include <sys/atomic_op.h>
+#ifndef HAVE_ATOMIC
+#define HAVE_ATOMIC
+#endif
+#endif
+
+#if defined(__cplusplus)
+#if defined(HAVE_GCC_BITS_ATOMIC) || defined(HAVE_GCC_CXX_BITS_ATOMIC)
+#include <bits/atomicity.h>
+#define HAVE_ATOMIC
+#endif
+#endif
+
+#if defined(HAVE_PTHREAD_H) && ( defined(_THREAD_SAFE) || defined(_REENTRANT) )
+
+#ifdef __QNX__
+#define __EXT_QNX
+#endif
+
+#include <pthread.h>
+
+#ifdef HAVE_PTHREAD_NP_H
+#include <pthread_np.h>
+#endif
+
+#ifdef HAVE_SEMAPHORE_H
+#include <semaphore.h>
+#endif
+#ifdef _POSIX_PRIORITY_SCHEDULING
+#ifdef HAVE_SCHED_H
+#include <sched.h>
+#else
+#ifdef HAVE_SYS_SCHED_H
+#include <sys/sched.h>
+#endif
+#endif
+#endif
+
+#define __PTHREAD_H__
+#ifndef PTHREAD_MUTEXTYPE_RECURSIVE
+#ifdef MUTEX_TYPE_COUNTING_FAST
+#define PTHREAD_MUTEXTYPE_RECURSIVE MUTEX_TYPE_COUNTING_FAST
+#endif
+#endif
+#ifndef PTHREAD_MUTEXTYPE_RECURSIVE
+#ifdef PTHREAD_MUTEX_RECURSIVE
+#define PTHREAD_MUTEXTYPE_RECURSIVE PTHREAD_MUTEX_RECURSIVE
+#endif
+#endif
+#ifndef HAVE_PTHREAD_MUTEXATTR_SETTYPE
+#if HAVE_PTHREAD_MUTEXATTR_SETKIND_NP
+#ifndef PTHREAD_MUTEXTYPE_RECURSIVE
+#define PTHREAD_MUTEXTYPE_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
+#endif
+#define pthread_mutexattr_gettype(x, y) pthread_mutexattr_getkind_np(x, y)
+#define pthread_mutexattr_settype(x, y) pthread_mutexattr_setkind_np(x, y)
+#endif
+#if HAVE_PTHREAD_MUTEXATTR_SETTYPE_NP
+#ifndef PTHREAD_MUTEXTYPE_RECURSIVE
+#define PTHREAD_MUTEXTYPE_RECURSIVE PTHREAD_MUTEXTYPE_RECURSIVE_NP
+#endif
+#define pthread_mutexattr_settype(x, y) pthread_mutexattr_settype_np(x, y)
+#define pthread_mutexattr_gettype(x, y) pthread_mutexattr_gettype_np(x, y)
+#endif
+#endif
+
+#ifdef HAVE_PTHREAD_MACH_THREAD_NP
+#define _THR_MACH
+#endif
+
+#ifndef HAVE_PTHREAD_YIELD
+#ifdef HAVE_PTHREAD_YIELD_NP
+#define pthread_yield() pthread_yield_np()
+#define HAVE_PTHREAD_YIELD
+#endif
+#endif
+
+#ifndef HAVE_PTHREAD_YIELD
+#ifdef HAVE_PTHREAD_SCHED_YIELD
+#define pthread_yield() sched_yield()
+#define HAVE_PTHREAD_YIELD
+#endif
+#endif
+
+#ifndef HAVE_PTHREAD_DELAY
+#ifdef HAVE_PTHREAD_DELAY_NP
+#define HAVE_PTHREAD_DELAY
+#define pthread_delay(x) pthread_delay_np(x)
+#endif
+#if defined(HAVE_PTHREAD_NANOSLEEP)
+#ifndef HAVE_PTHREAD_DELAY
+#define HAVE_PTHREAD_DELAY
+#ifdef __FreeBSD__
+#ifdef __cplusplus
+extern "C" int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
+#endif
+#endif
+#define pthread_delay(x) nanosleep(x, NULL)
+#endif
+#endif
+#endif
+
+#ifdef HAVE_PTHREAD_ATTR_SETSTACK
+#ifndef PTHREAD_STACK_MIN
+#define PTHREAD_STACK_MIN 32768
+#endif
+#endif
+
+#ifndef HAVE_PTHREAD_CANCEL
+#ifdef SIGCANCEL
+#define CCXX_SIG_THREAD_CANCEL SIGCANCEL
+#else
+#define CCXX_SIG_THREAD_CANCEL SIGQUIT
+#endif
+#define pthread_cancel(x) pthread_kill(x, CCXX_SIG_THREAD_CANCEL)
+#define pthread_setcanceltype(x, y)
+#define pthread_setcancelstate(x, y)
+#endif
+
+#ifndef HAVE_PTHREAD_SETCANCELTYPE
+#ifdef HAVE_PTHREAD_SETCANCEL
+enum
+{ PTHREAD_CANCEL_ASYNCHRONOUS = CANCEL_ON,
+ PTHREAD_CANCEL_DEFERRED = CANCEL_OFF};
+enum
+{ PTHREAD_CANCEL_ENABLE = CANCEL_ON,
+ PTHREAD_CANCEL_DISABLE = CANCEL_OFF};
+#define pthread_setcancelstate(x, y) \
+ (y == NULL) ? pthread_setcancel(x) : *y = pthread_setcancel
+#define pthread_setcanceltype(x, y) \
+ (y == NULL) ? pthread_setasynccancel(x) | *y = pthread_setasynccancel(x)
+#else
+#define pthread_setcanceltype(x, y)
+#define pthread_setcancelstate(x, y)
+#endif
+#endif
+
+#ifdef _AIX
+#ifdef HAVE_PTHREAD_SUSPEND
+#undef HAVE_PTHREAD_SUSPEND
+#endif
+#endif
+
+#endif
+
+
+ ])
+
+])
+
diff --git a/src/object.cpp b/src/object.cpp
index 651aa1e1..c03653e9 100644
--- a/src/object.cpp
+++ b/src/object.cpp
@@ -33,13 +33,13 @@ namespace vmime
object::object()
- : m_refMgr(new utility::refManager(this))
+ : m_refMgr(utility::refManager::create(this))
{
}
object::object(const object&)
- : m_refMgr(new utility::refManager(this))
+ : m_refMgr(utility::refManager::create(this))
{
}
diff --git a/src/utility/smartPtr.cpp b/src/utility/smartPtr.cpp
index 16249df8..08a8f57c 100644
--- a/src/utility/smartPtr.cpp
+++ b/src/utility/smartPtr.cpp
@@ -29,135 +29,10 @@ namespace vmime {
namespace utility {
-// refManager
-
-refManager::refManager(object* obj)
- : m_object(obj), m_strongCount(1), m_weakCount(1)
-{
-}
-
-
-refManager::~refManager()
-{
-}
-
-
-const bool refManager::addStrong()
-{
- if (m_strongCount <= 0)
- return false;
-
- m_strongCount.increment();
- m_weakCount.increment();
-
- return true;
-}
-
-
-void refManager::releaseStrong()
-{
- m_strongCount.decrement();
-
- if (m_strongCount.compareExchange(0, -424242) == 0) // prevent from adding strong refs later
- deleteObject();
-
- releaseWeak();
-}
-
-
-void refManager::addWeak()
-{
- m_weakCount.increment();
-}
-
-
-void refManager::releaseWeak()
-{
- if (m_weakCount.decrement() == 0)
- deleteManager();
-}
-
-
-object* refManager::getObject()
-{
- return m_object;
-}
-
-
-void refManager::deleteManager()
-{
- delete this;
-}
-
-
-void refManager::deleteObject()
-{
- try
- {
- m_object->setRefManager(0);
- delete m_object;
- }
- catch (...)
- {
- // Exception in destructor
- }
-
- m_object = 0;
-}
-
-
-const long refManager::getStrongRefCount() const
-{
- return m_strongCount;
-}
-
-
-const long refManager::getWeakRefCount() const
-{
- return m_weakCount;
-}
-
-
-
-// refCounter
-
-refCounter::refCounter(const long initialValue)
- : m_value(initialValue)
-{
-}
-
-
-refCounter::~refCounter()
-{
-}
-
-
-const long refCounter::increment()
-{
- return ++m_value;
-}
-
-
-const long refCounter::decrement()
-{
- return --m_value;
-}
-
-
-const long refCounter::compareExchange(const long compare, const long exchangeWith)
-{
- const int prev = m_value;
-
- if (m_value == compare)
- m_value = exchangeWith;
-
- return prev;
-}
-
-
-refCounter::operator long() const
+void refManager::deleteObjectImpl(object* obj)
{
- return m_value;
+ obj->setRefManager(0);
+ delete obj;
}
diff --git a/src/utility/smartPtrInt.cpp b/src/utility/smartPtrInt.cpp
new file mode 100644
index 00000000..a3036310
--- /dev/null
+++ b/src/utility/smartPtrInt.cpp
@@ -0,0 +1,301 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2007 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#include "vmime/utility/smartPtrInt.hpp"
+#include "vmime/object.hpp"
+
+#if defined(_WIN32)
+# include <windows.h>
+#elif defined(VMIME_HAVE_PTHREAD)
+# include <pthread.h>
+#endif
+
+
+namespace vmime {
+namespace utility {
+
+
+// static
+refManager* refManager::create(object* obj)
+{
+ return new refManagerImpl(obj);
+}
+
+
+//
+// refManager
+//
+
+refManagerImpl::refManagerImpl(object* obj)
+ : m_object(obj), m_strongCount(1), m_weakCount(1)
+{
+}
+
+
+refManagerImpl::~refManagerImpl()
+{
+}
+
+
+const bool refManagerImpl::addStrong()
+{
+ if (m_strongCount <= 0)
+ return false;
+
+ m_strongCount.increment();
+ m_weakCount.increment();
+
+ return true;
+}
+
+
+void refManagerImpl::releaseStrong()
+{
+ if (m_strongCount.decrement() <= 0)
+ deleteObject();
+
+ releaseWeak();
+}
+
+
+void refManagerImpl::addWeak()
+{
+ m_weakCount.increment();
+}
+
+
+void refManagerImpl::releaseWeak()
+{
+ if (m_weakCount.decrement() <= 0)
+ deleteManager();
+}
+
+
+object* refManagerImpl::getObject()
+{
+ return m_object;
+}
+
+
+void refManagerImpl::deleteManager()
+{
+ delete this;
+}
+
+
+void refManagerImpl::deleteObject()
+{
+ try
+ {
+ deleteObjectImpl(m_object);
+ }
+ catch (...)
+ {
+ // Exception in destructor
+ }
+
+ m_object = 0;
+}
+
+
+const long refManagerImpl::getStrongRefCount() const
+{
+ return m_strongCount;
+}
+
+
+const long refManagerImpl::getWeakRefCount() const
+{
+ return m_weakCount;
+}
+
+
+
+//
+// refCounter
+//
+
+#ifdef _WIN32
+
+
+refCounter::refCounter(const long initialValue)
+ : m_value(initialValue)
+{
+}
+
+
+refCounter::~refCounter()
+{
+}
+
+
+const long refCounter::increment()
+{
+ return InterlockedIncrement(&m_value);
+}
+
+
+const long refCounter::decrement()
+{
+ return InterlockedDecrement(&m_value);
+}
+
+
+refCounter::operator long() const
+{
+ return m_value;
+}
+
+
+#elif defined(__GNUC__) && defined(__GLIBCPP__)
+
+
+refCounter::refCounter(const long initialValue)
+ : m_value(static_cast <int>(initialValue))
+{
+}
+
+
+refCounter::~refCounter()
+{
+}
+
+
+const long refCounter::increment()
+{
+#if __GNUC_MINOR__ < 4 && __GNUC__ < 4
+ return __exchange_and_add(&m_value, 1) + 1;
+#else
+ return __gnu_cxx::__exchange_and_add(&m_value, 1) + 1;
+#endif
+}
+
+
+const long refCounter::decrement()
+{
+#if __GNUC_MINOR__ < 4 && __GNUC__ < 4
+ return __exchange_and_add(&m_value, -1) - 1;
+#else
+ return __gnu_cxx::__exchange_and_add(&m_value, -1) - 1;
+#endif
+}
+
+
+refCounter::operator long() const
+{
+#if __GNUC_MINOR__ < 4 && __GNUC__ < 4
+ return static_cast <long>(__exchange_and_add(&m_value, 0));
+#else
+ return static_cast <long>(__gnu_cxx::__exchange_and_add(&m_value, 0));
+#endif
+}
+
+
+#elif defined(VMIME_HAVE_PTHREAD)
+
+
+refCounter::refCounter(const long initialValue)
+ : m_value(initialValue)
+{
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+ pthread_mutex_init(&m_mutex, &attr);
+ pthread_mutexattr_destroy(&attr);
+}
+
+
+refCounter::~refCounter()
+{
+ pthread_mutex_destroy(&m_mutex);
+}
+
+
+const long refCounter::increment()
+{
+ long value;
+
+ pthread_mutex_lock(&m_mutex);
+ value = ++m_value;
+ pthread_mutex_unlock(&m_mutex);
+
+ return value;
+}
+
+
+const long refCounter::decrement()
+{
+ long value;
+
+ pthread_mutex_lock(&m_mutex);
+ value = --m_value;
+ pthread_mutex_unlock(&m_mutex);
+
+ return value;
+}
+
+
+refCounter::operator long() const
+{
+ return m_value;
+}
+
+
+#else // not thread-safe implementation
+
+
+refCounter::refCounter(const long initialValue)
+ : m_value(initialValue)
+{
+}
+
+
+refCounter::~refCounter()
+{
+}
+
+
+const long refCounter::increment()
+{
+ return ++m_value;
+}
+
+
+const long refCounter::decrement()
+{
+ return --m_value;
+}
+
+
+refCounter::operator long() const
+{
+ return m_value;
+}
+
+
+#endif
+
+
+} // utility
+} // vmime
+
diff --git a/vmime/utility/smartPtr.hpp b/vmime/utility/smartPtr.hpp
index c52752ed..9b97121c 100644
--- a/vmime/utility/smartPtr.hpp
+++ b/vmime/utility/smartPtr.hpp
@@ -58,86 +58,66 @@ public:
};
-/** Reference counter for shared pointers.
- */
-
-class refCounter
-{
-public:
-
- refCounter(const long initialValue);
- ~refCounter();
-
- const long increment();
- const long decrement();
- const long compareExchange(const long compare, const long exchangeWith);
-
- operator long() const;
-
-private:
-
- long m_value;
-};
-
-
/** Manage the life cycle of an object.
*/
class refManager
{
+protected:
+
+ refManager() {}
+
public:
- refManager(object* obj);
- ~refManager();
+ virtual ~refManager() {}
+
+ /** Create a ref manager for the specified object.
+ *
+ * @return a new manager
+ */
+ static refManager* create(object* obj);
/** Add a strong reference to the managed object.
*/
- const bool addStrong();
+ virtual const bool addStrong() = 0;
/** Release a strong reference to the managed object.
* If it is the last reference, the object is destroyed.
*/
- void releaseStrong();
+ virtual void releaseStrong() = 0;
/** Add a weak reference to the managed object.
*/
- void addWeak();
+ virtual void addWeak() = 0;
/** Release a weak reference to the managed object.
* If it is the last weak reference, the manager is destroyed.
*/
- void releaseWeak();
+ virtual void releaseWeak() = 0;
/** Return a raw pointer to the managed object.
*
* @return pointer to the managed object
*/
- object* getObject();
+ virtual object* getObject() = 0;
/** Return the number of strong refs to this object.
* For debugging purposes only.
*
* @return strong reference count
*/
- const long getStrongRefCount() const;
+ virtual const long getStrongRefCount() const = 0;
/** Return the number of weak refs to this object.
* For debugging purposes only.
*
* @return weak reference count
*/
- const long getWeakRefCount() const;
-
-private:
+ virtual const long getWeakRefCount() const = 0;
- void deleteManager();
- void deleteObject();
-
-
- object* m_object;
+protected:
- refCounter m_strongCount;
- refCounter m_weakCount;
+ void deleteObjectImpl(object* obj);
};
diff --git a/vmime/utility/smartPtrInt.hpp b/vmime/utility/smartPtrInt.hpp
new file mode 100644
index 00000000..b47ce504
--- /dev/null
+++ b/vmime/utility/smartPtrInt.hpp
@@ -0,0 +1,107 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2007 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#ifndef VMIME_UTILITY_SMARTPTRIMPL_HPP_INCLUDED
+#define VMIME_UTILITY_SMARTPTRIMPL_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+#include "vmime/utility/smartPtr.hpp"
+
+
+namespace vmime {
+namespace utility {
+
+
+/** Reference counter for shared pointers.
+ */
+
+class refCounter
+{
+public:
+
+ refCounter(const long initialValue);
+ ~refCounter();
+
+ const long increment();
+ const long decrement();
+
+ operator long() const;
+
+private:
+
+#if defined(_WIN32)
+ long m_value;
+#elif defined(__GNUC__) && defined(__GLIBCPP__)
+ mutable volatile int m_value;
+#elif defined (VMIME_HAVE_PTHREAD)
+ volatile long m_value;
+ pthread_mutex_t m_mutex;
+#else // not thread-safe implementation
+ long m_value;
+#endif
+
+};
+
+
+/** Separate implementation of refManager, to avoid polluting global
+ * namespace with system-specific inclusions/definitions.
+ */
+
+class refManagerImpl : public refManager
+{
+public:
+
+ refManagerImpl(object* obj);
+ ~refManagerImpl();
+
+ const bool addStrong();
+ void releaseStrong();
+
+ void addWeak();
+ void releaseWeak();
+
+ object* getObject();
+
+ const long getStrongRefCount() const;
+ const long getWeakRefCount() const;
+
+private:
+
+ void deleteManager();
+ void deleteObject();
+
+
+ object* m_object;
+
+ refCounter m_strongCount;
+ refCounter m_weakCount;
+};
+
+
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_SMARTPTRIMPL_HPP_INCLUDED
+