complement-svn Mailing List for Complement (Page 6)
Status: Pre-Alpha
Brought to you by:
complement
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(61) |
Nov
(76) |
Dec
(39) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(33) |
Feb
(41) |
Mar
(16) |
Apr
|
May
(22) |
Jun
(14) |
Jul
(64) |
Aug
(60) |
Sep
(35) |
Oct
(34) |
Nov
(10) |
Dec
(5) |
2008 |
Jan
(4) |
Feb
(24) |
Mar
(10) |
Apr
(30) |
May
(15) |
Jun
(50) |
Jul
(20) |
Aug
(7) |
Sep
(8) |
Oct
(10) |
Nov
|
Dec
|
From: <com...@us...> - 2008-04-23 09:22:17
|
Revision: 1853 http://complement.svn.sourceforge.net/complement/?rev=1853&view=rev Author: complement Date: 2008-04-23 02:22:13 -0700 (Wed, 23 Apr 2008) Log Message: ----------- compiled with modern xmt/date_time Modified Paths: -------------- trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/smtp-batch.cc Property Changed: ---------------- trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/ trunk/complement/explore/app/SMTP-tools/smtp_server_ut/ Modified: trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile 2008-04-23 09:20:23 UTC (rev 1852) +++ trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile 2008-04-23 09:22:13 UTC (rev 1853) @@ -1,4 +1,4 @@ -# -*- Makefile -*- Time-stamp: <08/04/23 09:38:04 ptr> +# -*- Makefile -*- Time-stamp: <08/04/23 09:48:37 ptr> SRCROOT := ../../.. @@ -13,7 +13,7 @@ # LIBFS_DIR = ${CoMT_DIR}/../extern/custom/boost/libs/filesystem DEFS += -D_NO_TEST -INCLUDES += -I$(SRCROOT)/include -I$(STLPORT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR) +INCLUDES += -I$(SRCROOT)/include -I$(BOOST_INCLUDE_DIR) release-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR} -L${LIBSOCKIOS_DIR}/${OUTPUT_DIR} -L${LIBMISC_DIR}/${OUTPUT_DIR} dbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_DBG} -L${LIBSOCKIOS_DIR}/${OUTPUT_DIR_DBG} -L${LIBMISC_DIR}/${OUTPUT_DIR_DBG} Property changes on: trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch ___________________________________________________________________ Name: svn:ignore + obj Modified: trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile 2008-04-23 09:20:23 UTC (rev 1852) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile 2008-04-23 09:22:13 UTC (rev 1853) @@ -1,28 +1,26 @@ # -*- Makefile -*- Time-stamp: <04/05/06 14:30:08 ptr> -# $Id: Makefile,v 1.1 2004/06/16 14:24:07 ptr Exp $ -#SRCROOT := ../../../../extern/complement -SRCROOT := ../../../../../../island/workshop/explore -COMPILER_NAME := gcc +SRCROOT := ../../../.. include Makefile.inc -include ${SRCROOT}/Makefiles/top.mak +include ${SRCROOT}/Makefiles/gmake/top.mak +LIBMT_DIR = ${CoMT_DIR}/lib/mt +LIBSOCKIOS_DIR = ${CoMT_DIR}/lib/sockios +LIBMISC_DIR = ${CoMT_DIR}/lib/misc +LIBBOOSTRE_DIR = ${CoMT_DIR}/../extern/custom/boost/lib/regex DEFS += -D_NO_TEST -INCLUDES += -I$(SRCROOT)/include -I$(STLPORT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR) +INCLUDES += -I$(SRCROOT)/include -I$(BOOST_INCLUDE_DIR) -release-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR} -Wl,-rpath=${STLPORT_LIB_DIR} -stldbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_STLDBG} -Wl,-rpath=${STLPORT_LIB_DIR} -dbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_DBG} -Wl,-rpath=${STLPORT_LIB_DIR} - -ifeq ($(OSNAME),sunos) -release-shared : LDLIBS = -lstlport_gcc -lrt -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lrt -dbg-shared : LDLIBS = -lstlport_gcc_debug -lrt -else -release-shared : LDLIBS = -lstlport_gcc -lxmt_gcc -lsockios_gcc -lmisc_gcc -lboost_regex_gcc -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lxmt_gcc_stl-g -lsockios_gcc_stl-g -lmisc_gcc_stl-g -lboost_regex_gcc_stl-g -dbg-shared : LDLIBS = -lstlport_gcc_debug -lxmt_gcc-g -lsockios_gcc-g -lmisc_gcc-g -lboost_regex_gcc-g +release-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR} -L${LIBSOCKIOS_DIR}/${OUTPUT_DIR} -L${LIBMISC_DIR}/${OUTPUT_DIR} -L$(LIBBOOSTRE_DIR)/${OUTPUT_DIR} +dbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_DBG} -L${LIBSOCKIOS_DIR}/${OUTPUT_DIR_DBG} -L${LIBMISC_DIR}/${OUTPUT_DIR_DBG} -L$(LIBBOOSTRE_DIR)/${OUTPUT_DIR_DBG} +ifndef WITHOUT_STLPORT +stldbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBSOCKIOS_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBMISC_DIR}/${OUTPUT_DIR_STLDBG} -L$(LIBBOOSTRE_DIR)/${OUTPUT_DIR_STLDBG} endif +release-shared : LDLIBS += -lxmt -lsockios -lmisc -lboost_regex +dbg-shared : LDLIBS += -lxmtg -lsockiosg -lmiscg -lboost_regexg +ifndef WITHOUT_STLPORT +stldbg-shared: LDLIBS += -lxmtstlg -lsockiosstl -lmiscstlg -lboost_regexstlg +endif Modified: trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/smtp-batch.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/smtp-batch.cc 2008-04-23 09:20:23 UTC (rev 1852) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/smtp-batch.cc 2008-04-23 09:22:13 UTC (rev 1853) @@ -1,16 +1,11 @@ // -*- C++ -*- Time-stamp: <04/06/16 12:51:35 ptr> -#ifdef __unix -# ifdef __HP_aCC -#pragma VERSIONID "@(#)$Id: smtp-batch.cc,v 1.1 2004/06/16 14:24:07 ptr Exp $" -# else -#ident "@(#)$Id: smtp-batch.cc,v 1.1 2004/06/16 14:24:07 ptr Exp $" -# endif -#endif +#include <mt/thread> +#include <mt/mutex> +#include <mt/condition_variable> +#include <mt/date_time> -#include <mt/xmt.h> -#include <mt/time.h> #include <sockios/sockstream> #include <misc/args.h> @@ -23,6 +18,7 @@ using namespace std; using namespace boost; +using namespace std::tr2; struct conn { @@ -68,7 +64,8 @@ map<command_type,string> CMD; sockstream tecol; -__impl::Condition tecol_ready; +mutex tecol_ready_lk; +condition_variable tecol_ready; void init_map() { @@ -405,14 +402,14 @@ send_flag = true; { stringstream ss; - timespec t; - __impl::Thread::gettime( &t ); - ss << t.tv_sec << "." + system_time t = get_system_time(); + ss << t.seconds_since_epoch() << "." << setiosflags(ios_base::right) << setfill('0') << setw(9) - << t.tv_nsec << "-" << my_host_name; + << (t.nanoseconds_since_epoch() - seconds(t.seconds_since_epoch()) ).count() << "-" << my_host_name; if ( !tecol.is_open() ) { + lock_guard<mutex> lk( tecol_ready_lk ); tecol.open( host.c_str(), port ); - tecol_ready.set( true ); + tecol_ready.notify_one(); }// else if ( host changed or port changed ) { // } tecol << "id=" << ss.str() << " " << "action=out" << endl; @@ -461,19 +458,17 @@ getline( ss, rest ); if ( !nodelay ) { istringstream str( rest ); - timespec t; - str >> t.tv_sec; + int tsec; + str >> tsec; + seconds sec( tsec ); + nanoseconds t( sec ); if ( !str.fail() ) { - if ( t.tv_sec > 0 ) { - t.tv_nsec = lrand48() % 2000000000; - if ( t.tv_nsec > 1000000000 ) { - --t.tv_sec; - t.tv_nsec -= 1000000000; - } + if ( sec.count() > 0 ) { + t += nanoseconds( (lrand48() % 2000000000) - 1000000000 ); } else { - t.tv_nsec = lrand48() % 1000000000; + t += nanoseconds( lrand48() % 1000000000 ); } - __impl::Thread::delay( &t ); + this_thread::sleep( t ); } } break; @@ -501,9 +496,10 @@ } } -int read_tecol( void * ) +void read_tecol() { - tecol_ready.try_wait(); + unique_lock<mutex> lk( tecol_ready_lk ); + tecol_ready.wait( lk ); string s; @@ -513,8 +509,6 @@ cout << s << endl; } } - - return 0; } int main( int argc, char * const *argv ) @@ -524,7 +518,7 @@ try { Argv arg; - arg.copyright( "Copyright (C) K sky Lab, 2003, 2004" ); + arg.copyright( "Copyright (C) Petr Ovtchenkov 2003, 2004, 2008" ); arg.brief( "Mail script interpreter" ); arg.option( "-h", false, "print this help message" ); arg.option( "-f", string( "" ), "script file, default stdin" ); @@ -547,10 +541,8 @@ string fname; arg.assign( "-f", fname ); - tecol_ready.set( false ); + basic_thread<thread_base::detached,0> t( read_tecol ); - __impl::Thread t( read_tecol, 0, 0, __impl::Thread::detached ); - if ( fname.length() != 0 ) { ifstream script( fname.c_str() ); interpret( script, arg ); Property changes on: trunk/complement/explore/app/SMTP-tools/smtp_server_ut ___________________________________________________________________ Name: svn:ignore + obj This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-23 09:20:26
|
Revision: 1852 http://complement.svn.sourceforge.net/complement/?rev=1852&view=rev Author: complement Date: 2008-04-23 02:20:23 -0700 (Wed, 23 Apr 2008) Log Message: ----------- take thread's id into fake variable and keep _id as bad_thread_id Modified Paths: -------------- trunk/complement/explore/include/mt/thread trunk/complement/explore/lib/mt/ChangeLog Modified: trunk/complement/explore/include/mt/thread =================================================================== --- trunk/complement/explore/include/mt/thread 2008-04-23 06:23:55 UTC (rev 1851) +++ trunk/complement/explore/include/mt/thread 2008-04-23 09:20:23 UTC (rev 1852) @@ -248,16 +248,15 @@ _stack_on_create = s.str(); } #endif - int err = pthread_create( &this->_id, F != 0 || S != 0 ? &attr : 0, &_call<Entry>, this ); + native_handle_type _id_tmp; + int err = pthread_create( (F & detached) != 0 ? &_id_tmp : &this->_id, F != 0 || S != 0 ? &attr : 0, &_call<Entry>, this ); if ( err != 0 ) { - // _id = id(); -- not required, already set + // _id = id(); -- not required, already set if required delete static_cast<Entry *>(_entry); if ( F & detached ) { // reset condition (_entry free, ready for delete) _entry = 0; } - } else if ( F & detached ) { - _id = id()._id; } if ( F != 0 || S != 0 ) { pthread_attr_destroy( &attr ); @@ -298,17 +297,16 @@ _stack_on_create = s.str(); } #endif - int err = pthread_create( &this->_id, F != 0 || S != 0 ? &attr : 0, &_call<Entry,Arg1>, this ); + native_handle_type _id_tmp; + int err = pthread_create( (F & detached) != 0 ? &_id_tmp : &this->_id, F != 0 || S != 0 ? &attr : 0, &_call<Entry,Arg1>, this ); if ( err != 0 ) { - // _id = id(); -- not required, already set + // _id = id(); -- not required, already set if required delete static_cast<Arg1 *>( static_cast<void **>(_entry)[1] ); delete static_cast<Entry *>( static_cast<void **>(_entry)[0] ); delete [] static_cast<void **>(_entry); if ( F & detached ) { _entry = 0; // reset condition (_entry free, ready for delete) } - } else if ( F & detached ) { - _id = id()._id; } if ( F != 0 || S != 0 ) { pthread_attr_destroy( &attr ); Modified: trunk/complement/explore/lib/mt/ChangeLog =================================================================== --- trunk/complement/explore/lib/mt/ChangeLog 2008-04-23 06:23:55 UTC (rev 1851) +++ trunk/complement/explore/lib/mt/ChangeLog 2008-04-23 09:20:23 UTC (rev 1852) @@ -1,3 +1,9 @@ +2008-04-23 Petr Ovtchenkov <pt...@is...> + + * thread: fix access to thread's _id in case of detached thread; + really take thread's id into fake variable and keep _id as + bad_thread_id. + 2008-03-26 Petr Ovtchenkov <pt...@is...> * mutex: add rw_mutex_ip typedef; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-23 06:24:03
|
Revision: 1851 http://complement.svn.sourceforge.net/complement/?rev=1851&view=rev Author: complement Date: 2008-04-22 23:23:55 -0700 (Tue, 22 Apr 2008) Log Message: ----------- compiled within complement source tree Modified Paths: -------------- trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile Property Changed: ---------------- trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/ trunk/complement/explore/app/SMTP-tools/scgen/ut/ Property changes on: trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn ___________________________________________________________________ Name: svn:ignore + obj Modified: trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile 2008-04-23 05:50:35 UTC (rev 1850) +++ trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile 2008-04-23 06:23:55 UTC (rev 1851) @@ -1,28 +1,8 @@ -# -*- Makefile -*- Time-stamp: <03/09/08 14:55:56 ptr> -# $Id: Makefile,v 1.1 2003/10/07 10:50:16 ptr Exp $ +# -*- Makefile -*- Time-stamp: <08/04/23 10:17:12 ptr> -SRCROOT := ../../../../../extern/complement -COMPILER_NAME := gcc +SRCROOT := ../../../.. -ALL_TAGS := dbg-shared - include Makefile.inc -include ${SRCROOT}/Makefiles/top.mak +include ${SRCROOT}/Makefiles/gmake/top.mak - -INCLUDES += -I$(SRCROOT)/include -I$(STLPORT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR) -I.. - -release-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR} -stldbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_STLDBG} -dbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_DBG} - -ifeq ($(OSNAME),sunos) -release-shared : LDLIBS = -lstlport_gcc -lrt -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lrt -dbg-shared : LDLIBS = -lstlport_gcc -lrt -else -release-shared : LDLIBS = -lstlport_gcc -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -dbg-shared : LDLIBS = -lstlport_gcc -endif - +INCLUDES += -I$(SRCROOT)/include -I$(BOOST_INCLUDE_DIR) -I.. Property changes on: trunk/complement/explore/app/SMTP-tools/scgen/ut ___________________________________________________________________ Name: svn:ignore + obj Modified: trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile 2008-04-23 05:50:35 UTC (rev 1850) +++ trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile 2008-04-23 06:23:55 UTC (rev 1851) @@ -1,28 +1,20 @@ -# -*- Makefile -*- Time-stamp: <03/09/09 12:54:58 ptr> -# $Id: Makefile,v 1.1 2003/09/11 10:34:11 ptr Exp $ +# -*- Makefile -*- Time-stamp: <08/04/23 10:21:52 ptr> -SRCROOT := ../../../../../extern/complement -COMPILER_NAME := gcc +SRCROOT := ../../../.. -ALL_TAGS := dbg-shared - include Makefile.inc -include ${SRCROOT}/Makefiles/top.mak +include ${SRCROOT}/Makefiles/gmake/top.mak +INCLUDES += -I$(SRCROOT)/include -I$(BOOST_INCLUDE_DIR) -I.. -INCLUDES += -I$(SRCROOT)/include -I$(STLPORT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR) -I.. - -release-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR} -stldbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_STLDBG} -dbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_DBG} - -ifeq ($(OSNAME),sunos) -release-shared : LDLIBS = -lstlport_gcc -lrt -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lrt -dbg-shared : LDLIBS = -lstlport_gcc -lrt -else -release-shared : LDLIBS = -lstlport_gcc -lboost_test_utf_gcc -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lboost_test_utf_gcc_stl-g -dbg-shared : LDLIBS = -lstlport_gcc -lboost_test_utf_gcc-g +release-shared: LDSEARCH += -L${CoMT_LIB_DIR} +dbg-shared: LDSEARCH += -L${CoMT_LIB_DIR_DBG} +ifndef WITHOUT_STLPORT +stldbg-shared: LDSEARCH += -L${CoMT_LIB_DIR_STLDBG} endif +release-shared : LDLIBS = -lboost_test_utf +dbg-shared : LDLIBS = -lboost_test_utfg +ifndef WITHOUT_STLPORT +stldbg-shared : LDLIBS = -lboost_test_utfstlg +endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-23 05:50:38
|
Revision: 1850 http://complement.svn.sourceforge.net/complement/?rev=1850&view=rev Author: complement Date: 2008-04-22 22:50:35 -0700 (Tue, 22 Apr 2008) Log Message: ----------- compiled within complement source tree Modified Paths: -------------- trunk/complement/explore/app/SMTP-tools/scgen/Makefile Property Changed: ---------------- trunk/complement/explore/app/SMTP-tools/scgen/ Property changes on: trunk/complement/explore/app/SMTP-tools/scgen ___________________________________________________________________ Name: svn:ignore + obj Modified: trunk/complement/explore/app/SMTP-tools/scgen/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/Makefile 2008-04-23 05:45:02 UTC (rev 1849) +++ trunk/complement/explore/app/SMTP-tools/scgen/Makefile 2008-04-23 05:50:35 UTC (rev 1850) @@ -1,28 +1,11 @@ -# -*- Makefile -*- Time-stamp: <03/09/08 14:55:56 ptr> -# $Id: Makefile,v 1.1 2003/09/11 10:33:15 ptr Exp $ +# -*- Makefile -*- Time-stamp: <08/04/23 09:49:02 ptr> -SRCROOT := ../../../../extern/complement -COMPILER_NAME := gcc +SRCROOT := ../../.. -ALL_TAGS := dbg-shared - include Makefile.inc -include ${SRCROOT}/Makefiles/top.mak +include ${SRCROOT}/Makefiles/gmake/top.mak +INCLUDES += -I$(SRCROOT)/include -I$(BOOST_INCLUDE_DIR) -INCLUDES += -I$(SRCROOT)/include -I$(STLPORT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR) -release-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR} -stldbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_STLDBG} -dbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_DBG} -ifeq ($(OSNAME),sunos) -release-shared : LDLIBS = -lstlport_gcc -lrt -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lrt -dbg-shared : LDLIBS = -lstlport_gcc -lrt -else -release-shared : LDLIBS = -lstlport_gcc -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -dbg-shared : LDLIBS = -lstlport_gcc -endif - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-23 05:45:09
|
Revision: 1849 http://complement.svn.sourceforge.net/complement/?rev=1849&view=rev Author: complement Date: 2008-04-22 22:45:02 -0700 (Tue, 22 Apr 2008) Log Message: ----------- compiled with current libxmt Modified Paths: -------------- trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile trunk/complement/explore/app/SMTP-tools/DoSclient/doscl.cc Property Changed: ---------------- trunk/complement/explore/app/SMTP-tools/DoSclient/ Property changes on: trunk/complement/explore/app/SMTP-tools/DoSclient ___________________________________________________________________ Name: svn:ignore + obj Modified: trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile 2008-04-23 05:42:33 UTC (rev 1848) +++ trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile 2008-04-23 05:45:02 UTC (rev 1849) @@ -1,28 +1,30 @@ -# -*- Makefile -*- Time-stamp: <03/10/07 18:28:29 ptr> -# $Id: Makefile,v 1.2 2004/06/16 14:29:20 ptr Exp $ +# -*- Makefile -*- Time-stamp: <08/04/23 09:38:04 ptr> -SRCROOT := ../../../../extern/complement -# SRCROOT := /export/home/ptr/island/workshop/explore -COMPILER_NAME := gcc +SRCROOT := ../../.. include Makefile.inc -include ${SRCROOT}/Makefiles/top.mak +include ${SRCROOT}/Makefiles/gmake/top.mak +LIBMT_DIR = ${CoMT_DIR}/lib/mt +LIBSOCKIOS_DIR = ${CoMT_DIR}/lib/sockios +LIBMISC_DIR = ${CoMT_DIR}/lib/misc +# LIBUTF_DIR = ${CoMT_DIR}/../extern/custom/boost/libs/test/unit_test_framework +# LIBEXAM_DIR = ${CoMT_DIR}/lib/exam +# LIBFS_DIR = ${CoMT_DIR}/../extern/custom/boost/libs/filesystem DEFS += -D_NO_TEST INCLUDES += -I$(SRCROOT)/include -I$(STLPORT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR) -release-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR} -stldbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_STLDBG} -dbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_DBG} +release-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR} -L${LIBSOCKIOS_DIR}/${OUTPUT_DIR} -L${LIBMISC_DIR}/${OUTPUT_DIR} +dbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_DBG} -L${LIBSOCKIOS_DIR}/${OUTPUT_DIR_DBG} -L${LIBMISC_DIR}/${OUTPUT_DIR_DBG} +ifndef WITHOUT_STLPORT +stldbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBSOCKIOS_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBMISC_DIR}/${OUTPUT_DIR_STLDBG} +endif -ifeq ($(OSNAME),sunos) -release-shared : LDLIBS = -lstlport_gcc -lrt -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lrt -dbg-shared : LDLIBS = -lstlport_gcc -lrt -else -release-shared : LDLIBS = -lstlport_gcc -lxmt_gcc -lsockios_gcc -lmisc_gcc -stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lxmt_gcc_stl-g -lsockios_gcc_stl-g -lmisc_gcc_stl-g -dbg-shared : LDLIBS = -lstlport_gcc -lxmt_gcc-g -lsockios_gcc-g -lmisc_gcc-g +release-shared : LDLIBS = -lxmt -lsockios -lmisc +dbg-shared : LDLIBS = -lxmtg -lsockiosg -lmiscg +ifndef WITHOUT_STLPORT +stldbg-shared : LDLIBS = -lxmtstlg -lsockiosstlg -lmiscstlg endif + Modified: trunk/complement/explore/app/SMTP-tools/DoSclient/doscl.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/DoSclient/doscl.cc 2008-04-23 05:42:33 UTC (rev 1848) +++ trunk/complement/explore/app/SMTP-tools/DoSclient/doscl.cc 2008-04-23 05:45:02 UTC (rev 1849) @@ -1,22 +1,15 @@ // -*- C++ -*- Time-stamp: <04/01/21 18:04:57 ptr> -#ifdef __unix -# ifdef __HP_aCC -#pragma VERSIONID "@(#)$Id: doscl.cc,v 1.2 2004/06/16 14:29:20 ptr Exp $" -# else -#ident "@(#)$Id: doscl.cc,v 1.2 2004/06/16 14:29:20 ptr Exp $" -# endif -#endif - #include <iostream> #include <string> #include <sstream> #include <sockios/sockstream> -#include <mt/xmt.h> +#include <mt/date_time> +#include <mt/thread> #include <misc/args.h> using namespace std; -using namespace __impl; +using namespace std::tr2; int command_whole_timeout_test( iostream& s, const string& hello_host, int delay ) { @@ -27,12 +20,8 @@ cout << rline << endl; - timespec t; - t.tv_sec = delay; - t.tv_nsec = 0; + this_thread::sleep( seconds( delay ) ); - Thread::delay( &t ); - s << "EHLO " << hello_host << "\r" << endl; getline( s, rline ); @@ -57,16 +46,12 @@ cout << rline << endl; - timespec t; - t.tv_sec = delay; - t.tv_nsec = 0; - stringstream sstr; sstr << "EHLO " << hello_host << "\r" << endl; string greeting( sstr.str() ); for ( string::iterator i = greeting.begin(); i != greeting.end(); ++i ) { - Thread::delay( &t ); + this_thread::sleep( seconds( delay ) ); s << *i; s.flush(); (cout << *i).flush(); @@ -90,7 +75,7 @@ { try { Argv arg; - arg.copyright( "Copyright (C) K sky Lab, 2003" ); + arg.copyright( "Copyright (C) Petr Ovtchenkov 2003, 2008" ); arg.brief( "test for SMTP GW project" ); arg.option( "-h", false, "print this help message" ); arg.option( "-s", string( "" ), "host with SMTP GW server" ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-23 05:42:41
|
Revision: 1848 http://complement.svn.sourceforge.net/complement/?rev=1848&view=rev Author: complement Date: 2008-04-22 22:42:33 -0700 (Tue, 22 Apr 2008) Log Message: ----------- Removed directory utils and node, not used a long time; libmisc: version 1.9.0 Modified Paths: -------------- trunk/complement/explore/lib/misc/ChangeLog trunk/complement/explore/lib/misc/Makefile.inc Modified: trunk/complement/explore/lib/misc/ChangeLog =================================================================== --- trunk/complement/explore/lib/misc/ChangeLog 2008-04-22 11:42:53 UTC (rev 1847) +++ trunk/complement/explore/lib/misc/ChangeLog 2008-04-23 05:42:33 UTC (rev 1848) @@ -1,3 +1,9 @@ +2008-04-23 Petr Ovtchenkov <pt...@is...> + + * Removed directory utils and node, not used a long time. + + * libmisc: version 1.9.0. + 2007-08-17 Petr Ovtchenkov <pt...@is...> * type_traits.h: made code acceptable for gcc 3.3 [remove Modified: trunk/complement/explore/lib/misc/Makefile.inc =================================================================== --- trunk/complement/explore/lib/misc/Makefile.inc 2008-04-22 11:42:53 UTC (rev 1847) +++ trunk/complement/explore/lib/misc/Makefile.inc 2008-04-23 05:42:33 UTC (rev 1848) @@ -1,5 +1,4 @@ # -*- Makefile -*- Time-stamp: <02/08/01 09:27:30 ptr> -# $Id$ # I have only one reason while I should use "C++" variant of MD5 instead of "C": # names like MD5Init is wide distributed, but some cool programmers use this @@ -10,7 +9,7 @@ LIBNAME = misc MAJOR = 1 -MINOR = 8 -PATCH = 1 -SRC_CC = CyrMoney.cc args.cc dir_utils.cc directory.cc _node.cc arguments.cc +MINOR = 9 +PATCH = 0 +SRC_CC = CyrMoney.cc args.cc arguments.cc SRC_C = md5.c This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <oke...@us...> - 2008-04-22 11:42:59
|
Revision: 1847 http://complement.svn.sourceforge.net/complement/?rev=1847&view=rev Author: okechina Date: 2008-04-22 04:42:53 -0700 (Tue, 22 Apr 2008) Log Message: ----------- Added Paths: ----------- trunk/complement/explore/app/SMTP-tools/smtp_server_ut/ trunk/complement/explore/app/SMTP-tools/smtp_server_ut/Makefile trunk/complement/explore/app/SMTP-tools/smtp_server_ut/Makefile.inc trunk/complement/explore/app/SMTP-tools/smtp_server_ut/SMTP_Server.cc trunk/complement/explore/app/SMTP-tools/smtp_server_ut/SMTP_Server.h trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test.cc trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test.h trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test_suite.cc trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test_suite.h trunk/complement/explore/app/SMTP-tools/smtp_server_ut/unit_test.cc Added: trunk/complement/explore/app/SMTP-tools/smtp_server_ut/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp_server_ut/Makefile (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp_server_ut/Makefile 2008-04-22 11:42:53 UTC (rev 1847) @@ -0,0 +1,74 @@ +# -*- Makefile -*- Time-stamp: <07/08/03 22:38:12 ptr> + +SRCROOT := ../../.. + +include Makefile.inc +include ${SRCROOT}/Makefiles/gmake/top.mak + + +INCLUDES += -I$(SRCROOT)/include +ifdef BOOST_DIR +INCLUDES += -I$(BOOST_INCLUDE_DIR) +endif +DEFS += -D__FIT_EXAM + +# temporary, before dums fix strings: +# DEFS += -D_STLP_DONT_USE_TEMPLATE_EXPRESSION + +# RPATH := $(realpath ${CoMT_LIB_DIR}) +# ifndef WITHOUT_STLPORT +# RPATH := ${RPATH}:$(realpath ${STLPORT_LIB_DIR}):$(realpath /usr/lib) +# endif + +LIBMT_DIR = ${CoMT_DIR}/lib/mt +# LIBUTF_DIR = ${CoMT_DIR}/../extern/custom/boost/libs/test/unit_test_framework +LIBEXAM_DIR = ${CoMT_DIR}/lib/exam +LIBFS_DIR = ${CoMT_DIR}/../extern/custom/boost/libs/filesystem + +ifeq ($(OSNAME),linux) + +release-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR} -L${LIBEXAM_DIR}/${OUTPUT_DIR} -L${LIBFS_DIR}/${OUTPUT_DIR} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR}:${LIBEXAM_DIR}/${OUTPUT_DIR}:${LIBFS_DIR}/${OUTPUT_DIR}:${STLPORT_LIB_DIR} + +dbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_DBG} -L${LIBEXAM_DIR}/${OUTPUT_DIR_DBG} -L${LIBFS_DIR}/${OUTPUT_DIR_DBG} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR_DBG}:${LIBEXAM_DIR}/${OUTPUT_DIR_DBG}:${LIBFS_DIR}/${OUTPUT_DIR_DBG}:${STLPORT_LIB_DIR} + +ifndef WITHOUT_STLPORT +stldbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBFS_DIR}/${OUTPUT_DIR_STLDBG} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR_STLDBG}:${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG}:${LIBFS_DIR}/${OUTPUT_DIR_STLDBG}:${STLPORT_LIB_DIR} +endif + +endif + +ifeq ($(OSNAME),openbsd) + +release-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR} -Wl,-R${LIBMT_DIR}/${OUTPUT_DIR}:${STLPORT_LIB_DIR} + +dbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_DBG} -Wl,-R${LIBMT_DIR}/${OUTPUT_DIR_DBG}:${STLPORT_LIB_DIR} + +ifndef WITHOUT_STLPORT +stldbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_STLDBG} -Wl,-R${LIBMT_DIR}/${OUTPUT_DIR_STLDBG}:${STLPORT_LIB_DIR} +endif + +endif + +release-shared : LDLIBS = -lxmt -lexam +dbg-shared : LDLIBS = -lxmtg -lexamg +ifndef WITHOUT_STLPORT +stldbg-shared : LDLIBS = -lxmtstlg -lexamstlg +endif + +ifeq ($(OSNAME),freebsd) +release-shared : LDLIBS += -lthr +dbg-shared : LDLIBS += -lthr +ifndef WITHOUT_STLPORT +stldbg-shared : LDLIBS += -lthr +endif +endif + +ifeq ($(OSNAME),sunos) +release-shared : LDLIBS += -lrt +dbg-shared : LDLIBS += -lrt +ifndef WITHOUT_STLPORT +stldbg-shared : LDLIBS += -lrt +endif +endif + + Added: trunk/complement/explore/app/SMTP-tools/smtp_server_ut/Makefile.inc =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp_server_ut/Makefile.inc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp_server_ut/Makefile.inc 2008-04-22 11:42:53 UTC (rev 1847) @@ -0,0 +1,7 @@ +# -*- makefile -*- Time-stamp: <08/03/26 10:12:36 ptr> + +PRGNAME = my_ut +SRC_CC = unit_test.cc \ + my_test.cc \ + my_test_suite.cc \ + SMTP_Server.cc Added: trunk/complement/explore/app/SMTP-tools/smtp_server_ut/SMTP_Server.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp_server_ut/SMTP_Server.cc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp_server_ut/SMTP_Server.cc 2008-04-22 11:42:53 UTC (rev 1847) @@ -0,0 +1,151 @@ +#include <iostream> +#include <string> +#include "SMTP_Server.h" + +using namespace std; + +command setCom(const string& str) { + string Str(str); + for(int i = 0; Str[i] != '\0'; i++) + Str[i] = tolower(Str[i]); + if (Str == "helo") return helo; + else if (Str == "ehlo") return ehlo; + else if (Str == "mail") return mail; + else if (Str == "rcpt") return rcpt; + else if (Str == "data") return data; + else if (Str == "rset") return rset; + else if (Str == "vrfy") return vrfy; + else if (Str == "expn") return expn; + else if (Str == "help") return help; + else if (Str == "noop") return noop; + else if (Str == "quit") return quit; + else return none; +} + +void change(state& st, command& com, string& param, string& stout) { + switch (com) { + case helo: + if (st == connect) { + stout = "250 localhost Hello localhost, pleased to meet you\n"; + st = hello; + return; + } + else { + stout = "503 localhost Duplicate HELO/EHLO\n"; + return; + } + case ehlo: + if (st == connect) { + stout = "250-localhost Hello localhost, pleased to meet you\n"; + stout += "250-8BITMIME\n"; + stout += "250-SIZE 8000000\n"; + stout += "250 HELP\n"; + st = hello; + return; + } + else { + stout = "503 localhost Duplicate HELO/EHLO\n"; + return; + } + case mail: + switch (st) { + case connect: + stout = "503 Polite people say HELO first\n"; + return; + case hello: + stout = "250 " + param + "... Sender ok\n"; + st = sender; + return; + case sender: + stout = "503 Sender already specified\n"; + return; + case recipient: + stout = "503 Sender already specified\n"; + return; + } + case rcpt: + switch (st) { + case connect: + stout = "503 Need MAIL before RCPT\n"; + return; + case hello: + stout = "503 Need MAIL before RCPT\n"; + return; + case sender: + stout = "250 " + param + "... Recipient ok\n"; + st = recipient; + return; + case recipient: + stout = "250 " + param + "... Recipient ok\n"; + return; + } + case data: + switch (st) { + case connect: + stout = "503 Need MAIL command\n"; + return; + case hello: + stout = "503 Need MAIL command\n"; + return; + case sender: + stout = "503 Need RCPT (recipient)\n"; + return; + case recipient: + stout = "354 Enter mail, end with '.' on a line by itself\n"; + st = letter; + return; + } + case rset: + stout = "250 Reset state\n"; + if (st!=connect) st = hello; + return; + case vrfy: + stout = "502 Command not implemented\n"; + return; + case expn: + stout = "502 Command not implemented\n"; + return; + case help: + stout = "214-This is SMTP_Server\n"; + stout += "214 End of HELP info\n"; + return; + case noop: + stout = "250 OK\n"; + return; + case quit: + stout = "221 localhost closing connection\n"; + stout += "Connection closed by foreign host.\n"; + st = disconnect; + return; + case none: + stout = "500 Command unrecognized\n"; + return; + } +} + + +int ServerWork() { + state st = connect; + command com; + string param, message, stout; + while (st != disconnect) { + if (st != letter) { + string str; + cin >> str; + getline(cin, param); + com = setCom(str); + change(st, com, param, stout); + cout << stout; + } + else { + getline(cin, param); + if (param != ".") message = message + param + "\n"; + else { + st = hello; + cout << message; + message = ""; + } + }; + }; + return 0; +} Added: trunk/complement/explore/app/SMTP-tools/smtp_server_ut/SMTP_Server.h =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp_server_ut/SMTP_Server.h (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp_server_ut/SMTP_Server.h 2008-04-22 11:42:53 UTC (rev 1847) @@ -0,0 +1,32 @@ +using namespace std; + +enum state { + disconnect, + connect, + hello, + sender, + recipient, + letter + }; +enum command { + helo, + ehlo, + mail, + rcpt, + data, + rset, + vrfy, + expn, + help, + noop, + quit, + none + }; + + +int ServerWork(); + +command setCom(const string& str); + +void change(state& st, command& com, string& param, string& stout); + Added: trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test.cc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test.cc 2008-04-22 11:42:53 UTC (rev 1847) @@ -0,0 +1,97 @@ +// -*- C++ -*- Time-stamp: <08/03/26 01:53:46 ptr> + +#include "my_test.h" +#include "SMTP_Server.h" + +#include <mt/thread> +#include <mt/mutex> +#include <mt/condition_variable> +#include <misc/type_traits.h> +#include <typeinfo> + +#include <iostream> +#include <semaphore.h> + +#include <sys/wait.h> +#include <sys/ipc.h> +#include <sys/shm.h> + +#include <unistd.h> + +using namespace std; + +static int fd1[2], fd2[2]; + +const int buf_size = 1024; +const int com_length = 4; + +void server_thread() +{ + char buffer[buf_size]; + state st = connect; + command com; + string param, message, stout; + + while (st != disconnect) { + if (st != letter) { + + if (read (fd2[0], buffer, sizeof(buffer)) < 1) fprintf(stderr,"Reading error\n"); + else fprintf (stderr,"%s\n",buffer); + + string str(buffer); + param.assign (str, com_length, str.size()); + str.erase (com_length, str.size() - com_length + 1); + com = setCom (str); + change (st, com, param, stout); + + strcpy (buffer, stout.c_str()); + write (fd1[1], buffer, sizeof(buffer)); + } + else { + read (fd2[0], buffer, sizeof(buffer)); + param.assign (buffer, 0, sizeof(buffer)); + if (param != ".") message = message + param + "\n"; + else { + st = hello; +// cout << message; + message = ""; + } + }; + }; + cerr << "Server's loop may be here" << endl; +} + +int EXAM_IMPL(my_test::thread_call) +{ + char r_buffer[buf_size], w_buffer[buf_size]; + pipe (fd1); + pipe (fd2); + std::tr2::basic_thread<0,0> t( server_thread ); + + strcpy (w_buffer, "ehlo"); + write (fd2[1], w_buffer, sizeof(w_buffer)); + read (fd1[0], r_buffer, sizeof(r_buffer)); + cerr << r_buffer; + + strcpy (w_buffer, "help"); + write (fd2[1], w_buffer, sizeof(w_buffer)); + read (fd1[0], r_buffer, sizeof(r_buffer)); + cerr << r_buffer; + + strcpy (w_buffer, "quit"); + write (fd2[1], w_buffer, sizeof(w_buffer)); + read (fd1[0], r_buffer, sizeof(r_buffer)); + cerr << r_buffer; + + cerr << "Client's text may be here" << endl; + t.join(); + + // EXAM_CHECK( val == 1 ); + // std::tr2::basic_thread<0,0> t2( thread_func_int, 2 ); + // t2.join(); + // EXAM_CHECK( val == 2 ); + // val = 0; + + return EXAM_RESULT; +} + Added: trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test.h =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test.h (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test.h 2008-04-22 11:42:53 UTC (rev 1847) @@ -0,0 +1,18 @@ +// -*- C++ -*- Time-stamp: <08/02/25 12:12:20 ptr> + + +#ifndef __MY_TEST_H +#define __MY_TEST_H + +#define FIT_EXAM + +#include <exam/suite.h> +// #include <mt/shm.h> + +class my_test +{ + public: + int EXAM_DECL(thread_call); +}; + +#endif // __MY_TEST_H Added: trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test_suite.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test_suite.cc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test_suite.cc 2008-04-22 11:42:53 UTC (rev 1847) @@ -0,0 +1,16 @@ +// -*- C++ -*- Time-stamp: <08/03/26 10:12:21 ptr> + +#include "my_test_suite.h" +#include "my_test.h" + +#include <config/feature.h> + +int EXAM_IMPL(my_test_suite) +{ + exam::test_suite t( "my test" ); + my_test test; + + t.add( &my_test::thread_call, test, "my_test::thread_call" ); + + return t.girdle(); +}; Added: trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test_suite.h =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test_suite.h (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp_server_ut/my_test_suite.h 2008-04-22 11:42:53 UTC (rev 1847) @@ -0,0 +1,10 @@ +// -*- C++ -*- Time-stamp: <07/07/16 22:08:39 ptr> + +#ifndef __MY_TEST_SUITE_H +#define __MY_TEST_SUITE_H + +#include <exam/suite.h> + +int EXAM_DECL(my_test_suite); + +#endif // __MY_TEST_SUITE_H Added: trunk/complement/explore/app/SMTP-tools/smtp_server_ut/unit_test.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp_server_ut/unit_test.cc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp_server_ut/unit_test.cc 2008-04-22 11:42:53 UTC (rev 1847) @@ -0,0 +1,11 @@ +// -*- C++ -*- Time-stamp: <07/07/16 22:12:10 ptr> + +#include <exam/suite.h> +#include <config/feature.h> + +#include "my_test_suite.h" + +int main( int, char ** ) +{ + return my_test_suite(0); +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-11 18:15:55
|
Revision: 1846 http://complement.svn.sourceforge.net/complement/?rev=1846&view=rev Author: complement Date: 2008-04-11 11:15:28 -0700 (Fri, 11 Apr 2008) Log Message: ----------- under construction; Modified Paths: -------------- branches/complement-sockios/explore/include/sockios/sp.cc branches/complement-sockios/explore/include/sockios/sp.h Modified: branches/complement-sockios/explore/include/sockios/sp.cc =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.cc 2008-04-09 17:35:43 UTC (rev 1845) +++ branches/complement-sockios/explore/include/sockios/sp.cc 2008-04-11 18:15:28 UTC (rev 1846) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/04/09 20:17:13 yeti> +// -*- C++ -*- Time-stamp: <08/04/11 21:52:28 yeti> /* * Copyright (c) 2008 @@ -199,9 +199,12 @@ } template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_new_t& ) +void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( int fd, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_new_t& ) { - Connect* c = new Connect( s ); + typename base_t::sockstream_t* s = base_t::create_stream( fd ); + + Connect* c = new Connect( s ); // bad point! I can't read from s in ctor indeed! + if ( s.rdbuf()->in_avail() ) { std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); ready_pool.push_back( processor( c, &s ) ); @@ -213,13 +216,14 @@ } template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_close_t& ) +void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( int fd, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_close_t& ) { { std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); - typename worker_pool_t::iterator i = worker_pool.find( &s ); + typename worker_pool_t::iterator i = worker_pool.find( fd ); if ( i != worker_pool.end() ) { - delete i->second; + delete i->second.s; + delete i->second.c; // std::cerr << "oops\n"; worker_pool.erase( i ); return; @@ -229,7 +233,7 @@ Connect* c = 0; { std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); - typename ready_pool_t::iterator j = std::find( ready_pool.begin(), ready_pool.end(), /* std::bind2nd( typename processor::equal_to(), &s ) */ &s ); + typename ready_pool_t::iterator j = std::find( ready_pool.begin(), ready_pool.end(), /* std::bind2nd( typename processor::equal_to(), &s ) */ fd ); if ( j != ready_pool.end() ) { // std::cerr << "oops 2\n"; c = j->c; @@ -243,22 +247,22 @@ } template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_data_t& ) +void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( int fd, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_data_t& ) { - Connect* c; + processor p; { std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); - typename worker_pool_t::const_iterator i = worker_pool.find( &s ); + typename worker_pool_t::const_iterator i = worker_pool.find( fd ); if ( i == worker_pool.end() ) { return; } - c = i->second; + p = i->second; worker_pool.erase( i ); } std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); - ready_pool.push_back( processor( c, &s ) ); + ready_pool.push_back( p ); cnd.notify_one(); // std::cerr << "notify data " << (void *)c << " " << ready_pool.size() << std::endl; } @@ -489,45 +493,35 @@ if ( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { throw std::runtime_error( "can't establish nonblock mode" ); } - sockstream_t* s; try { - s = new sockstream_t(); - std::cerr << __FILE__ << ":" << __LINE__ << " new sockstream_t: " << (void*)s << std::endl; - if ( s->rdbuf()->_open_sockmgr( fd, addr ) ) { - epoll_event ev_add; - ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - ev_add.data.fd = fd; - fd_info new_info = { fd_info::owner, s, info.p }; - descr[fd] = new_info; + std::cerr << __FILE__ << ":" << __LINE__ << " new sockstream_t" << std::endl; + (*info.p)( fd, typename socks_processor_t::adopt_new_t() ); - if ( epoll_ctl( efd, EPOLL_CTL_ADD, fd, &ev_add ) < 0 ) { - std::cerr << "Accept, add " << fd << ", errno " << errno << std::endl; - descr.erase( fd ); - // throw system_error - } - std::cerr << __FILE__ << ":" << __LINE__ << " adopt_new_t()\n"; - bool in_closed = false; - { - std::tr2::lock_guard<std::tr2::mutex> lk( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.begin(); - for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { - if ( closed_ifd->second.p == info.p ) { - in_closed = true; - std::cerr << "@@@ 1\n" << std::endl; - break; - } + epoll_event ev_add; + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = fd; + fd_info new_info = { fd_info::owner, s, info.p }; + descr[fd] = new_info; + + if ( epoll_ctl( efd, EPOLL_CTL_ADD, fd, &ev_add ) < 0 ) { + std::cerr << "Accept, add " << fd << ", errno " << errno << std::endl; + descr.erase( fd ); + // throw system_error + } + + std::cerr << __FILE__ << ":" << __LINE__ << " adopt_new_t()\n"; + bool in_closed = false; + { + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + in_closed = true; + std::cerr << "@@@ 1\n" << std::endl; + break; } } - if ( !in_closed ) { - std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)s << std::endl; - (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); - std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)s << std::endl; - } - } else { - std::cerr << "Accept, delete " << fd << std::endl; - std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)s << std::endl; - delete s; } } catch ( const std::bad_alloc& ) { @@ -535,7 +529,6 @@ } catch ( ... ) { descr.erase( fd ); - delete s; } } } else { Modified: branches/complement-sockios/explore/include/sockios/sp.h =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.h 2008-04-09 17:35:43 UTC (rev 1845) +++ branches/complement-sockios/explore/include/sockios/sp.h 2008-04-11 18:15:28 UTC (rev 1846) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/04/09 20:14:14 yeti> +// -*- C++ -*- Time-stamp: <08/04/11 22:14:39 yeti> /* * Copyright (c) 2008 @@ -100,9 +100,9 @@ virtual void close(); - virtual void operator ()( sockstream_t& s, const adopt_new_t& ) = 0; - virtual void operator ()( sockstream_t& s, const adopt_close_t& ) = 0; - virtual void operator ()( sockstream_t& s, const adopt_data_t& ) = 0; + virtual void operator ()( int fd, const adopt_new_t& ) = 0; + virtual void operator ()( int fd, const adopt_close_t& ) = 0; + virtual void operator ()( int fd, const adopt_data_t& ) = 0; private: sock_processor_base( const sock_processor_base& ); @@ -110,6 +110,12 @@ protected: void setoptions_unsafe( sock_base2::so_t optname, bool on_off = true, int __v = 0 ); + sockstream_t* create_stream( int fd ) + { + typename base_t::sockstream_t* s = new typename base_t::sockstream_t(); + s->rdbuf()->_open_sockmgr( fd, addr ); + return s; + } public: bool is_open() const @@ -208,11 +214,10 @@ { if ( ploop.joinable() ) { ploop.join(); } } private: - virtual void operator ()( typename base_t::sockstream_t& s, const typename base_t::adopt_new_t& ); - virtual void operator ()( typename base_t::sockstream_t& s, const typename base_t::adopt_close_t& ); - virtual void operator ()( typename base_t::sockstream_t& s, const typename base_t::adopt_data_t& ); + virtual void operator ()( int fd, const typename base_t::adopt_new_t& ); + virtual void operator ()( int fd, const typename base_t::adopt_close_t& ); + virtual void operator ()( int fd, const typename base_t::adopt_data_t& ); - static void loop( connect_processor* me ) { me->worker(); } @@ -251,6 +256,13 @@ { return s == p.s; } bool operator ==( const typename sock_processor_base<charT,traits,_Alloc>::sockstream_t* st ) const { return const_cast<const typename sock_processor_base<charT,traits,_Alloc>::sockstream_t*>(s) == st; } + bool operator ==( int fd ) const + { + if ( s == 0 ) { + return fd == -1; + } + return s->rdbuf()->fd() == fd; + } /* struct equal_to : @@ -265,13 +277,13 @@ bool pop_ready( processor& ); #ifdef __USE_STLPORT_HASH - typedef std::hash_map<typename base_t::sockstream_t*,Connect*> worker_pool_t; + typedef std::hash_map<int,processor> worker_pool_t; #endif #ifdef __USE_STD_HASH - typedef __gnu_cxx::hash_map<typename base_t::sockstream_t*,Connect*> worker_pool_t; + typedef __gnu_cxx::hash_map<int,processor> worker_pool_t; #endif #if defined(__USE_STLPORT_TR1) || defined(__USE_STD_TR1) - typedef std::tr1::unordered_map<typename base_t::sockstream_t*,Connect*> worker_pool_t; + typedef std::tr1::unordered_map<int,processor> worker_pool_t; #endif typedef std::deque<processor> ready_pool_t; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-09 17:36:26
|
Revision: 1845 http://complement.svn.sourceforge.net/complement/?rev=1845&view=rev Author: complement Date: 2008-04-09 10:35:43 -0700 (Wed, 09 Apr 2008) Log Message: ----------- split template decls and implementation; under construction Modified Paths: -------------- branches/complement-sockios/explore/include/sockios/sockstream2 branches/complement-sockios/explore/include/sockios/sp.h branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc Added Paths: ----------- branches/complement-sockios/explore/include/sockios/sp.cc Modified: branches/complement-sockios/explore/include/sockios/sockstream2 =================================================================== --- branches/complement-sockios/explore/include/sockios/sockstream2 2008-04-09 10:22:41 UTC (rev 1844) +++ branches/complement-sockios/explore/include/sockios/sockstream2 2008-04-09 17:35:43 UTC (rev 1845) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/27 17:18:22 yeti> +// -*- C++ -*- Time-stamp: <08/04/09 13:02:18 yeti> /* * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 @@ -25,6 +25,7 @@ #include <mt/mutex> #include <mt/condition_variable> #include <mt/date_time> +#include <mt/thread> #include <netdb.h> #include <netinet/in.h> @@ -311,6 +312,7 @@ } #endif // _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); + std::cerr << __FILE__ << ":" << __LINE__ << " new mgr " << std::tr2::getpid() << std::endl; } } else { std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); @@ -318,6 +320,7 @@ if ( basic_socket<charT,traits,_Alloc>::mgr == 0 ) { std::cerr << __FILE__ << ":" << __LINE__ << " shit happens\n"; } + std::cerr << __FILE__ << ":" << __LINE__ << " mgr destroyed " << std::tr2::getpid() << std::endl; delete basic_socket<charT,traits,_Alloc>::mgr; basic_socket<charT,traits,_Alloc>::mgr = 0; } Added: branches/complement-sockios/explore/include/sockios/sp.cc =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.cc (rev 0) +++ branches/complement-sockios/explore/include/sockios/sp.cc 2008-04-09 17:35:43 UTC (rev 1845) @@ -0,0 +1,766 @@ +// -*- C++ -*- Time-stamp: <08/04/09 20:17:13 yeti> + +/* + * Copyright (c) 2008 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License Version 3.0 + * + */ + +namespace std { + +template<class charT, class traits, class _Alloc> +void sock_processor_base<charT,traits,_Alloc>::open( const in_addr& addr, int port, sock_base2::stype type, sock_base2::protocol prot ) +{ + std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); + if ( basic_socket_t::is_open_unsafe() ) { + return; + } + _mode = ios_base::in | ios_base::out; + _state = ios_base::goodbit; +#ifdef WIN32 + ::WSASetLastError( 0 ); +#endif + if ( prot == sock_base2::inet ) { + basic_socket_t::_fd = socket( PF_INET, type, 0 ); + if ( basic_socket_t::_fd == -1 ) { + _state |= ios_base::failbit | ios_base::badbit; + return; + } + // _open = true; + basic_socket_t::_address.inet.sin_family = AF_INET; + basic_socket_t::_address.inet.sin_port = htons( port ); + basic_socket_t::_address.inet.sin_addr.s_addr = addr.s_addr; + + if ( type == sock_base2::sock_stream || type == sock_base2::sock_seqpacket ) { + // let's try reuse local address + setoptions_unsafe( sock_base2::so_reuseaddr, true ); + } + + if ( ::bind( basic_socket_t::_fd, &basic_socket_t::_address.any, sizeof(basic_socket_t::_address) ) == -1 ) { + _state |= ios_base::failbit; +#ifdef WIN32 + ::closesocket( basic_socket_t::_fd ); +#else + ::close( basic_socket_t::_fd ); +#endif + basic_socket_t::_fd = -1; + return; + } + + if ( type == sock_base2::sock_stream || type == sock_base2::sock_seqpacket ) { + // I am shure, this is socket of type SOCK_STREAM | SOCK_SEQPACKET, + // so don't check return code from listen + ::listen( basic_socket_t::_fd, SOMAXCONN ); + basic_socket_t::mgr->push( *this ); + } + } else if ( prot == sock_base2::local ) { + return; + } else { + return; + } + _state = ios_base::goodbit; + + return; +} + +template<class charT, class traits, class _Alloc> +void sock_processor_base<charT,traits,_Alloc>::close() +{ + std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); + if ( !basic_socket_t::is_open_unsafe() ) { + return; + } + basic_socket<charT,traits,_Alloc>::mgr->pop( *this, basic_socket_t::_fd ); +#ifdef WIN32 + ::closesocket( basic_socket_t::_fd ); +#else + ::shutdown( basic_socket_t::_fd, 2 ); + ::close( basic_socket_t::_fd ); +#endif + basic_socket_t::_fd = -1; +} + +template<class charT, class traits, class _Alloc> +void sock_processor_base<charT,traits,_Alloc>::shutdown( sock_base2::shutdownflg dir ) +{ + std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); + if ( basic_socket_t::is_open_unsafe() ) { + if ( (dir & (sock_base2::stop_in | sock_base2::stop_out)) == + (sock_base2::stop_in | sock_base2::stop_out) ) { + ::shutdown( basic_socket_t::_fd, 2 ); + } else if ( dir & sock_base2::stop_in ) { + ::shutdown( basic_socket_t::_fd, 0 ); + } else if ( dir & sock_base2::stop_out ) { + ::shutdown( basic_socket_t::_fd, 1 ); + } + } +} + +template<class charT, class traits, class _Alloc> +void sock_processor_base<charT,traits,_Alloc>::setoptions_unsafe( sock_base2::so_t optname, bool on_off, int __v ) +{ +#ifdef __unix + if ( basic_socket_t::is_open_unsafe() ) { + if ( optname != sock_base2::so_linger ) { + int turn = on_off ? 1 : 0; + if ( setsockopt( basic_socket_t::_fd, SOL_SOCKET, (int)optname, (const void *)&turn, + (socklen_t)sizeof(int) ) != 0 ) { + _state |= ios_base::failbit; + } + } else { + linger l; + l.l_onoff = on_off ? 1 : 0; + l.l_linger = __v; + if ( setsockopt( basic_socket_t::_fd, SOL_SOCKET, (int)optname, (const void *)&l, + (socklen_t)sizeof(linger) ) != 0 ) { + _state |= ios_base::failbit; + } + + } + } else { + _state |= ios_base::failbit; + } +#endif // __unix +} + + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +int connect_processor<Connect, charT, traits, _Alloc, C>::Init::_count = 0; + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +bool connect_processor<Connect, charT, traits, _Alloc, C>::Init::_at_fork = false; + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +std::tr2::mutex connect_processor<Connect, charT, traits, _Alloc, C>::Init::_init_lock; + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::Init::_guard( int direction ) +{ + if ( direction ) { + std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); + if ( _count++ == 0 ) { +#ifdef __FIT_PTHREADS + if ( !_at_fork ) { // call only once + if ( pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ) ) { + // throw system_error + } + _at_fork = true; + } +#endif +// _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); + } + } else { + std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); + if ( --_count == 0 ) { + + } + } +} + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_prepare() +{ _init_lock.lock(); } + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_child() +{ + _init_lock.unlock(); + + if ( _count != 0 ) { + // std::cerr << "SHOULD NEVER HAPPEN!!!!\n"; + throw std::logic_error( "Fork while connect_processor working may has unexpected behaviour in child process" ); + } + // _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); +} + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_parent() +{ _init_lock.unlock(); } + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +char connect_processor<Connect, charT, traits, _Alloc, C>::Init_buf[128]; + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::close() +{ + base_t::close(); + + { + std::tr2::lock_guard<std::tr2::mutex> lk(inwlock); + _in_work = false; // <--- set before cnd.notify_one(); (below in this func) + } + + std::tr2::lock_guard<std::tr2::mutex> lk2( rdlock ); + ready_pool.push_back( processor() ); // make ready_pool not empty + // std::cerr << "=== " << ready_pool.size() << std::endl; + cnd.notify_one(); +} + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_new_t& ) +{ + Connect* c = new Connect( s ); + if ( s.rdbuf()->in_avail() ) { + std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); + ready_pool.push_back( processor( c, &s ) ); + cnd.notify_one(); + } else { + std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); + worker_pool.insert( std::make_pair( &s, c ) ); + } +} + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_close_t& ) +{ + { + std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); + typename worker_pool_t::iterator i = worker_pool.find( &s ); + if ( i != worker_pool.end() ) { + delete i->second; + // std::cerr << "oops\n"; + worker_pool.erase( i ); + return; + } + } + + Connect* c = 0; + { + std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); + typename ready_pool_t::iterator j = std::find( ready_pool.begin(), ready_pool.end(), /* std::bind2nd( typename processor::equal_to(), &s ) */ &s ); + if ( j != ready_pool.end() ) { + // std::cerr << "oops 2\n"; + c = j->c; + ready_pool.erase( j ); + } + } + if ( c != 0 ) { + (c->*C)( s ); + delete c; + } +} + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_data_t& ) +{ + Connect* c; + + { + std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); + typename worker_pool_t::const_iterator i = worker_pool.find( &s ); + if ( i == worker_pool.end() ) { + return; + } + c = i->second; + worker_pool.erase( i ); + } + + std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); + ready_pool.push_back( processor( c, &s ) ); + cnd.notify_one(); + // std::cerr << "notify data " << (void *)c << " " << ready_pool.size() << std::endl; +} + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +bool connect_processor<Connect, charT, traits, _Alloc, C>::pop_ready( processor& p ) +{ + { + std::tr2::unique_lock<std::tr2::mutex> lk( rdlock ); + + cnd.wait( lk, not_empty ); + p = ready_pool.front(); // it may contain p.c == 0, p.s == 0, if !in_work() + ready_pool.pop_front(); + // std::cerr << "pop 1\n"; + if ( p.c == 0 ) { // wake up, but _in_work may be still true here (in processor pipe?), + return false; // even I know that _in_work <- false before notification... + } // so, check twice + } + + // std::cerr << "pop 2\n"; + + std::tr2::lock_guard<std::tr2::mutex> lk(inwlock); + return _in_work ? true : false; +} + + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::worker() +{ + _in_work = true; + + processor p; + + while ( pop_ready( p ) ) { + // std::cerr << "worker 1\n"; + (p.c->*C)( *p.s ); + // std::cerr << "worker 2\n"; + if ( p.s->rdbuf()->in_avail() ) { + std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); + ready_pool.push_back( p ); + } else { + std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); + worker_pool[p.s] = p.c; + } + // std::cerr << "worker 3\n"; + } +} + +namespace detail { +template<class charT, class traits, class _Alloc> +void sockmgr<charT,traits,_Alloc>::io_worker() +{ + epoll_event ev[/*n_ret*/ 512 ]; + +/* + ctl _xctl; + int r = read( pipefd[0], &_xctl, sizeof(ctl) ); + + if ( _xctl.cmd == rqstart ) { + std::cerr << "io_worker fine" << std::endl; + } else { + std::cerr << "io_worker not fine, " << r << ", " << errno << std::endl; + } +*/ + + try { + for ( ; ; ) { + int n = epoll_wait( efd, &ev[0], /* n_ret */ 512, -1 ); + + if ( n < 0 ) { + if ( errno == EINTR ) { + continue; + } + // throw system_error + } + // std::cerr << "epoll see " << n << std::endl; + + std::tr2::lock_guard<std::tr2::mutex> lk( dll ); + + for ( int i = 0; i < n; ++i ) { + // std::cerr << "epoll i = " << i << std::endl; + if ( ev[i].data.fd == pipefd[0] ) { + // std::cerr << "on pipe\n"; + cmd_from_pipe(); + } else { + // std::cerr << "#\n"; + + typename fd_container_type::iterator ifd = descr.find( ev[i].data.fd ); + if ( ifd == descr.end() ) { + if ( epoll_ctl( efd, EPOLL_CTL_DEL, ev[i].data.fd, 0 ) < 0 ) { + // throw system_error + } + continue; + // throw std::logic_error( "file descriptor in epoll, but not in descr[]" ); + } + + fd_info& info = ifd->second; + if ( info.flags & fd_info::listener ) { + // std::cerr << "%\n"; + process_listener( ev[i], ifd ); + } else { + // std::cerr << "not listener\n"; + process_regular( ev[i], ifd ); + } + } + } + } + } + catch ( std::detail::stop_request& ) { + // this is possible, normal flow of operation + } + catch ( std::exception& e ) { + std::cerr << e.what() << std::endl; + } +} + +template<class charT, class traits, class _Alloc> +void sockmgr<charT,traits,_Alloc>::cmd_from_pipe() +{ + epoll_event ev_add; + ctl _ctl; + + int r = read( pipefd[0], &_ctl, sizeof(ctl) ); + if ( r < 0 ) { + // throw system_error + // std::cerr << "Read pipe\n"; + } else if ( r == 0 ) { + // std::cerr << "Read pipe 0\n"; + throw runtime_error( "Read pipe return 0" ); + } + + switch ( _ctl.cmd ) { + case listener: + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = static_cast<socks_processor_t*>(_ctl.data.ptr)->fd(); + if ( ev_add.data.fd >= 0 ) { + if ( fcntl( ev_add.data.fd, F_SETFL, fcntl( ev_add.data.fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { + // std::cerr << "xxx " << errno << " " << std::tr2::getpid() << std::endl; + throw std::runtime_error( "can't establish nonblock mode on listener" ); + } + fd_info new_info = { fd_info::listener, 0, static_cast<socks_processor_t*>(_ctl.data.ptr) }; + descr[ev_add.data.fd] = new_info; + if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { + descr.erase( ev_add.data.fd ); + // throw system_error + } + } + break; +#if 0 + case tcp_stream: + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = static_cast<sockstream_t*>(_ctl.data.ptr)->rdbuf()->fd(); + if ( ev_add.data.fd >= 0 ) { + fd_info new_info = { 0, static_cast<sockstream_t*>(_ctl.data.ptr), 0 }; + descr[ev_add.data.fd] = new_info; + if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { + descr.erase( ev_add.data.fd ); + // throw system_error + } + } + break; +#endif + case tcp_buffer: + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = static_cast<sockbuf_t*>(_ctl.data.ptr)->fd(); + if ( ev_add.data.fd >= 0 ) { + fd_info new_info = { fd_info::buffer, static_cast<sockstream_t* /* sockbuf_t* */ >(_ctl.data.ptr), 0 }; + descr[ev_add.data.fd] = new_info; + if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { + descr.erase( ev_add.data.fd ); + // throw system_error + } + } + break; + case rqstop: + // std::cerr << "Stop request\n"; + throw std::detail::stop_request(); // runtime_error( "Stop request (normal flow)" ); + // break; + } +} + +template<class charT, class traits, class _Alloc> +void sockmgr<charT,traits,_Alloc>::process_listener( epoll_event& ev, typename sockmgr<charT,traits,_Alloc>::fd_container_type::iterator ifd ) +{ + if ( ev.events & EPOLLRDHUP ) { + epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ); + // walk through descr and detach every .p ? + descr.erase( ifd ); + std::cerr << "Remove listener EPOLLRDHUP\n"; + } else if ( ev.events & EPOLLIN ) { + sockaddr addr; + socklen_t sz = sizeof( sockaddr_in ); + + fd_info info = ifd->second; + + for ( ; ; ) { + int fd = accept( ev.data.fd, &addr, &sz ); + if ( fd < 0 ) { + std::cerr << "Accept, listener # " << ev.data.fd << ", errno " << errno << std::endl; + std::cerr << __FILE__ << ":" << __LINE__ << " " << std::tr2::getpid() << std::endl; + if ( (errno == EINTR) || (errno == ECONNABORTED) /* || (errno == ERESTARTSYS) */ ) { + continue; + } + if ( !(errno == EAGAIN || errno == EWOULDBLOCK) ) { + // std::cerr << "Accept, listener " << ev[i].data.fd << ", errno " << errno << std::endl; + // throw system_error ? + } +#if 0 + { + std::tr2::lock_guard<std::tr2::mutex> lck( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.find( ev.data.fd ); + if ( closed_ifd != closed_queue.end() ) { + typename fd_container_type::iterator ifd = descr.begin(); + for ( ; ifd != descr.end(); ) { + if ( ifd->second.p == closed_ifd->second.p ) { + descr.erase( ifd++ ); + } else { + ++ifd; + } + } + closed_queue.erase( closed_ifd ); + } + } +#endif + break; + } + // std::cerr << "listener accept " << fd << std::endl; + if ( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { + throw std::runtime_error( "can't establish nonblock mode" ); + } + sockstream_t* s; + + try { + s = new sockstream_t(); + std::cerr << __FILE__ << ":" << __LINE__ << " new sockstream_t: " << (void*)s << std::endl; + if ( s->rdbuf()->_open_sockmgr( fd, addr ) ) { + epoll_event ev_add; + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = fd; + fd_info new_info = { fd_info::owner, s, info.p }; + descr[fd] = new_info; + + if ( epoll_ctl( efd, EPOLL_CTL_ADD, fd, &ev_add ) < 0 ) { + std::cerr << "Accept, add " << fd << ", errno " << errno << std::endl; + descr.erase( fd ); + // throw system_error + } + std::cerr << __FILE__ << ":" << __LINE__ << " adopt_new_t()\n"; + bool in_closed = false; + { + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + in_closed = true; + std::cerr << "@@@ 1\n" << std::endl; + break; + } + } + } + if ( !in_closed ) { + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)s << std::endl; + (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)s << std::endl; + } + } else { + std::cerr << "Accept, delete " << fd << std::endl; + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)s << std::endl; + delete s; + } + } + catch ( const std::bad_alloc& ) { + // nothing + } + catch ( ... ) { + descr.erase( fd ); + delete s; + } + } + } else { + // std::cerr << "listener: " << std::hex << ev.events << std::dec << std::endl; + } +} + +template<class charT, class traits, class _Alloc> +void sockmgr<charT,traits,_Alloc>::process_regular( epoll_event& ev, typename sockmgr<charT,traits,_Alloc>::fd_container_type::iterator ifd ) +{ + fd_info& info = ifd->second; + + if ( ev.events & EPOLLIN ) { + if ( (info.flags & fd_info::owner) == 0 ) { + // marginal case: me not owner (registerd via push(), + // when I owner, I know destroy point), + // already closed, but I not see closed event yet; + // object may be deleted already, so I can't + // call b->egptr() etc. here + std::tr2::lock_guard<std::tr2::mutex> lck( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.find( ev.data.fd ); + if ( closed_ifd != closed_queue.end() ) { + closed_queue.erase( closed_ifd ); + if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { + // throw system_error + } + descr.erase( ifd ); + return; + } + } + sockbuf_t* b = (info.flags & fd_info::buffer != 0) ? info.s.b : info.s.s->rdbuf(); + errno = 0; + for ( ; ; ) { + if ( b->_ebuf == b->egptr() ) { + // process extract data from buffer too slow for us! + if ( (info.flags & fd_info::level_triggered) == 0 ) { + epoll_event xev; + xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP; + xev.data.fd = ev.data.fd; + info.flags |= fd_info::level_triggered; + if ( epoll_ctl( efd, EPOLL_CTL_MOD, ev.data.fd, &xev ) < 0 ) { + std::cerr << "X " << ev.data.fd << ", " << errno << std::endl; + } + } + std::cerr << "Z " << ev.data.fd << ", " << errno << std::endl; + if ( info.p != 0 ) { + bool is_closed = false; + { + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + is_closed = true; + std::cerr << "@@@ 2\n" << std::endl; + break; + } + } + } + if ( !is_closed ) { + (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); + } + } + break; + } + // std::cerr << "ptr " << (void *)b->egptr() << ", " << errno << std::endl; + long offset = read( ev.data.fd, b->egptr(), sizeof(charT) * (b->_ebuf - b->egptr()) ); + // std::cerr << "offset " << offset << ", " << errno << std::endl; + if ( offset < 0 ) { + if ( (errno == EAGAIN) || (errno == EINTR) ) { + errno = 0; + epoll_event xev; + xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + xev.data.fd = ev.data.fd; + epoll_ctl( efd, EPOLL_CTL_MOD, ev.data.fd, &xev ); + break; + } else { + switch ( errno ) { + // case EINTR: // read was interrupted + // continue; + // break; + case EFAULT: // Bad address + case ECONNRESET: // Connection reset by peer + ev.events |= EPOLLRDHUP; // will be processed below + break; + default: + // std::cerr << "not listener, other " << ev.data.fd << std::hex << ev.events << std::dec << " : " << errno << std::endl; + break; + } + break; + } + } else if ( offset > 0 ) { + offset /= sizeof(charT); // if offset % sizeof(charT) != 0, rest will be lost! + + if ( info.flags & fd_info::level_triggered ) { + epoll_event xev; + xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + xev.data.fd = ev.data.fd; + info.flags &= ~static_cast<unsigned>(fd_info::level_triggered); + if ( epoll_ctl( efd, EPOLL_CTL_MOD, ev.data.fd, &xev ) < 0 ) { + std::cerr << "Y " << ev.data.fd << ", " << errno << std::endl; + } + } + std::tr2::lock_guard<std::tr2::mutex> lk( b->ulck ); + b->setg( b->eback(), b->gptr(), b->egptr() + offset ); + b->ucnd.notify_one(); + if ( info.p != 0 ) { + // std::cerr << "data here" << std::endl; + bool is_closed = false; + { + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + is_closed = true; + std::cerr << "@@@ 3\n" << std::endl; + break; + } + } + } + if ( !is_closed ) { + (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); + } + } + } else { + std::cerr << "K " << ev.data.fd << ", " << errno << std::endl; + // EPOLLRDHUP may be missed in kernel, but offset 0 is the same + ev.events |= EPOLLRDHUP; // will be processed below + break; + } + } + } else { + std::cerr << "Q\n"; + } + + if ( (ev.events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR) ) != 0 ) { + // std::cerr << "Poll EPOLLRDHUP " << ev.data.fd << ", " << errno << std::endl; + if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { + // throw system_error + } + bool need_delete = true; + if ( info.p != 0 ) { + { + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + need_delete = false; // will be deleted in 'final' method + std::cerr << "@@@ 4\n" << std::endl; + break; + } + } + } + if ( need_delete ) { + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)info.s.s << std::endl; + (*info.p)( *info.s.s, typename socks_processor_t::adopt_close_t() ); + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)info.s.s << std::endl; + } + } + if ( (info.flags & fd_info::owner) != 0 && need_delete ) { + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)info.s.s << std::endl; + delete info.s.s; + info.s.s = 0; + } else { + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)info.s.s << std::endl; + if ( (info.flags & fd_info::buffer) != 0 ) { + info.s.b->close(); + } else { + info.s.s->close(); + } + std::tr2::lock_guard<std::tr2::mutex> lck( cll ); + closed_queue.erase( ev.data.fd ); + } + descr.erase( ifd ); + } + // if ( ev.events & EPOLLHUP ) { + // std::cerr << "Poll HUP" << std::endl; + // } + // if ( ev.events & EPOLLERR ) { + // std::cerr << "Poll ERR" << std::endl; + // } + if ( ev.events & EPOLLPRI ) { + std::cerr << "Poll PRI" << std::endl; + } + if ( ev.events & EPOLLRDNORM ) { + std::cerr << "Poll RDNORM" << std::endl; + } + if ( ev.events & EPOLLRDBAND ) { + std::cerr << "Poll RDBAND" << std::endl; + } + if ( ev.events & EPOLLMSG ) { + std::cerr << "Poll MSG" << std::endl; + } +} + +template<class charT, class traits, class _Alloc> +void sockmgr<charT,traits,_Alloc>::final( sockmgr<charT,traits,_Alloc>::socks_processor_t& p ) +{ + std::tr2::lock_guard<std::tr2::mutex> lk_descr( dll ); + + for ( typename fd_container_type::iterator ifd = descr.begin(); ifd != descr.end(); ) { + if ( (ifd->second.flags & fd_info::owner) && (ifd->second.p == &p) ) { + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)&p << " " << (void*)ifd->second.s.s << std::endl; + p( *ifd->second.s.s, typename socks_processor_t::adopt_close_t() ); + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)&p << " " << (void*)ifd->second.s.s << std::endl; + delete ifd->second.s.s; + if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { + // throw system_error + } + descr.erase( ifd++ ); + } else { + ++ifd; + } + } + + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + + // I can't use closed_queue.erase( p.fd() ) here: fd is -1 already + for ( typename fd_container_type::iterator closed_ifd = closed_queue.begin(); closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == &p ) { + closed_queue.erase( closed_ifd ); + break; + } + } +} + +} // namespace detail + +} // namespace std Modified: branches/complement-sockios/explore/include/sockios/sp.h =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.h 2008-04-09 10:22:41 UTC (rev 1844) +++ branches/complement-sockios/explore/include/sockios/sp.h 2008-04-09 17:35:43 UTC (rev 1845) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/04/04 01:02:50 ptr> +// -*- C++ -*- Time-stamp: <08/04/09 20:14:14 yeti> /* * Copyright (c) 2008 @@ -80,7 +80,10 @@ { sock_processor_base::close(); - basic_socket<charT,traits,_Alloc>::mgr->final( *this ); + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)this << " " << std::tr2::getpid() << std::endl; + // Never uncomment next line: + // basic_socket<charT,traits,_Alloc>::mgr->final( *this ); + // this lead to virtual fuction call, that is already pure here. } void open( const in_addr& addr, int port, sock_base2::stype type, sock_base2::protocol prot ); @@ -132,121 +135,6 @@ std::tr2::mutex _fd_lck; }; -template<class charT, class traits, class _Alloc> -void sock_processor_base<charT,traits,_Alloc>::open( const in_addr& addr, int port, sock_base2::stype type, sock_base2::protocol prot ) -{ - std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); - if ( basic_socket_t::is_open_unsafe() ) { - return; - } - _mode = ios_base::in | ios_base::out; - _state = ios_base::goodbit; -#ifdef WIN32 - ::WSASetLastError( 0 ); -#endif - if ( prot == sock_base2::inet ) { - basic_socket_t::_fd = socket( PF_INET, type, 0 ); - if ( basic_socket_t::_fd == -1 ) { - _state |= ios_base::failbit | ios_base::badbit; - return; - } - // _open = true; - basic_socket_t::_address.inet.sin_family = AF_INET; - basic_socket_t::_address.inet.sin_port = htons( port ); - basic_socket_t::_address.inet.sin_addr.s_addr = addr.s_addr; - - if ( type == sock_base2::sock_stream || type == sock_base2::sock_seqpacket ) { - // let's try reuse local address - setoptions_unsafe( sock_base2::so_reuseaddr, true ); - } - - if ( ::bind( basic_socket_t::_fd, &basic_socket_t::_address.any, sizeof(basic_socket_t::_address) ) == -1 ) { - _state |= ios_base::failbit; -#ifdef WIN32 - ::closesocket( basic_socket_t::_fd ); -#else - ::close( basic_socket_t::_fd ); -#endif - basic_socket_t::_fd = -1; - return; - } - - if ( type == sock_base2::sock_stream || type == sock_base2::sock_seqpacket ) { - // I am shure, this is socket of type SOCK_STREAM | SOCK_SEQPACKET, - // so don't check return code from listen - ::listen( basic_socket_t::_fd, SOMAXCONN ); - basic_socket_t::mgr->push( *this ); - } - } else if ( prot == sock_base2::local ) { - return; - } else { - return; - } - _state = ios_base::goodbit; - - return; -} - -template<class charT, class traits, class _Alloc> -void sock_processor_base<charT,traits,_Alloc>::close() -{ - std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); - if ( !basic_socket_t::is_open_unsafe() ) { - return; - } - basic_socket<charT,traits,_Alloc>::mgr->pop( *this, basic_socket_t::_fd ); -#ifdef WIN32 - ::closesocket( basic_socket_t::_fd ); -#else - ::shutdown( basic_socket_t::_fd, 2 ); - ::close( basic_socket_t::_fd ); -#endif - basic_socket_t::_fd = -1; -} - -template<class charT, class traits, class _Alloc> -void sock_processor_base<charT,traits,_Alloc>::shutdown( sock_base2::shutdownflg dir ) -{ - std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); - if ( basic_socket_t::is_open_unsafe() ) { - if ( (dir & (sock_base2::stop_in | sock_base2::stop_out)) == - (sock_base2::stop_in | sock_base2::stop_out) ) { - ::shutdown( basic_socket_t::_fd, 2 ); - } else if ( dir & sock_base2::stop_in ) { - ::shutdown( basic_socket_t::_fd, 0 ); - } else if ( dir & sock_base2::stop_out ) { - ::shutdown( basic_socket_t::_fd, 1 ); - } - } -} - -template<class charT, class traits, class _Alloc> -void sock_processor_base<charT,traits,_Alloc>::setoptions_unsafe( sock_base2::so_t optname, bool on_off, int __v ) -{ -#ifdef __unix - if ( basic_socket_t::is_open_unsafe() ) { - if ( optname != sock_base2::so_linger ) { - int turn = on_off ? 1 : 0; - if ( setsockopt( basic_socket_t::_fd, SOL_SOCKET, (int)optname, (const void *)&turn, - (socklen_t)sizeof(int) ) != 0 ) { - _state |= ios_base::failbit; - } - } else { - linger l; - l.l_onoff = on_off ? 1 : 0; - l.l_linger = __v; - if ( setsockopt( basic_socket_t::_fd, SOL_SOCKET, (int)optname, (const void *)&l, - (socklen_t)sizeof(linger) ) != 0 ) { - _state |= ios_base::failbit; - } - - } - } else { - _state |= ios_base::failbit; - } -#endif // __unix -} - typedef sock_processor_base<char,char_traits<char>,allocator<char> > sock_basic_processor; template <class Connect, class charT = char, class traits = std::char_traits<charT>, class _Alloc = std::allocator<charT>, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& ) = &Connect::connect > @@ -308,6 +196,9 @@ } ready_pool.clear(); + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)this << " " << std::tr2::getpid() << std::endl; + basic_socket<charT,traits,_Alloc>::mgr->final( *this ); + ((Init *)Init_buf)->~Init(); } @@ -409,189 +300,16 @@ friend struct _not_empty; }; -template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -int connect_processor<Connect, charT, traits, _Alloc, C>::Init::_count = 0; +namespace detail { -template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -bool connect_processor<Connect, charT, traits, _Alloc, C>::Init::_at_fork = false; - -template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -std::tr2::mutex connect_processor<Connect, charT, traits, _Alloc, C>::Init::_init_lock; - -template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::Init::_guard( int direction ) +class stop_request : + public std::exception { - if ( direction ) { - std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); - if ( _count++ == 0 ) { -#ifdef __FIT_PTHREADS - if ( !_at_fork ) { // call only once - if ( pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ) ) { - // throw system_error - } - _at_fork = true; - } -#endif -// _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); - } - } else { - std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); - if ( --_count == 0 ) { + public: + virtual const char* what() throw() + { return "sockmgr receive stop reqest"; } +}; - } - } -} - -template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_prepare() -{ _init_lock.lock(); } - -template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_child() -{ - _init_lock.unlock(); - - if ( _count != 0 ) { - // std::cerr << "SHOULD NEVER HAPPEN!!!!\n"; - throw std::logic_error( "Fork while connect_processor working may has unexpected behaviour in child process" ); - } - // _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); -} - -template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_parent() -{ _init_lock.unlock(); } - -template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -char connect_processor<Connect, charT, traits, _Alloc, C>::Init_buf[128]; - -template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::close() -{ - base_t::close(); - - { - std::tr2::lock_guard<std::tr2::mutex> lk(inwlock); - _in_work = false; // <--- set before cnd.notify_one(); (below in this func) - } - - std::tr2::lock_guard<std::tr2::mutex> lk2( rdlock ); - ready_pool.push_back( processor() ); // make ready_pool not empty - // std::cerr << "=== " << ready_pool.size() << std::endl; - cnd.notify_one(); -} - -template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_new_t& ) -{ - Connect* c = new Connect( s ); - if ( s.rdbuf()->in_avail() ) { - std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); - ready_pool.push_back( processor( c, &s ) ); - cnd.notify_one(); - } else { - std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); - worker_pool.insert( std::make_pair( &s, c ) ); - } -} - -template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_close_t& ) -{ - { - std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); - typename worker_pool_t::iterator i = worker_pool.find( &s ); - if ( i != worker_pool.end() ) { - delete i->second; - // std::cerr << "oops\n"; - worker_pool.erase( i ); - return; - } - } - - Connect* c = 0; - { - std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); - typename ready_pool_t::iterator j = std::find( ready_pool.begin(), ready_pool.end(), /* std::bind2nd( typename processor::equal_to(), &s ) */ &s ); - if ( j != ready_pool.end() ) { - // std::cerr << "oops 2\n"; - c = j->c; - ready_pool.erase( j ); - } - } - if ( c != 0 ) { - (c->*C)( s ); - delete c; - } -} - -template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_data_t& ) -{ - Connect* c; - - { - std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); - typename worker_pool_t::const_iterator i = worker_pool.find( &s ); - if ( i == worker_pool.end() ) { - return; - } - c = i->second; - worker_pool.erase( i ); - } - - std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); - ready_pool.push_back( processor( c, &s ) ); - cnd.notify_one(); - // std::cerr << "notify data " << (void *)c << " " << ready_pool.size() << std::endl; -} - -template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -bool connect_processor<Connect, charT, traits, _Alloc, C>::pop_ready( processor& p ) -{ - { - std::tr2::unique_lock<std::tr2::mutex> lk( rdlock ); - - cnd.wait( lk, not_empty ); - p = ready_pool.front(); // it may contain p.c == 0, p.s == 0, if !in_work() - ready_pool.pop_front(); - // std::cerr << "pop 1\n"; - if ( p.c == 0 ) { // wake up, but _in_work may be still true here (in processor pipe?), - return false; // even I know that _in_work <- false before notification... - } // so, check twice - } - - // std::cerr << "pop 2\n"; - - std::tr2::lock_guard<std::tr2::mutex> lk(inwlock); - return _in_work ? true : false; -} - - -template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> -void connect_processor<Connect, charT, traits, _Alloc, C>::worker() -{ - _in_work = true; - - processor p; - - while ( pop_ready( p ) ) { - std::cerr << "worker 1\n"; - (p.c->*C)( *p.s ); - std::cerr << "worker 2\n"; - if ( p.s->rdbuf()->in_avail() ) { - std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); - ready_pool.push_back( p ); - } else { - std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); - worker_pool[p.s] = p.c; - } - std::cerr << "worker 3\n"; - } -} - -namespace detail { - template<class charT, class traits, class _Alloc> class sockmgr { @@ -724,6 +442,7 @@ fd_info info = { fd_info::listener, 0, &p }; std::tr2::lock_guard<std::tr2::mutex> lk( cll ); closed_queue[_fd] = info; + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)&p << " " << std::tr2::getpid() << std::endl; } void final( socks_processor_t& p ); @@ -733,6 +452,7 @@ fd_info info = { 0, reinterpret_cast<sockstream_t*>(b), 0 }; std::tr2::lock_guard<std::tr2::mutex> lk( cll ); closed_queue[fd] = info; + std::cerr << __FILE__ << ":" << __LINE__ << " " << (void*)b << " " << std::tr2::getpid() << std::endl; } private: @@ -768,434 +488,6 @@ std::tr2::mutex dll; }; -template<class charT, class traits, class _Alloc> -void sockmgr<charT,traits,_Alloc>::final( sockmgr<charT,traits,_Alloc>::socks_processor_t& p ) -{ - // lock descr here ... should be - std::tr2::lock_guard<std::tr2::mutex> lk_descr( dll ); - - for ( typename fd_container_type::iterator ifd = descr.begin(); ifd != descr.end(); ) { - if ( (ifd->second.flags & fd_info::owner) && (ifd->second.p == &p) ) { - std::cerr << (void*)&p << " " << (void*)ifd->second.s.s << std::endl; - p( *ifd->second.s.s, typename socks_processor_t::adopt_close_t() ); - delete ifd->second.s.s; - if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { - // throw system_error - } - descr.erase( ifd++ ); - } else { - ++ifd; - } - } - - std::tr2::lock_guard<std::tr2::mutex> lk( cll ); - - // I can't use closed_queue.erase( p.fd() ) here: fd is -1 already - for ( typename fd_container_type::iterator closed_ifd = closed_queue.begin(); closed_ifd != closed_queue.end(); ++closed_ifd ) { - if ( closed_ifd->second.p == &p ) { - closed_queue.erase( closed_ifd ); - break; - } - } -} - -template<class charT, class traits, class _Alloc> -void sockmgr<charT,traits,_Alloc>::io_worker() -{ - epoll_event ev[/*n_ret*/ 512 ]; - -/* - ctl _xctl; - int r = read( pipefd[0], &_xctl, sizeof(ctl) ); - - if ( _xctl.cmd == rqstart ) { - std::cerr << "io_worker fine" << std::endl; - } else { - std::cerr << "io_worker not fine, " << r << ", " << errno << std::endl; - } -*/ - - try { - for ( ; ; ) { - int n = epoll_wait( efd, &ev[0], /* n_ret */ 512, -1 ); - - if ( n < 0 ) { - if ( errno == EINTR ) { - continue; - } - // throw system_error - } - // std::cerr << "epoll see " << n << std::endl; - - std::tr2::lock_guard<std::tr2::mutex> lk( dll ); - - for ( int i = 0; i < n; ++i ) { - // std::cerr << "epoll i = " << i << std::endl; - if ( ev[i].data.fd == pipefd[0] ) { - // std::cerr << "on pipe\n"; - cmd_from_pipe(); - } else { - // std::cerr << "#\n"; - - typename fd_container_type::iterator ifd = descr.find( ev[i].data.fd ); - if ( ifd == descr.end() ) { - throw std::logic_error( "file descriptor in epoll, but not in descr[]" ); - } - - fd_info& info = ifd->second; - if ( info.flags & fd_info::listener ) { - // std::cerr << "%\n"; - process_listener( ev[i], ifd ); - } else { - // std::cerr << "not listener\n"; - process_regular( ev[i], ifd ); - } - } - } - } - } - catch ( std::exception& e ) { - std::cerr << e.what() << std::endl; - } -} - -template<class charT, class traits, class _Alloc> -void sockmgr<charT,traits,_Alloc>::cmd_from_pipe() -{ - epoll_event ev_add; - ctl _ctl; - - int r = read( pipefd[0], &_ctl, sizeof(ctl) ); - if ( r < 0 ) { - // throw system_error - // std::cerr << "Read pipe\n"; - } else if ( r == 0 ) { - // std::cerr << "Read pipe 0\n"; - throw runtime_error( "Read pipe return 0" ); - } - - switch ( _ctl.cmd ) { - case listener: - ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - ev_add.data.fd = static_cast<socks_processor_t*>(_ctl.data.ptr)->fd(); - if ( ev_add.data.fd >= 0 ) { - if ( fcntl( ev_add.data.fd, F_SETFL, fcntl( ev_add.data.fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { - // std::cerr << "xxx " << errno << " " << std::tr2::getpid() << std::endl; - throw std::runtime_error( "can't establish nonblock mode on listener" ); - } - fd_info new_info = { fd_info::listener, 0, static_cast<socks_processor_t*>(_ctl.data.ptr) }; - descr[ev_add.data.fd] = new_info; - if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { - descr.erase( ev_add.data.fd ); - // throw system_error - } - } - break; -#if 0 - case tcp_stream: - ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - ev_add.data.fd = static_cast<sockstream_t*>(_ctl.data.ptr)->rdbuf()->fd(); - if ( ev_add.data.fd >= 0 ) { - fd_info new_info = { 0, static_cast<sockstream_t*>(_ctl.data.ptr), 0 }; - descr[ev_add.data.fd] = new_info; - if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { - descr.erase( ev_add.data.fd ); - // throw system_error - } - } - break; -#endif - case tcp_buffer: - ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - ev_add.data.fd = static_cast<sockbuf_t*>(_ctl.data.ptr)->fd(); - if ( ev_add.data.fd >= 0 ) { - fd_info new_info = { fd_info::buffer, static_cast<sockstream_t* /* sockbuf_t* */ >(_ctl.data.ptr), 0 }; - descr[ev_add.data.fd] = new_info; - if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { - descr.erase( ev_add.data.fd ); - // throw system_error - } - } - break; - case rqstop: - // std::cerr << "Stop request\n"; - throw runtime_error( "Stop request (normal flow)" ); - break; - } -} - -template<class charT, class traits, class _Alloc> -void sockmgr<charT,traits,_Alloc>::process_listener( epoll_event& ev, typename sockmgr<charT,traits,_Alloc>::fd_container_type::iterator ifd ) -{ - if ( ev.events & EPOLLRDHUP ) { - epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ); - // walk through descr and detach every .p ? - descr.erase( ifd ); - std::cerr << "Remove listener EPOLLRDHUP\n"; - } else if ( ev.events & EPOLLIN ) { - sockaddr addr; - socklen_t sz = sizeof( sockaddr_in ); - - fd_info& info = ifd->second; - - for ( ; ; ) { - int fd = accept( ev.data.fd, &addr, &sz ); - if ( fd < 0 ) { - std::cerr << "Accept, listener # " << ev.data.fd << ", errno " << errno << std::endl; - if ( (errno == EINTR) || (errno == ECONNABORTED) /* || (errno == ERESTARTSYS) */ ) { - continue; - } - if ( !(errno == EAGAIN || errno == EWOULDBLOCK) ) { - // std::cerr << "Accept, listener " << ev[i].data.fd << ", errno " << errno << std::endl; - // throw system_error ? - } -#if 0 - { - std::tr2::lock_guard<std::tr2::mutex> lck( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.find( ev.data.fd ); - if ( closed_ifd != closed_queue.end() ) { - typename fd_container_type::iterator ifd = descr.begin(); - for ( ; ifd != descr.end(); ) { - if ( ifd->second.p == closed_ifd->second.p ) { - descr.erase( ifd++ ); - } else { - ++ifd; - } - } - closed_queue.erase( closed_ifd ); - } - } -#endif - break; - } - // std::cerr << "listener accept " << fd << std::endl; - if ( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { - throw std::runtime_error( "can't establish nonblock mode" ); - } - sockstream_t* s; - - try { - s = new sockstream_t(); - std::cerr << "sockstream_t: " << (void*)s << std::endl; - if ( s->rdbuf()->_open_sockmgr( fd, addr ) ) { - epoll_event ev_add; - ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - ev_add.data.fd = fd; - fd_info new_info = { fd_info::owner, s, info.p }; - descr[fd] = new_info; - - if ( epoll_ctl( efd, EPOLL_CTL_ADD, fd, &ev_add ) < 0 ) { - std::cerr << "Accept, add " << fd << ", errno " << errno << std::endl; - descr.erase( fd ); - // throw system_error - } - std::cerr << "adopt_new_t()\n"; - std::tr2::lock_guard<std::tr2::mutex> lk( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.begin(); - for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { - if ( closed_ifd->second.p == info.p ) { - break; - } - } - if ( closed_ifd == closed_queue.end() ) { - (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); - } else { - std::cerr << "@@@ 1\n" << std::endl; - } - } else { - std::cerr << "Accept, delete " << fd << std::endl; - delete s; - } - } - catch ( const std::bad_alloc& ) { - // nothing - } - catch ( ... ) { - descr.erase( fd ); - delete s; - } - } - } else { - // std::cerr << "listener: " << std::hex << ev.events << std::dec << std::endl; - } -} - -template<class charT, class traits, class _Alloc> -void sockmgr<charT,traits,_Alloc>::process_regular( epoll_event& ev, typename sockmgr<charT,traits,_Alloc>::fd_container_type::iterator ifd ) -{ - fd_info& info = ifd->second; - - if ( ev.events & EPOLLIN ) { - if ( (info.flags & fd_info::owner) == 0 ) { - // marginal case: me not owner (registerd via push(), - // when I owner, I know destroy point), - // already closed, but I not see closed event yet; - // object may be deleted already, so I can't - // call b->egptr() etc. here - std::tr2::lock_guard<std::tr2::mutex> lck( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.find( ev.data.fd ); - if ( closed_ifd != closed_queue.end() ) { - closed_queue.erase( closed_ifd ); - if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { - // throw system_error - } - descr.erase( ifd ); - return; - } - } - sockbuf_t* b = (info.flags & fd_info::buffer != 0) ? info.s.b : info.s.s->rdbuf(); - errno = 0; - for ( ; ; ) { - if ( b->_ebuf == b->egptr() ) { - // process extract data from buffer too slow for us! - if ( (info.flags & fd_info::level_triggered) == 0 ) { - epoll_event xev; - xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP; - xev.data.fd = ev.data.fd; - info.flags |= fd_info::level_triggered; - if ( epoll_ctl( efd, EPOLL_CTL_MOD, ev.data.fd, &xev ) < 0 ) { - std::cerr << "X " << ev.data.fd << ", " << errno << std::endl; - } - } - std::cerr << "Z " << ev.data.fd << ", " << errno << std::endl; - if ( info.p != 0 ) { - std::tr2::lock_guard<std::tr2::mutex> lk( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.begin(); - for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { - if ( closed_ifd->second.p == info.p ) { - break; - } - } - if ( closed_ifd == closed_queue.end() ) { - (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); - } else { - std::cerr << "@@@ 2\n" << std::endl; - } - } - break; - } - std::cerr << "ptr " << (void *)b->egptr() << ", " << errno << std::endl; - long offset = read( ev.data.fd, b->egptr(), sizeof(charT) * (b->_ebuf - b->egptr()) ); - std::cerr << "offset " << offset << ", " << errno << std::endl; - if ( offset < 0 ) { - if ( (errno == EAGAIN) || (errno == EINTR) ) { - errno = 0; - epoll_event xev; - xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - xev.data.fd = ev.data.fd; - epoll_ctl( efd, EPOLL_CTL_MOD, ev.data.fd, &xev ); - break; - } else { - switch ( errno ) { - // case EINTR: // read was interrupted - // continue; - // break; - case EFAULT: // Bad address - case ECONNRESET: // Connection reset by peer - ev.events |= EPOLLRDHUP; // will be processed below - break; - default: - std::cerr << "not listener, other " << ev.data.fd << std::hex << ev.events << std::dec << " : " << errno << std::endl; - break; - } - break; - } - } else if ( offset > 0 ) { - offset /= sizeof(charT); // if offset % sizeof(charT) != 0, rest will be lost! - - if ( info.flags & fd_info::level_triggered ) { - epoll_event xev; - xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - xev.data.fd = ev.data.fd; - info.flags &= ~static_cast<unsigned>(fd_info::level_triggered); - if ( epoll_ctl( efd, EPOLL_CTL_MOD, ev.data.fd, &xev ) < 0 ) { - std::cerr << "Y " << ev.data.fd << ", " << errno << std::endl; - } - } - std::tr2::lock_guard<std::tr2::mutex> lk( b->ulck ); - b->setg( b->eback(), b->gptr(), b->egptr() + offset ); - b->ucnd.notify_one(); - if ( info.p != 0 ) { - // std::cerr << "data here" << std::endl; - std::tr2::lock_guard<std::tr2::mutex> lk( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.begin(); - for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { - if ( closed_ifd->second.p == info.p ) { - break; - } - } - if ( closed_ifd == closed_queue.end() ) { - (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); - } else { - std::cerr << "@@@ 3\n" << std::endl; - } - } - } else { - std::cerr << "K " << ev.data.fd << ", " << errno << std::endl; - // EPOLLRDHUP may be missed in kernel, but offset 0 is the same - ev.events |= EPOLLRDHUP; // will be processed below - break; - } - } - } else { - std::cerr << "Q\n"; - } - - if ( (ev.events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR) ) != 0 ) { - // std::cerr << "Poll EPOLLRDHUP " << ev.data.fd << ", " << errno << std::endl; - if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { - // throw system_error - } - bool need_delete = true; - if ( info.p != 0 ) { - std::tr2::lock_guard<std::tr2::mutex> lk( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.begin(); - for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { - if ( closed_ifd->second.p == info.p ) { - break; - } - } - if ( closed_ifd == closed_queue.end() ) { - (*info.p)( *info.s.s, typename socks_processor_t::adopt_close_t() ); - } else { - need_delete = false; // will be deleted in 'final' method - std::cerr << "@@@ 4\n" << std::endl; - } - } - if ( (info.flags & fd_info::owner) != 0 && need_delete ) { - delete info.s.s; - info.s.s = 0; - } else { - if ( (info.flags & fd_info::buffer) != 0 ) { - info.s.b->close(); - } else { - info.s.s->close(); - } - std::tr2::lock_guard<std::tr2::mutex> lck( cll ); - closed_queue.erase( ev.data.fd ); - } - descr.erase( ifd ); - } - // if ( ev.events & EPOLLHUP ) { - // std::cerr << "Poll HUP" << std::endl; - // } - // if ( ev.events & EPOLLERR ) { - // std::cerr << "Poll ERR" << std::endl; - // } - if ( ev.events & EPOLLPRI ) { - std::cerr << "Poll PRI" << std::endl; - } - if ( ev.events & EPOLLRDNORM ) { - std::cerr << "Poll RDNORM" << std::endl; - } - if ( ev.events & EPOLLRDBAND ) { - std::cerr << "Poll RDBAND" << std::endl; - } - if ( ev.events & EPOLLMSG ) { - std::cerr << "Poll MSG" << std::endl; - } ... [truncated message content] |
From: <com...@us...> - 2008-04-09 10:22:45
|
Revision: 1844 http://complement.svn.sourceforge.net/complement/?rev=1844&view=rev Author: complement Date: 2008-04-09 03:22:41 -0700 (Wed, 09 Apr 2008) Log Message: ----------- import old staff from K Sky, SMTP-related issues Added Paths: ----------- trunk/complement/explore/app/SMTP-tools/ trunk/complement/explore/app/SMTP-tools/DoSclient/ trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile.inc trunk/complement/explore/app/SMTP-tools/DoSclient/doscl.cc trunk/complement/explore/app/SMTP-tools/scgen/ trunk/complement/explore/app/SMTP-tools/scgen/Makefile trunk/complement/explore/app/SMTP-tools/scgen/Makefile.inc trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/ trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile.inc trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/dropconn.cc trunk/complement/explore/app/SMTP-tools/scgen/scgen.cc trunk/complement/explore/app/SMTP-tools/scgen/stategraph.cc trunk/complement/explore/app/SMTP-tools/scgen/stategraph.h trunk/complement/explore/app/SMTP-tools/scgen/ut/ trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile.inc trunk/complement/explore/app/SMTP-tools/scgen/ut/unit_test.cc trunk/complement/explore/app/SMTP-tools/smtp-ut/ trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-addr-2 trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-body-1 trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-domain-1 trunk/complement/explore/app/SMTP-tools/smtp-ut/dot-line trunk/complement/explore/app/SMTP-tools/smtp-ut/good-addr trunk/complement/explore/app/SMTP-tools/smtp-ut/good-domain-1 trunk/complement/explore/app/SMTP-tools/smtp-ut/good-domain-2 trunk/complement/explore/app/SMTP-tools/smtp-ut/null-char trunk/complement/explore/app/SMTP-tools/smtp-ut/scr.sed trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/ trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile.inc trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/smtp-batch.cc trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch.py trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-ut-aux.py trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-ut.py trunk/complement/explore/app/SMTP-tools/smtp-ut/test-1 trunk/complement/explore/app/SMTP-tools/smtp-ut/test-2 trunk/complement/explore/app/SMTP-tools/smtp-ut/test-3 trunk/complement/explore/app/SMTP-tools/smtp-ut/test-4 trunk/complement/explore/app/SMTP-tools/smtp-ut/test-5 trunk/complement/explore/app/SMTP-tools/smtp-ut/test-drop-conn trunk/complement/explore/app/SMTP-tools/smtp-ut/test-graph-1 trunk/complement/explore/app/SMTP-tools/smtp-ut/test-tecol trunk/complement/explore/app/SMTP-tools/smtp-ut/test-twice trunk/complement/explore/app/SMTP-tools/smtp-ut/timeoutsocket.py trunk/complement/explore/app/SMTP-tools/tecol/ trunk/complement/explore/app/SMTP-tools/tecol/ConnectionProcessor.cc trunk/complement/explore/app/SMTP-tools/tecol/ConnectionProcessor.h trunk/complement/explore/app/SMTP-tools/tecol/Makefile trunk/complement/explore/app/SMTP-tools/tecol/Makefile.inc trunk/complement/explore/app/SMTP-tools/tecol/dump/ trunk/complement/explore/app/SMTP-tools/tecol/dump/Makefile trunk/complement/explore/app/SMTP-tools/tecol/dump/Makefile.inc trunk/complement/explore/app/SMTP-tools/tecol/dump/dump.cc trunk/complement/explore/app/SMTP-tools/tecol/tecol.cc trunk/complement/explore/app/SMTP-tools/tecol/ut/ trunk/complement/explore/app/SMTP-tools/tecol/ut/Makefile trunk/complement/explore/app/SMTP-tools/tecol/ut/Makefile.inc trunk/complement/explore/app/SMTP-tools/tecol/ut/client.cc trunk/complement/explore/app/SMTP-tools/tecol/ut/client.h trunk/complement/explore/app/SMTP-tools/tecol/ut/message.cc trunk/complement/explore/app/SMTP-tools/tecol/ut/message.h trunk/complement/explore/app/SMTP-tools/tecol/ut/unit_test.cc trunk/complement/explore/app/SMTP-tools/test_mta/ trunk/complement/explore/app/SMTP-tools/test_mta/ConnectionProcessor.cc trunk/complement/explore/app/SMTP-tools/test_mta/ConnectionProcessor.h trunk/complement/explore/app/SMTP-tools/test_mta/Makefile trunk/complement/explore/app/SMTP-tools/test_mta/Makefile.inc trunk/complement/explore/app/SMTP-tools/test_mta/tmta.cc Added: trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile (rev 0) +++ trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,28 @@ +# -*- Makefile -*- Time-stamp: <03/10/07 18:28:29 ptr> +# $Id: Makefile,v 1.2 2004/06/16 14:29:20 ptr Exp $ + +SRCROOT := ../../../../extern/complement +# SRCROOT := /export/home/ptr/island/workshop/explore +COMPILER_NAME := gcc + +include Makefile.inc +include ${SRCROOT}/Makefiles/top.mak + + +DEFS += -D_NO_TEST +INCLUDES += -I$(SRCROOT)/include -I$(STLPORT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR) + +release-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR} +stldbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_STLDBG} +dbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_DBG} + +ifeq ($(OSNAME),sunos) +release-shared : LDLIBS = -lstlport_gcc -lrt +stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lrt +dbg-shared : LDLIBS = -lstlport_gcc -lrt +else +release-shared : LDLIBS = -lstlport_gcc -lxmt_gcc -lsockios_gcc -lmisc_gcc +stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lxmt_gcc_stl-g -lsockios_gcc_stl-g -lmisc_gcc_stl-g +dbg-shared : LDLIBS = -lstlport_gcc -lxmt_gcc-g -lsockios_gcc-g -lmisc_gcc-g +endif + Added: trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile.inc =================================================================== --- trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile.inc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/DoSclient/Makefile.inc 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,5 @@ +# -*- makefile -*- Time-stamp: <03/10/07 15:14:22 ptr> +# $Id: Makefile.inc,v 1.1 2003/10/08 08:26:16 ptr Exp $ + +PRGNAME = doscl +SRC_CC = doscl.cc Added: trunk/complement/explore/app/SMTP-tools/DoSclient/doscl.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/DoSclient/doscl.cc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/DoSclient/doscl.cc 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,144 @@ +// -*- C++ -*- Time-stamp: <04/01/21 18:04:57 ptr> + +#ifdef __unix +# ifdef __HP_aCC +#pragma VERSIONID "@(#)$Id: doscl.cc,v 1.2 2004/06/16 14:29:20 ptr Exp $" +# else +#ident "@(#)$Id: doscl.cc,v 1.2 2004/06/16 14:29:20 ptr Exp $" +# endif +#endif + +#include <iostream> +#include <string> +#include <sstream> +#include <sockios/sockstream> +#include <mt/xmt.h> +#include <misc/args.h> + +using namespace std; +using namespace __impl; + +int command_whole_timeout_test( iostream& s, const string& hello_host, int delay ) +{ + string rline; + string err_line; + + getline( s, rline ); + + cout << rline << endl; + + timespec t; + t.tv_sec = delay; + t.tv_nsec = 0; + + Thread::delay( &t ); + + s << "EHLO " << hello_host << "\r" << endl; + getline( s, rline ); + + if ( s.good() ) { + // cerr << "Connection even here seems ok" << endl; + cout << rline << endl; + } + getline( s, err_line ); + if ( s.good() ) { + return -1; // connection still ok, timeout not happens + } + + return 0; +} + +int cumulative_command_timeout_test( iostream& s, const string& hello_host, int delay ) +{ + string rline; + string err_line; + + getline( s, rline ); + + cout << rline << endl; + + timespec t; + t.tv_sec = delay; + t.tv_nsec = 0; + + stringstream sstr; + sstr << "EHLO " << hello_host << "\r" << endl; + string greeting( sstr.str() ); + + for ( string::iterator i = greeting.begin(); i != greeting.end(); ++i ) { + Thread::delay( &t ); + s << *i; + s.flush(); + (cout << *i).flush(); + } + + getline( s, rline ); + + if ( s.good() ) { + cout << rline << endl; + } + getline( s, err_line ); + if ( s.good() ) { + return -1; // connection still ok, timeout not happens + } + + // cout << rline << endl; + return 0; +} + +int main( int argc, char * const *argv ) +{ + try { + Argv arg; + arg.copyright( "Copyright (C) K sky Lab, 2003" ); + arg.brief( "test for SMTP GW project" ); + arg.option( "-h", false, "print this help message" ); + arg.option( "-s", string( "" ), "host with SMTP GW server" ); + arg.option( "-p", int(25), "port that listen SMTP GW server" ); + arg.option( "-hello", string( "peak.avp.ru" ), "argument of EHLO/HELO command" ); + arg.option( "-delay", int( 305 ), "delay (timeout) for test" ); + arg.option( "-test", int( 0 ), "test number (0 or 1)" ); + try { + arg.parse( argc, argv ); + } + catch ( std::invalid_argument& err ) { + cerr << err.what() << endl; + arg.print_help( cerr ); + throw 1; + } + bool turn; + if ( arg.assign( "-h", turn ) ) { + arg.print_help( cerr ); + throw 0; + } + + string t_host; + int t_port; + arg.assign( "-s", t_host ); + arg.assign( "-p", t_port ); + + string hello_host; + arg.assign( "-hello", hello_host ); + + int delay; + int test_no; + arg.assign( "-delay", delay ); + arg.assign( "-test", test_no ); + + string rline; + + sockstream s( t_host.data(), t_port ); + if ( test_no == 0 ) { + return command_whole_timeout_test( s, hello_host, delay ); + } else if ( test_no == 1 ) { + return cumulative_command_timeout_test( s, hello_host, delay ); + } + + return -1; + } + catch( int ret ) { + return ret; + } + + return 0; +} Added: trunk/complement/explore/app/SMTP-tools/scgen/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/Makefile (rev 0) +++ trunk/complement/explore/app/SMTP-tools/scgen/Makefile 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,28 @@ +# -*- Makefile -*- Time-stamp: <03/09/08 14:55:56 ptr> +# $Id: Makefile,v 1.1 2003/09/11 10:33:15 ptr Exp $ + +SRCROOT := ../../../../extern/complement +COMPILER_NAME := gcc + +ALL_TAGS := dbg-shared + +include Makefile.inc +include ${SRCROOT}/Makefiles/top.mak + + +INCLUDES += -I$(SRCROOT)/include -I$(STLPORT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR) + +release-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR} +stldbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_STLDBG} +dbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_DBG} + +ifeq ($(OSNAME),sunos) +release-shared : LDLIBS = -lstlport_gcc -lrt +stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lrt +dbg-shared : LDLIBS = -lstlport_gcc -lrt +else +release-shared : LDLIBS = -lstlport_gcc +stldbg-shared : LDLIBS = -lstlport_gcc_stldebug +dbg-shared : LDLIBS = -lstlport_gcc +endif + Added: trunk/complement/explore/app/SMTP-tools/scgen/Makefile.inc =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/Makefile.inc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/scgen/Makefile.inc 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,5 @@ +# -*- makefile -*- Time-stamp: <03/09/09 12:51:17 ptr> +# $Id: Makefile.inc,v 1.1 2003/09/11 10:33:15 ptr Exp $ + +PRGNAME = scgen +SRC_CC = scgen.cc stategraph.cc Added: trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile (rev 0) +++ trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,28 @@ +# -*- Makefile -*- Time-stamp: <03/09/08 14:55:56 ptr> +# $Id: Makefile,v 1.1 2003/10/07 10:50:16 ptr Exp $ + +SRCROOT := ../../../../../extern/complement +COMPILER_NAME := gcc + +ALL_TAGS := dbg-shared + +include Makefile.inc +include ${SRCROOT}/Makefiles/top.mak + + +INCLUDES += -I$(SRCROOT)/include -I$(STLPORT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR) -I.. + +release-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR} +stldbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_STLDBG} +dbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_DBG} + +ifeq ($(OSNAME),sunos) +release-shared : LDLIBS = -lstlport_gcc -lrt +stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lrt +dbg-shared : LDLIBS = -lstlport_gcc -lrt +else +release-shared : LDLIBS = -lstlport_gcc +stldbg-shared : LDLIBS = -lstlport_gcc_stldebug +dbg-shared : LDLIBS = -lstlport_gcc +endif + Added: trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile.inc =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile.inc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/Makefile.inc 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,5 @@ +# -*- makefile -*- Time-stamp: <03/09/09 12:51:17 ptr> +# $Id: Makefile.inc,v 1.1 2003/10/07 10:50:16 ptr Exp $ + +PRGNAME = dropconn +SRC_CC = dropconn.cc ../stategraph.cc Added: trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/dropconn.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/dropconn.cc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/scgen/scgen-dropconn/dropconn.cc 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,129 @@ +// -*- C++ -*- Time-stamp: <03/10/06 18:09:23 ptr> + +#ifdef __unix +# ifdef __HP_aCC +#pragma VERSIONID "@(#)$Id: dropconn.cc,v 1.1 2003/10/07 10:50:16 ptr Exp $" +# else +#ident "@(#)$Id: dropconn.cc,v 1.1 2003/10/07 10:50:16 ptr Exp $" +# endif +#endif + +#include <iostream> +#include "stategraph.h" + +enum vertex { + NotConnected, + Connected, + Greeting, + Mail, + Recipient, + Data, + EndOfData, + NVertices +}; + +enum edge { + _connect_, + _disconnect_, + _QUIT_, + _RSET_, + _EXPN_, + _HELP_, + _VRFY_, + _NOOP_, + _MAIL_, + _HELO_, + _EHLO_, + _RCPT_, + _DATA_, + _EOD_, // end of data + _nothing_, + _NCommands_ +}; + + +int main( int, char * const * ) +{ + StateGraph g( NVertices, std::cout ); + + g.edge( NotConnected, Connected, 5, _connect_ ); + // g.edge( Connected, NotConnected, 10, _QUIT_ ); + // g.edge( Connected, Connected, 1, _RSET_ ); + // g.edge( Connected, Connected, 1, _EXPN_ ); + // g.edge( Connected, Connected, 1, _HELP_ ); + // g.edge( Connected, Connected, 1, _NOOP_ ); + // g.edge( Connected, Connected, 1, _VRFY_ ); + g.edge( Connected, Greeting, 2, _HELO_ ); + g.edge( Connected, Greeting, 1, _EHLO_ ); + // g.edge( Greeting, Greeting, 1, _EHLO_ ); + // g.edge( Greeting, Greeting, 1, _RSET_ ); + // g.edge( Greeting, Greeting, 1, _VRFY_ ); + // g.edge( Greeting, Greeting, 1, _EXPN_ ); + // g.edge( Greeting, Greeting, 1, _HELP_ ); + // g.edge( Greeting, Greeting, 1, _NOOP_ ); + g.edge( Greeting, NotConnected, 10, _QUIT_ ); + g.edge( Greeting, Mail, 1, _MAIL_ ); + g.edge( Greeting, NotConnected, 1, _disconnect_ ); + // g.edge( Mail, Mail, 1, _NOOP_ ); + // g.edge( Mail, Mail, 1, _HELP_ ); + // g.edge( Mail, Greeting, 3, _EHLO_ ); + // g.edge( Mail, Greeting, 3, _RSET_ ); + // g.edge( Mail, NotConnected, 10, _QUIT_ ); + g.edge( Mail, NotConnected, 1, _disconnect_ ); + g.edge( Mail, Recipient, 1, _RCPT_ ); + // g.edge( Recipient, Greeting, 3, _RSET_ ); + // g.edge( Recipient, Greeting, 3, _EHLO_ ); + // g.edge( Recipient, NotConnected, 10, _QUIT_ ); + g.edge( Recipient, NotConnected, 1, _disconnect_ ); + // g.edge( Recipient, Recipient, 1, _NOOP_ ); + // g.edge( Recipient, Recipient, 1, _HELP_ ); + g.edge( Recipient, Data, 1, _DATA_ ); + g.edge( Recipient, NotConnected, 1, _disconnect_ ); + g.edge( Data, EndOfData, 1, _EOD_ ); + g.edge( EndOfData, Greeting, 1, _nothing_ ); + g.edge( EndOfData, NotConnected, 1, _disconnect_ ); + + + std::string host( "$1 $2" ); + std::string hello( "$3" ); + std::string msg_to( "<$5>" ); + std::string msg_from( "<$4>" ); + + g[_connect_] << "# --------------\n" + << "connect " << host << "\n" + << "expected 220\n"; + g[_disconnect_] << "disconnect\n"; + g[_QUIT_] << "QUIT\n" + << "expected 221\n" + << "disconnect\n" + << "# --------------\n"; + g[_RSET_] << "RSET\n" + << "expected 250\n"; + g[_EXPN_] << "EXPN so...@ho...\n" + << "expected\n"; + g[_HELP_] << "HELP\n" + << "expected 250\n"; + g[_VRFY_] << "VRFY so...@ho...\n" + << "expected\n"; + g[_NOOP_] << "NOOP\n" + << "expected 250\n"; + g[_MAIL_] << "MAIL FROM:" << msg_from << "\n" + << "expected 250\n"; + g[_HELO_] << "HELO " << hello << "\n" + << "expected 250\n"; + g[_EHLO_] << "EHLO " << hello << "\n" + << "expected 250\n"; + g[_RCPT_] << "RCPT TO:" << msg_to << "\n" + << "expected 250\n"; + g[_DATA_] << "DATA\n" + << "expected 354\n" + << ">>>A\n" + << "Subject: KL smtp relay test\n\nSample mess\n"; + g[_EOD_] // << "\r\n.\r\n" + << "<<<A\n" + << "expected 250\n"; + + g.girdle( NotConnected ); + + return 0; +} Added: trunk/complement/explore/app/SMTP-tools/scgen/scgen.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/scgen.cc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/scgen/scgen.cc 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,125 @@ +// -*- C++ -*- Time-stamp: <03/10/06 18:10:41 ptr> + +#ifdef __unix +# ifdef __HP_aCC +#pragma VERSIONID "@(#)$Id: scgen.cc,v 1.3 2003/10/06 15:33:52 ptr Exp $" +# else +#ident "@(#)$Id: scgen.cc,v 1.3 2003/10/06 15:33:52 ptr Exp $" +# endif +#endif + +#include <iostream> +#include "stategraph.h" + +using namespace std; + +enum vertex { + NotConnected, + Connected, + Greeting, + Mail, + Recipient, + Data, + EndOfData, + NVertices +}; + +enum edge { + _connect_, + _disconnect_, + _QUIT_, + _RSET_, + _EXPN_, + _HELP_, + _VRFY_, + _NOOP_, + _MAIL_, + _HELO_, + _EHLO_, + _RCPT_, + _DATA_, + _EOD_, // end of data + _nothing_, + _NCommands_ +}; + + +int main( int, char * const * ) +{ + StateGraph g( NVertices, cout ); + + g.edge( NotConnected, Connected, 5, _connect_ ); + g.edge( Connected, NotConnected, 10, _QUIT_ ); + g.edge( Connected, Connected, 1, _RSET_ ); + g.edge( Connected, Connected, 1, _EXPN_ ); + g.edge( Connected, Connected, 1, _HELP_ ); + g.edge( Connected, Connected, 1, _NOOP_ ); + g.edge( Connected, Connected, 1, _VRFY_ ); + g.edge( Connected, Greeting, 2, _HELO_ ); + g.edge( Connected, Greeting, 1, _EHLO_ ); + g.edge( Greeting, Greeting, 1, _EHLO_ ); + g.edge( Greeting, Greeting, 1, _RSET_ ); + g.edge( Greeting, Greeting, 1, _VRFY_ ); + g.edge( Greeting, Greeting, 1, _EXPN_ ); + g.edge( Greeting, Greeting, 1, _HELP_ ); + g.edge( Greeting, Greeting, 1, _NOOP_ ); + g.edge( Greeting, NotConnected, 10, _QUIT_ ); + g.edge( Greeting, Mail, 1, _MAIL_ ); + g.edge( Mail, Mail, 1, _NOOP_ ); + g.edge( Mail, Mail, 1, _HELP_ ); + g.edge( Mail, Greeting, 3, _EHLO_ ); + g.edge( Mail, Greeting, 3, _RSET_ ); + g.edge( Mail, NotConnected, 10, _QUIT_ ); + g.edge( Mail, Recipient, 1, _RCPT_ ); + g.edge( Recipient, Greeting, 3, _RSET_ ); + g.edge( Recipient, Greeting, 3, _EHLO_ ); + g.edge( Recipient, NotConnected, 10, _QUIT_ ); + g.edge( Recipient, Recipient, 1, _NOOP_ ); + g.edge( Recipient, Recipient, 1, _HELP_ ); + g.edge( Recipient, Data, 1, _DATA_ ); + g.edge( Data, EndOfData, 1, _EOD_ ); + g.edge( EndOfData, Greeting, 1, _nothing_ ); + + string host( "$1 $2" ); + string hello( "$3" ); + string msg_to( "<$5>" ); + string msg_from( "<$4>" ); + + g[_connect_] << "# --------------\n" + << "connect " << host << "\n" + << "expected 220\n"; + g[_disconnect_] << "disconnect\n"; + g[_QUIT_] << "QUIT\n" + << "expected 221\n" + << "disconnect\n" + << "# --------------\n"; + g[_RSET_] << "RSET\n" + << "expected 250\n"; + g[_EXPN_] << "EXPN so...@ho...\n" + << "expected\n"; + g[_HELP_] << "HELP\n" + << "expected 250\n"; + g[_VRFY_] << "VRFY so...@ho...\n" + << "expected\n"; + g[_NOOP_] << "NOOP\n" + << "expected 250\n"; + g[_MAIL_] << "MAIL FROM:" << msg_from << "\n" + << "expected 250\n"; + g[_HELO_] << "HELO " << hello << "\n" + << "expected 250\n"; + g[_EHLO_] << "EHLO " << hello << "\n" + << "expected 250\n"; + g[_RCPT_] << "RCPT TO:" << msg_to << "\n" + << "expected 250\n"; + g[_DATA_] << "DATA\n" + << "expected 354\n" + << ">>>A\n" + << "Subject: KL smtp relay test\n\nSample mess\n"; + g[_EOD_] // << "\r\n.\r\n" + << "<<<A\n" + << "expected 250\n"; + + g.girdle( NotConnected ); + + return 0; +} Added: trunk/complement/explore/app/SMTP-tools/scgen/stategraph.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/stategraph.cc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/scgen/stategraph.cc 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,123 @@ +// -*- C++ -*- Time-stamp: <03/09/29 15:22:19 ptr> + +#ifdef __unix +# ifdef __HP_aCC +#pragma VERSIONID "@(#)$Id: stategraph.cc,v 1.2 2003/10/06 07:56:07 ptr Exp $" +# else +#ident "@(#)$Id: stategraph.cc,v 1.2 2003/10/06 07:56:07 ptr Exp $" +# endif +#endif + +#include "stategraph.h" + +using namespace boost; +using namespace std; + +StateGraph::StateGraph( int nv, std::ostream& _out ) : + g( nv ), + out( _out ) +{ + weight = get( edge_weight, g ); + color = get( edge_color, g ); + operation = get( edge_operation, g ); +} + +void StateGraph::edge( int v_from, int v_to, int weight, int operation ) +{ + // the '0' parameter in Color(... is definition of initial color '0' for edge + add_edge( v_from, v_to, EdgeProperty(weight,Color(0,operation)), g ); +} + +StateGraph::vertex_t StateGraph::walk_from( StateGraph::vertex_t v ) +{ + out_edge_iterator_t ei; + out_edge_iterator_t eend; + + for ( tie(ei,eend) = out_edges(v,g); ei != eend; ++ei ) { + if ( color[*ei] == 0 ) { + color[*ei] = 1; + + out << (*this)[operation[*ei]].str(); + return target(*ei, g); + } + } + + return vertex_t(-1); +} + +StateGraph::vertex_t StateGraph::vertex_with_white_edge() +{ + vertex_iterator_t vi; + vertex_iterator_t vie; + for ( tie(vi,vie) = vertices(g); vi != vie; ++vi ) { + out_edge_iterator_t ei; + out_edge_iterator_t eend; + + for ( tie(ei,eend) = out_edges(*vi,g); ei != eend; ++ei ) { + if ( color[*ei] == 0 ) { + return *vi; + } + } + } + + return vertex_t(-1); +} + +int StateGraph::least_cost_edge_aux( const vertex_t& x, const vertex_t& u ) +{ + out_edge_iterator_t ei; + out_edge_iterator_t eend; + out_edge_iterator_t least_cost; + + tie(ei,eend) = out_edges(x,g); + least_cost = eend; + for ( ; ei != eend; ++ei ) { + if ( target(*ei, g) == u ) { + if ( (least_cost == eend) || (weight[*least_cost] > weight[*ei]) ) { + least_cost = ei; + } + } + } + return operation[*least_cost]; +} + +void StateGraph::shortest_path( StateGraph::vertex_t v, StateGraph::vertex_t u ) +{ + vector<vertex_t> p(num_vertices(g)); + vector<int> ops; + + dijkstra_shortest_paths( g, v, predecessor_map(&p[0]) ); + + vertex_t x = p[u]; + while ( x != v ) { + ops.push_back( least_cost_edge_aux(x,u) ); + u = x; + x = p[u]; + } + ops.push_back( least_cost_edge_aux(x,u) ); // last step + + for ( vector<int>::reverse_iterator i = ops.rbegin(); i != ops.rend(); ++i ) { + out << (*this)[*i].str(); + } +} + +void StateGraph::girdle( int start ) +{ + vertex_t v = walk_from( start ); + vertex_t u = v; + + do { + while ( v != vertex_t(-1) ) { + u = v; + v = walk_from( u ); + } + v = vertex_with_white_edge(); + if ( v == vertex_t(-1) ) { + break; + } + shortest_path( u, v ); + } while ( true ); + if ( u != start ) { + shortest_path( u, start ); + } +} Added: trunk/complement/explore/app/SMTP-tools/scgen/stategraph.h =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/stategraph.h (rev 0) +++ trunk/complement/explore/app/SMTP-tools/scgen/stategraph.h 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,82 @@ +// -*- C++ -*- Time-stamp: <03/09/29 15:21:11 ptr> + +#ifdef __unix +# ifdef __HP_aCC +#pragma VERSIONID "@(#)$Id: stategraph.h,v 1.2 2003/10/06 07:56:07 ptr Exp $" +# else +#ident "@(#)$Id: stategraph.h,v 1.2 2003/10/06 07:56:07 ptr Exp $" +# endif +#endif + +#include <iostream> +#include <sstream> +#include <map> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/dijkstra_shortest_paths.hpp> + +//using namespace boost; +//using namespace std; + +enum edge_operation_t { edge_operation }; + +namespace boost { + BOOST_INSTALL_PROPERTY( edge, operation ); +} // namespace boost + + +//typedef property<edge_operation_t,int> Operation; +//typedef property<edge_color_t,int,Operation> Color; + + +class StateGraph +{ + private: + typedef boost::property<edge_operation_t,int> Operation; + typedef boost::property<boost::edge_color_t,int,Operation> Color; + typedef boost::property<boost::edge_weight_t,int,Color> EdgeProperty; + + typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::no_property, EdgeProperty > graph_t; + typedef boost::graph_traits<graph_t>::out_edge_iterator out_edge_iterator_t; + typedef boost::graph_traits<graph_t>::vertex_iterator vertex_iterator_t; + + typedef boost::graph_traits<graph_t>::vertex_descriptor vertex_t; + + typedef boost::property_map<graph_t,boost::edge_color_t>::type edge_color_map_t; + typedef boost::property_map<graph_t,boost::edge_weight_t>::type edge_weight_map_t; + typedef boost::property_map<graph_t,edge_operation_t>::type edge_operation_map_t; + + typedef std::vector<vertex_t> predecessor_map_t; + + public: + StateGraph( int, std::ostream& ); + + void edge( int v_from, int v_to, int weight, int operation ); + std::stringstream& operator [] ( int key ) + { + std::stringstream *_s = _cmd[key]; + if ( _s == 0 ) { + _s = new std::stringstream(); + _cmd[key] = _s; + } + return *_s; + } + + void girdle( int start ); + + private: + + graph_t g; + edge_weight_map_t weight; + edge_color_map_t color; + edge_operation_map_t operation; + + void shortest_path( vertex_t, vertex_t ); + vertex_t walk_from( vertex_t v ); + vertex_t vertex_with_white_edge(); + int least_cost_edge_aux( const vertex_t&, const vertex_t& ); + + std::map<int,std::stringstream *> _cmd; + + std::ostream& out; +}; + Added: trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile (rev 0) +++ trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,28 @@ +# -*- Makefile -*- Time-stamp: <03/09/09 12:54:58 ptr> +# $Id: Makefile,v 1.1 2003/09/11 10:34:11 ptr Exp $ + +SRCROOT := ../../../../../extern/complement +COMPILER_NAME := gcc + +ALL_TAGS := dbg-shared + +include Makefile.inc +include ${SRCROOT}/Makefiles/top.mak + + +INCLUDES += -I$(SRCROOT)/include -I$(STLPORT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR) -I.. + +release-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR} +stldbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_STLDBG} +dbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_DBG} + +ifeq ($(OSNAME),sunos) +release-shared : LDLIBS = -lstlport_gcc -lrt +stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lrt +dbg-shared : LDLIBS = -lstlport_gcc -lrt +else +release-shared : LDLIBS = -lstlport_gcc -lboost_test_utf_gcc +stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lboost_test_utf_gcc_stl-g +dbg-shared : LDLIBS = -lstlport_gcc -lboost_test_utf_gcc-g +endif + Added: trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile.inc =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile.inc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/scgen/ut/Makefile.inc 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,5 @@ +# -*- makefile -*- Time-stamp: <03/09/09 12:51:52 ptr> +# $Id: Makefile.inc,v 1.1 2003/09/11 10:34:11 ptr Exp $ + +PRGNAME = ut +SRC_CC = unit_test.cc ../stategraph.cc Added: trunk/complement/explore/app/SMTP-tools/scgen/ut/unit_test.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/scgen/ut/unit_test.cc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/scgen/ut/unit_test.cc 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,88 @@ +// -*- C++ -*- Time-stamp: <03/09/29 15:21:38 ptr> + +#ifdef __unix +# ifdef __HP_aCC +#pragma VERSIONID "@(#)$Id: unit_test.cc,v 1.2 2003/10/06 07:56:08 ptr Exp $" +# else +#ident "@(#)$Id: unit_test.cc,v 1.2 2003/10/06 07:56:08 ptr Exp $" +# endif +#endif + +#include <boost/test/unit_test.hpp> + +using namespace boost::unit_test_framework; +using namespace std; + +#include <iostream> +#include <sstream> + +#include "stategraph.h" + + +enum vertex { + NotConnected, + Connected, + Greeting, + NVertices +}; + +enum edge { + _connect_, + _disconnect_, + _QUIT_, + _HELO_, + _NCommands_ +}; + +void girdle_test_1() +{ + stringstream s; + + StateGraph g( NVertices, s ); + + g.edge( NotConnected, Connected, 5, _connect_ ); + g.edge( Connected, Greeting, 1, _HELO_ ); + g.edge( Greeting, NotConnected, 5, _QUIT_ ); + + g[_connect_] << "1."; + g[_disconnect_] << "2."; + g[_QUIT_] << "3."; + g[_HELO_] << "4."; + + g.girdle( NotConnected ); + + BOOST_REQUIRE( s.str() == "1.4.3." ); +} + +void girdle_test_2() +{ + stringstream s; + + StateGraph g( NVertices, s ); + + g.edge( NotConnected, Connected, 5, _connect_ ); + g.edge( Connected, Greeting, 1, _HELO_ ); + g.edge( Greeting, NotConnected, 5, _QUIT_ ); + g.edge( Greeting, NotConnected, 10, _disconnect_ ); + g.edge( Connected, NotConnected, 10, _disconnect_ ); + + g[_connect_] << "1."; + g[_disconnect_] << "2."; + g[_QUIT_] << "3."; + g[_HELO_] << "4."; + + g.girdle( NotConnected ); + + BOOST_REQUIRE( s.str() == "1.4.3.1.2.1.4.2." ); + // cout << s.str() << endl; +} + +test_suite *init_unit_test_suite( int argc, char **argv ) +{ + test_suite *ts = BOOST_TEST_SUITE( "StateGraph test" ); + + ts->add( BOOST_TEST_CASE( &girdle_test_1 ) ); + ts->add( BOOST_TEST_CASE( &girdle_test_2 ) ); + + return ts; +} Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-addr-2 =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-addr-2 (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-addr-2 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,10 @@ +# comment +connect $1 $2 +expected 220 +EHLO $3 +expected 250 +MAIL FROM:<x@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com> +expected 500 +QUIT +expected 221 +disconnect Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-body-1 =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-body-1 (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-body-1 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,23 @@ +# bad-body-1 +connect $1 $2 +expected 220 +EHLO $3 +expected 250 +MAIL FROM:<$4> +expected 250 +RCPT TO:<$5> +expected 250 +send $6 $7 +DATA +expected 354 +>>>A +Subject: KL smtp relay test + +Expected 1 +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +<<<A +expected 500 +wait +QUIT +expected 221 +disconnect Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-domain-1 =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-domain-1 (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/bad-domain-1 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,8 @@ +# comment +connect $1 $2 +expected 220 +EHLO badhost +expected 250 +QUIT +expected 221 +disconnect Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/dot-line =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/dot-line (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/dot-line 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,28 @@ +# comment +connect $1 $2 +expected 220 +EHLO $3 +expected 250 +MAIL FROM:<$4> +expected 250 +RCPT TO:<$4> +expected 250 +#send $5 $6 +DATA +expected 354 +>>>A +Subject: KL smtp relay test + +Expected 1 and 2 should be here: 1, 2. More chars. +. +You must see this line. + +. + +And this line too! +<<<A +expected 250 +#wait +QUIT +expected 221 +disconnect Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/good-addr =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/good-addr (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/good-addr 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,23 @@ +# good-addr test +connect $1 $2 +expected 220 +EHLO $3 +expected 250 +MAIL FROM:<$4> +expected 250 +RCPT TO:<$5> +expected 250 +send $6 $7 +DATA +expected 354 +>>>A +Subject: KL smtp relay test + +Expected 1 +<<<A +expected 250 +wait +QUIT +expected 221 +disconnect +# end of good-addr test Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/good-domain-1 =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/good-domain-1 (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/good-domain-1 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,8 @@ +# comment +connect localhost 10025 +expected 220 +EHLO peak.avp.ru +expected 250 +QUIT +expected 221 +disconnect Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/good-domain-2 =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/good-domain-2 (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/good-domain-2 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,8 @@ +# comment +connect localhost 10025 +expected 220 +EHLO 127.0.0.1 +expected 250 +QUIT +expected 221 +disconnect Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/null-char =================================================================== (Binary files differ) Property changes on: trunk/complement/explore/app/SMTP-tools/smtp-ut/null-char ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/scr.sed =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/scr.sed (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/scr.sed 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,24 @@ +# This is sed script to generate MTA test script from output of command like +# find /opt/mcollection/1/Disinfected/ -type f -print + +i \ +# ----- begin\ +connect $1 $2\ +expected 220\ +EHLO $3\ +expected 250\ +MAIL FROM:<$4>\ +expected 250\ +RCPT TO:<$5>\ +expected 250\ +send $6 $7\ +DATA\ +expected 354 +s/\(.*\)/include "\1"/ +a \ +expected 250\ +wait\ +QUIT\ +expected 221\ +disconnect\ +# ----- end Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,28 @@ +# -*- Makefile -*- Time-stamp: <04/05/06 14:30:08 ptr> +# $Id: Makefile,v 1.1 2004/06/16 14:24:07 ptr Exp $ + +#SRCROOT := ../../../../extern/complement +SRCROOT := ../../../../../../island/workshop/explore +COMPILER_NAME := gcc + +include Makefile.inc +include ${SRCROOT}/Makefiles/top.mak + + +DEFS += -D_NO_TEST +INCLUDES += -I$(SRCROOT)/include -I$(STLPORT_INCLUDE_DIR) -I$(BOOST_INCLUDE_DIR) + +release-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR} -Wl,-rpath=${STLPORT_LIB_DIR} +stldbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_STLDBG} -Wl,-rpath=${STLPORT_LIB_DIR} +dbg-shared: LDSEARCH = -L${STLPORT_LIB_DIR} -L${CoMT_LIB_DIR_DBG} -Wl,-rpath=${STLPORT_LIB_DIR} + +ifeq ($(OSNAME),sunos) +release-shared : LDLIBS = -lstlport_gcc -lrt +stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lrt +dbg-shared : LDLIBS = -lstlport_gcc_debug -lrt +else +release-shared : LDLIBS = -lstlport_gcc -lxmt_gcc -lsockios_gcc -lmisc_gcc -lboost_regex_gcc +stldbg-shared : LDLIBS = -lstlport_gcc_stldebug -lxmt_gcc_stl-g -lsockios_gcc_stl-g -lmisc_gcc_stl-g -lboost_regex_gcc_stl-g +dbg-shared : LDLIBS = -lstlport_gcc_debug -lxmt_gcc-g -lsockios_gcc-g -lmisc_gcc-g -lboost_regex_gcc-g +endif + Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile.inc =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile.inc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/Makefile.inc 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,5 @@ +# -*- makefile -*- Time-stamp: <03/09/15 18:23:15 ptr> +# $Id: Makefile.inc,v 1.1 2004/06/16 14:24:07 ptr Exp $ + +PRGNAME = smtp-batch +SRC_CC = smtp-batch.cc Added: trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/smtp-batch.cc =================================================================== --- trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/smtp-batch.cc (rev 0) +++ trunk/complement/explore/app/SMTP-tools/smtp-ut/smtp-batch/smtp-batch.cc 2008-04-09 10:22:41 UTC (rev 1844) @@ -0,0 +1,574 @@ +// -*- C++ -*- Time-stamp: <04/06/16 12:51:35 ptr> + +#ifdef __unix +# ifdef __HP_aCC +#pragma VERSIONID "@(#)$Id: smtp-batch.cc,v 1.1 2004/06/16 14:24:07 ptr Exp $" +# else +#ident "@(#)$Id: smtp-batch.cc,v 1.1 2004/06/16 14:24:07 ptr Exp $" +# endif +#endif + + +#include <mt/xmt.h> +#include <mt/time.h> +#include <sockios/sockstream> +#include <misc/args.h> + +#include <iostream> +#include <iomanip> +#include <fstream> +#include <map> + +#include <boost/regex.hpp> + +using namespace std; +using namespace boost; + +struct conn +{ + conn() + { + tm[0].tv_sec = tm[1].tv_sec = tm[2].tv_sec = 0; + tm[0].tv_nsec = tm[1].tv_nsec = tm[2].tv_nsec = 0; + } + + conn( const conn& _c ) + { tm[0] = _c.tm[0]; tm[1] = _c.tm[1]; tm[2] = _c.tm[2]; } + + timespec tm[3]; // time of send, time of response, elapsed interval (from tecol server) +}; + +typedef std::pair<std::string,conn> map_type; +typedef std::map<std::string,conn> container_type; +static container_type m; +static container_type finished; + +enum command_type { + UNKNOWN = 0, + HELO, + EHLO, + VRFY, + EXPN, + NOOP, + RSET, + QUIT, + DATA, + HELP, + MAIL, + RCPT, + _connect_, + _disconnect_, + _wait_, + _include_, + _send_, + _expected_, + _delay_, + LAST_CMD +}; + +map<command_type,string> CMD; +sockstream tecol; +__impl::Condition tecol_ready; + +void init_map() +{ + CMD[UNKNOWN] = ""; + CMD[HELO] = "HELO"; + CMD[EHLO] = "EHLO"; + CMD[VRFY] = "VRFY"; + CMD[EXPN] = "EXPN"; + CMD[NOOP] = "NOOP"; + CMD[RSET] = "RSET"; + CMD[QUIT] = "QUIT"; + CMD[DATA] = "DATA"; + CMD[HELP] = "HELP"; + CMD[MAIL] = "MAIL"; + CMD[RCPT] = "RCPT"; + CMD[_connect_] = "connect"; + CMD[_disconnect_] = "disconnect"; + CMD[_wait_] = "wait"; + CMD[_include_] = "include"; + CMD[_send_] = "send"; + CMD[_expected_] = "expected"; + CMD[_delay_] = "delay"; +} + +class RAWclient +{ + public: + RAWclient() + { } + + ~RAWclient() + { + s.close(); + sess << "== " << calendar_time( time(0) ) << endl; + } + + void open( const string& host, int port, const string& log ) + { + if ( !sess.is_open() ) { + sess.open( log.c_str() ); + sess << "== " << calendar_time( time(0) ) << ' ' + << "this prg name and args" << endl; + } + s.open( host.c_str(), port ); + // _hostname = host; + // _port = port; + sess << "=+ " << calendar_time( time(0) ) + << ' ' << host << ':' << port << endl; + } + + void close() + { + s.close(); + sess << "=- " << calendar_time( time(0) ) << endl; + // sess.close(); + } + + // bool is_open() const + // { return s.is_open(); } + + // const string& hostname() const + // { return _hostname; } + + // int port() const + // { return _port; } + + void command( const string& str ) + { + s << str << "\r\n"; + s.flush(); + sess << "<- " << str << "\r\n"; + } + + int response( string& text ) + { + string line; + text.clear(); + getline( s, line ); + sess << "-> " << line; + while ( line.length() > 3 && line[3] == '-' ) { + text += line.substr( 4 ); + getline( s, line ); + sess << "\n-> " << line; + } + text += line; + stringstream str( line ); + int ret; + str >> ret; + getline( str, text ); + sess << endl; + return ret; + } + + string rawline() + { + string line; + getline( s, line ); + sess << "-> " << line << endl; + + return line; + } + + void write_silent( const string& str ) + { + s << str; + s.flush(); + } + + template <class InputIter> + void write_silent( InputIter b, InputIter e ) + { + ostream_iterator<char> o( s ); + copy( b, e, o ); + s.flush(); + } + + void write( const string& str ) + { + s << str; + /* + if ( str is "^\r\n" ) { + sess << "<- \n"; + skip NL + } + */ + sess << "<- " << str; + s.flush(); + } + + void mark_in_log( const string& str ) + { + sess << "!! " << str; + } + + void import_in_log( const string& str ) + { + sess << "<= " << str << '\n'; + } + + private: + sockstream s; + ofstream sess; + + // string _hostname; + // int _port; +}; + +command_type cmd_token( const string& cmd ) +{ + if ( cmd == "HELO" ) { + return HELO; + } else if ( cmd == "EHLO" ) { + return EHLO; + } else if ( cmd == "VRFY" ) { + return VRFY; + } else if ( cmd == "EXPN" ) { + return EXPN; + } else if ( cmd == "NOOP" ) { + return NOOP; + } else if ( cmd == "RSET" ) { + return RSET; + } else if ( cmd == "QUIT" ) { + return QUIT; + } else if ( cmd == "DATA" ) { + return DATA; + } else if ( cmd == "HELP" ) { + return HELP; + } else if ( cmd == "MAIL" ) { + return MAIL; + } else if ( cmd == "RCPT" ) { + return RCPT; + } else if ( cmd == "connect" ) { + return _connect_; + } else if ( cmd == "disconnect" ) { + return _disconnect_; + } else if ( cmd == "wait" ) { + return _wait_; + } else if ( cmd == "include" ) { + return _include_; + } else if ( cmd == "send" ) { + return _send_; + } else if ( cmd == "expected" ) { + return _expected_; + } else if ( cmd == "delay" ) { + return _delay_; + } + + return UNKNOWN; +} + +void interpret( istream& is, const Argv& arg ) +{ + string s; + ostringstream re; // ( "(\'.*?\')|(\".*?\")" ); + // re.seekp( 5, ios_base::beg ); + // cout << re.tellp() << endl; + re << "(\'.*?\')|(\".*?\")"; + for ( int j = 0; j < arg.size(); ++j ) { + re << "|(\\$" << (j+1) << ")"; + } + // cout << re.str().size() << endl; + // cout << re.str() << endl; + regex REcomment( "(\'.*?\')|(\".*?\")|(#.*)" ); + regex REqoutes( re.str() ); + // regex REname( "([[:space:]]+)((\'(.*?)\')|(\"(.*?)\")|(([[:alnum:]]|(\\\\.))+))" ); + regex REname( "(\'(.*?)\')|(\"(.*?)\")|(([[:word:]\\\\.\\$/,%~+-=])+)" ); + regex REescape( "(\\\\(.))" ); + + re.str( "" ); + re.clear(); + re << "(?1$&)(?2$&)"; + + for ( int j = 0; j < arg.size(); ++j ) { + // "()" used here to separate ?N from replacement string, + // that may contain digits. + re << "(?" << (j+3) << "()" << arg[j] << ")"; + } + // cout << re.str().size() << endl; + // cout << re.str() << endl; + string fmt = re.str(); + + bool verbatim_mode = false; + string verbatim_code; + int ln = 0; + + RAWclient client; + bool send_flag = false; + string id; + + init_map(); + + command_type last_command = UNKNOWN; + + char buf[64]; + gethostname( buf, 64 ); + string my_host_name = buf; + + string lfname; + arg.assign( "-l", lfname ); + + bool nodelay; + arg.assign( "-nodelay", nodelay ); + + while ( is.good() ) { + getline( is, s ); + if ( !is.fail() ) { + ++ln; + s = regex_replace( s, REqoutes, fmt, boost::match_default | boost::format_all ); + cout << ln << ": " << s << endl; + if ( !verbatim_mode ) { + // strip comments + string sr = regex_replace( s, REcomment, "(?1$&)(?2$&)(?3)", boost::match_default | boost::format_all ); + string::size_type p; + if ( (p = sr.find( ">>>" )) != string::npos ) { // start verbatim + verbatim_mode = true; + verbatim_code = sr.substr( p + 3 ); + if ( last_command == DATA && send_flag ) { + string tmp( "X-smtpgw-test: " ); + tmp += id; + tmp += " action=recv\n"; + client.write( tmp ); + send_flag = false; + } + continue; + } + istringstream ss( sr ); + string cmd; + ss >> cmd; + if ( cmd.size() > 0 ) { + command_type command = cmd_token( cmd ); + string host; + int port; + int expected; + string rest; + switch ( command ) { + case _connect_: + ss >> host >> port; + // cout << "connect " << host << ":" << port << endl; + client.open( host, port, lfname ); + break; + case HELO: + case EHLO: + case VRFY: + case EXPN: + getline( ss, rest ); + client.command( CMD[command] + rest ); + last_command = command; + // cout << CMD[command] << rest << endl; + break; + case NOOP: + case RSET: + case QUIT: + case DATA: + client.command( CMD[command] ); + // cout << CMD[command] << endl; + last_command = command; + break; + case HELP: + getline( ss, rest ); + client.command( CMD[command] + rest ); + // cout << CMD[command] << rest << endl; + break; + case MAIL: + case RCPT: + getline( ss, rest ); + client.command( CMD[command] + rest ); + last_command = command; + // cout << CMD[command] << rest << endl; + break; + case _disconnect_: + client.close(); + // cout << CMD[command] << endl; + break; + case _expected_: + ss >> expected; + getline( ss, rest ); + { + string txt; + int resp = client.response( txt ); + if ( resp != expected ) { + stringstream msg; + msg << "Unexpected return code after command " + << CMD[last_command] << ": " + << resp << " (expected " << expected << ")" << endl; + client.mark_in_log( msg.str() ); + cerr << msg.str(); + } + // cout << CMD[command] << rest << endl; + } + break; + case _send_: + ss >> host >> port; + // cout << "send " << host << ":" << port <... [truncated message content] |
From: <com...@us...> - 2008-04-04 06:25:44
|
Revision: 1843 http://complement.svn.sourceforge.net/complement/?rev=1843&view=rev Author: complement Date: 2008-04-03 23:25:40 -0700 (Thu, 03 Apr 2008) Log Message: ----------- add final() for listener to give chance to destroy slave Connectors; under construction Modified Paths: -------------- branches/complement-sockios/explore/include/sockios/sp.h branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc Modified: branches/complement-sockios/explore/include/sockios/sp.h =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.h 2008-04-03 06:12:50 UTC (rev 1842) +++ branches/complement-sockios/explore/include/sockios/sp.h 2008-04-04 06:25:40 UTC (rev 1843) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/04/03 01:05:05 ptr> +// -*- C++ -*- Time-stamp: <08/04/04 01:02:50 ptr> /* * Copyright (c) 2008 @@ -77,8 +77,12 @@ { sock_processor_base::open( port, t, sock_base2::inet ); } virtual ~sock_processor_base() - { sock_processor_base::close(); } + { + sock_processor_base::close(); + basic_socket<charT,traits,_Alloc>::mgr->final( *this ); + } + void open( const in_addr& addr, int port, sock_base2::stype type, sock_base2::protocol prot ); void open( unsigned long addr, int port, sock_base2::stype type, sock_base2::protocol prot ) @@ -722,6 +726,8 @@ closed_queue[_fd] = info; } + void final( socks_processor_t& p ); + void exit_notify( sockbuf_t* b, int fd ) { fd_info info = { 0, reinterpret_cast<sockstream_t*>(b), 0 }; @@ -759,9 +765,41 @@ fd_container_type descr; fd_container_type closed_queue; std::tr2::mutex cll; + std::tr2::mutex dll; }; template<class charT, class traits, class _Alloc> +void sockmgr<charT,traits,_Alloc>::final( sockmgr<charT,traits,_Alloc>::socks_processor_t& p ) +{ + // lock descr here ... should be + std::tr2::lock_guard<std::tr2::mutex> lk_descr( dll ); + + for ( typename fd_container_type::iterator ifd = descr.begin(); ifd != descr.end(); ) { + if ( (ifd->second.flags & fd_info::owner) && (ifd->second.p == &p) ) { + std::cerr << (void*)&p << " " << (void*)ifd->second.s.s << std::endl; + p( *ifd->second.s.s, typename socks_processor_t::adopt_close_t() ); + delete ifd->second.s.s; + if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { + // throw system_error + } + descr.erase( ifd++ ); + } else { + ++ifd; + } + } + + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + + // I can't use closed_queue.erase( p.fd() ) here: fd is -1 already + for ( typename fd_container_type::iterator closed_ifd = closed_queue.begin(); closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == &p ) { + closed_queue.erase( closed_ifd ); + break; + } + } +} + +template<class charT, class traits, class _Alloc> void sockmgr<charT,traits,_Alloc>::io_worker() { epoll_event ev[/*n_ret*/ 512 ]; @@ -780,6 +818,7 @@ try { for ( ; ; ) { int n = epoll_wait( efd, &ev[0], /* n_ret */ 512, -1 ); + if ( n < 0 ) { if ( errno == EINTR ) { continue; @@ -787,6 +826,9 @@ // throw system_error } // std::cerr << "epoll see " << n << std::endl; + + std::tr2::lock_guard<std::tr2::mutex> lk( dll ); + for ( int i = 0; i < n; ++i ) { // std::cerr << "epoll i = " << i << std::endl; if ( ev[i].data.fd == pipefd[0] ) { @@ -934,6 +976,7 @@ try { s = new sockstream_t(); + std::cerr << "sockstream_t: " << (void*)s << std::endl; if ( s->rdbuf()->_open_sockmgr( fd, addr ) ) { epoll_event ev_add; ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; @@ -1103,6 +1146,7 @@ if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { // throw system_error } + bool need_delete = true; if ( info.p != 0 ) { std::tr2::lock_guard<std::tr2::mutex> lk( cll ); typename fd_container_type::iterator closed_ifd = closed_queue.begin(); @@ -1114,11 +1158,13 @@ if ( closed_ifd == closed_queue.end() ) { (*info.p)( *info.s.s, typename socks_processor_t::adopt_close_t() ); } else { + need_delete = false; // will be deleted in 'final' method std::cerr << "@@@ 4\n" << std::endl; } } - if ( (info.flags & fd_info::owner) != 0 ) { + if ( (info.flags & fd_info::owner) != 0 && need_delete ) { delete info.s.s; + info.s.s = 0; } else { if ( (info.flags & fd_info::buffer) != 0 ) { info.s.b->close(); Modified: branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc =================================================================== --- branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc 2008-04-03 06:12:50 UTC (rev 1842) +++ branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc 2008-04-04 06:25:40 UTC (rev 1843) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/04/02 01:48:59 ptr> +// -*- C++ -*- Time-stamp: <08/04/04 01:06:58 ptr> /* * @@ -271,7 +271,7 @@ unique_lock<mutex> lk( worker::lock ); - worker::cnd.timed_wait( lk, milliseconds( 100 ), visits_counter1 ); + worker::cnd.timed_wait( lk, milliseconds( 500 ), visits_counter1 ); EXAM_CHECK( worker::visits == 1 ); worker::visits = 0; @@ -304,7 +304,7 @@ // } unique_lock<mutex> lk( worker::lock ); - worker::cnd.timed_wait( lk, milliseconds( 500 ), visits_counter2 ); + worker::cnd.timed_wait( lk, milliseconds( 1000 ), visits_counter2 ); EXAM_CHECK( worker::visits == 2 ); worker::visits = 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-03 06:12:53
|
Revision: 1842 http://complement.svn.sourceforge.net/complement/?rev=1842&view=rev Author: complement Date: 2008-04-02 23:12:50 -0700 (Wed, 02 Apr 2008) Log Message: ----------- throw from loop, if stop cmd detected; under construction Modified Paths: -------------- branches/complement-sockios/explore/include/sockios/sp.h Modified: branches/complement-sockios/explore/include/sockios/sp.h =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.h 2008-04-02 18:44:21 UTC (rev 1841) +++ branches/complement-sockios/explore/include/sockios/sp.h 2008-04-03 06:12:50 UTC (rev 1842) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/04/02 22:22:19 yeti> +// -*- C++ -*- Time-stamp: <08/04/03 01:05:05 ptr> /* * Copyright (c) 2008 @@ -778,40 +778,40 @@ */ try { - for ( ; ; ) { - int n = epoll_wait( efd, &ev[0], /* n_ret */ 512, -1 ); - if ( n < 0 ) { - if ( errno == EINTR ) { - continue; + for ( ; ; ) { + int n = epoll_wait( efd, &ev[0], /* n_ret */ 512, -1 ); + if ( n < 0 ) { + if ( errno == EINTR ) { + continue; + } + // throw system_error } - // throw system_error - } - // std::cerr << "epoll see " << n << std::endl; - for ( int i = 0; i < n; ++i ) { - // std::cerr << "epoll i = " << i << std::endl; - if ( ev[i].data.fd == pipefd[0] ) { - // std::cerr << "on pipe\n"; - cmd_from_pipe(); - } else { - // std::cerr << "#\n"; + // std::cerr << "epoll see " << n << std::endl; + for ( int i = 0; i < n; ++i ) { + // std::cerr << "epoll i = " << i << std::endl; + if ( ev[i].data.fd == pipefd[0] ) { + // std::cerr << "on pipe\n"; + cmd_from_pipe(); + } else { + // std::cerr << "#\n"; - typename fd_container_type::iterator ifd = descr.find( ev[i].data.fd ); - if ( ifd == descr.end() ) { - throw std::logic_error( "file descriptor in epoll, but not in descr[]" ); - } + typename fd_container_type::iterator ifd = descr.find( ev[i].data.fd ); + if ( ifd == descr.end() ) { + throw std::logic_error( "file descriptor in epoll, but not in descr[]" ); + } - fd_info& info = ifd->second; - if ( info.flags & fd_info::listener ) { - // std::cerr << "%\n"; - process_listener( ev[i], ifd ); - } else { - // std::cerr << "not listener\n"; - process_regular( ev[i], ifd ); + fd_info& info = ifd->second; + if ( info.flags & fd_info::listener ) { + // std::cerr << "%\n"; + process_listener( ev[i], ifd ); + } else { + // std::cerr << "not listener\n"; + process_regular( ev[i], ifd ); + } } } } } - } catch ( std::exception& e ) { std::cerr << e.what() << std::endl; } @@ -828,8 +828,8 @@ // throw system_error // std::cerr << "Read pipe\n"; } else if ( r == 0 ) { - std::cerr << "Read pipe 0\n"; - return; + // std::cerr << "Read pipe 0\n"; + throw runtime_error( "Read pipe return 0" ); } switch ( _ctl.cmd ) { @@ -877,7 +877,7 @@ break; case rqstop: // std::cerr << "Stop request\n"; - return; + throw runtime_error( "Stop request (normal flow)" ); break; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-02 18:44:25
|
Revision: 1841 http://complement.svn.sourceforge.net/complement/?rev=1841&view=rev Author: complement Date: 2008-04-02 11:44:21 -0700 (Wed, 02 Apr 2008) Log Message: ----------- spit long function into shorter ones; under construction Modified Paths: -------------- branches/complement-sockios/explore/include/sockios/sp.h Modified: branches/complement-sockios/explore/include/sockios/sp.h =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.h 2008-04-02 07:23:05 UTC (rev 1840) +++ branches/complement-sockios/explore/include/sockios/sp.h 2008-04-02 18:44:21 UTC (rev 1841) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/04/02 10:25:57 ptr> +// -*- C++ -*- Time-stamp: <08/04/02 22:22:19 yeti> /* * Copyright (c) 2008 @@ -735,13 +735,7 @@ sockmgr& operator =( const sockmgr& ) { return *this; } - void io_worker(); - int efd; - int pipefd[2]; - std::tr2::thread *_worker; - const int n_ret; - #ifdef __USE_STLPORT_HASH typedef std::hash_map<int,fd_info> fd_container_type; #endif @@ -752,6 +746,16 @@ typedef std::tr1::unordered_map<int, fd_info> fd_container_type; #endif + void io_worker(); + void cmd_from_pipe(); + void process_listener( epoll_event&, typename fd_container_type::iterator ); + void process_regular( epoll_event&, typename fd_container_type::iterator ); + + int efd; + int pipefd[2]; + std::tr2::thread *_worker; + const int n_ret; + fd_container_type descr; fd_container_type closed_queue; std::tr2::mutex cll; @@ -787,341 +791,363 @@ // std::cerr << "epoll i = " << i << std::endl; if ( ev[i].data.fd == pipefd[0] ) { // std::cerr << "on pipe\n"; - epoll_event ev_add; - ctl _ctl; - int r = read( pipefd[0], &_ctl, sizeof(ctl) ); - if ( r < 0 ) { + cmd_from_pipe(); + } else { + // std::cerr << "#\n"; + + typename fd_container_type::iterator ifd = descr.find( ev[i].data.fd ); + if ( ifd == descr.end() ) { + throw std::logic_error( "file descriptor in epoll, but not in descr[]" ); + } + + fd_info& info = ifd->second; + if ( info.flags & fd_info::listener ) { + // std::cerr << "%\n"; + process_listener( ev[i], ifd ); + } else { + // std::cerr << "not listener\n"; + process_regular( ev[i], ifd ); + } + } + } + } + } + catch ( std::exception& e ) { + std::cerr << e.what() << std::endl; + } +} + +template<class charT, class traits, class _Alloc> +void sockmgr<charT,traits,_Alloc>::cmd_from_pipe() +{ + epoll_event ev_add; + ctl _ctl; + + int r = read( pipefd[0], &_ctl, sizeof(ctl) ); + if ( r < 0 ) { + // throw system_error + // std::cerr << "Read pipe\n"; + } else if ( r == 0 ) { + std::cerr << "Read pipe 0\n"; + return; + } + + switch ( _ctl.cmd ) { + case listener: + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = static_cast<socks_processor_t*>(_ctl.data.ptr)->fd(); + if ( ev_add.data.fd >= 0 ) { + if ( fcntl( ev_add.data.fd, F_SETFL, fcntl( ev_add.data.fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { + // std::cerr << "xxx " << errno << " " << std::tr2::getpid() << std::endl; + throw std::runtime_error( "can't establish nonblock mode on listener" ); + } + fd_info new_info = { fd_info::listener, 0, static_cast<socks_processor_t*>(_ctl.data.ptr) }; + descr[ev_add.data.fd] = new_info; + if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { + descr.erase( ev_add.data.fd ); // throw system_error - // std::cerr << "Read pipe\n"; - } else if ( r == 0 ) { - std::cerr << "Read pipe 0\n"; - return; } - - switch ( _ctl.cmd ) { - case listener: - ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - ev_add.data.fd = static_cast<socks_processor_t*>(_ctl.data.ptr)->fd(); - if ( ev_add.data.fd >= 0 ) { - if ( fcntl( ev_add.data.fd, F_SETFL, fcntl( ev_add.data.fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { - // std::cerr << "xxx " << errno << " " << std::tr2::getpid() << std::endl; - throw std::runtime_error( "can't establish nonblock mode on listener" ); - } - fd_info new_info = { fd_info::listener, 0, static_cast<socks_processor_t*>(_ctl.data.ptr) }; - descr[ev_add.data.fd] = new_info; - if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { - descr.erase( ev_add.data.fd ); - // throw system_error - } - } - break; + } + break; #if 0 - case tcp_stream: - ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - ev_add.data.fd = static_cast<sockstream_t*>(_ctl.data.ptr)->rdbuf()->fd(); - if ( ev_add.data.fd >= 0 ) { - fd_info new_info = { 0, static_cast<sockstream_t*>(_ctl.data.ptr), 0 }; - descr[ev_add.data.fd] = new_info; - if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { - descr.erase( ev_add.data.fd ); - // throw system_error - } - } - break; + case tcp_stream: + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = static_cast<sockstream_t*>(_ctl.data.ptr)->rdbuf()->fd(); + if ( ev_add.data.fd >= 0 ) { + fd_info new_info = { 0, static_cast<sockstream_t*>(_ctl.data.ptr), 0 }; + descr[ev_add.data.fd] = new_info; + if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { + descr.erase( ev_add.data.fd ); + // throw system_error + } + } + break; #endif - case tcp_buffer: - ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - ev_add.data.fd = static_cast<sockbuf_t*>(_ctl.data.ptr)->fd(); - if ( ev_add.data.fd >= 0 ) { - fd_info new_info = { fd_info::buffer, static_cast<sockstream_t* /* sockbuf_t* */ >(_ctl.data.ptr), 0 }; - descr[ev_add.data.fd] = new_info; - if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { - descr.erase( ev_add.data.fd ); - // throw system_error - } - } - break; - case rqstop: - // std::cerr << "Stop request\n"; - return; - break; + case tcp_buffer: + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = static_cast<sockbuf_t*>(_ctl.data.ptr)->fd(); + if ( ev_add.data.fd >= 0 ) { + fd_info new_info = { fd_info::buffer, static_cast<sockstream_t* /* sockbuf_t* */ >(_ctl.data.ptr), 0 }; + descr[ev_add.data.fd] = new_info; + if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { + descr.erase( ev_add.data.fd ); + // throw system_error } - - continue; } - // std::cerr << "#\n"; + break; + case rqstop: + // std::cerr << "Stop request\n"; + return; + break; + } +} - typename fd_container_type::iterator ifd = descr.find( ev[i].data.fd ); - if ( ifd == descr.end() ) { - throw std::logic_error( "file descriptor in epoll, but not in descr[]" ); - } +template<class charT, class traits, class _Alloc> +void sockmgr<charT,traits,_Alloc>::process_listener( epoll_event& ev, typename sockmgr<charT,traits,_Alloc>::fd_container_type::iterator ifd ) +{ + if ( ev.events & EPOLLRDHUP ) { + epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ); + // walk through descr and detach every .p ? + descr.erase( ifd ); + std::cerr << "Remove listener EPOLLRDHUP\n"; + } else if ( ev.events & EPOLLIN ) { + sockaddr addr; + socklen_t sz = sizeof( sockaddr_in ); - fd_info& info = ifd->second; - if ( info.flags & fd_info::listener ) { - // std::cerr << "%\n"; - if ( ev[i].events & EPOLLRDHUP ) { - epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ); - // walk through descr and detach every .p ? - descr.erase( ifd ); - std::cerr << "Remove listener EPOLLRDHUP\n"; - } else if ( ev[i].events & EPOLLIN ) { - sockaddr addr; - socklen_t sz = sizeof( sockaddr_in ); + fd_info& info = ifd->second; - for ( ; ; ) { - int fd = accept( ev[i].data.fd, &addr, &sz ); - if ( fd < 0 ) { - std::cerr << "Accept, listener # " << ev[i].data.fd << ", errno " << errno << std::endl; - if ( (errno == EINTR) || (errno == ECONNABORTED) /* || (errno == ERESTARTSYS) */ ) { - continue; - } - if ( !(errno == EAGAIN || errno == EWOULDBLOCK) ) { - // std::cerr << "Accept, listener " << ev[i].data.fd << ", errno " << errno << std::endl; - // throw system_error ? - } + for ( ; ; ) { + int fd = accept( ev.data.fd, &addr, &sz ); + if ( fd < 0 ) { + std::cerr << "Accept, listener # " << ev.data.fd << ", errno " << errno << std::endl; + if ( (errno == EINTR) || (errno == ECONNABORTED) /* || (errno == ERESTARTSYS) */ ) { + continue; + } + if ( !(errno == EAGAIN || errno == EWOULDBLOCK) ) { + // std::cerr << "Accept, listener " << ev[i].data.fd << ", errno " << errno << std::endl; + // throw system_error ? + } #if 0 - { - std::tr2::lock_guard<std::tr2::mutex> lck( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.find( ev[i].data.fd ); - if ( closed_ifd != closed_queue.end() ) { - typename fd_container_type::iterator ifd = descr.begin(); - for ( ; ifd != descr.end(); ) { - if ( ifd->second.p == closed_ifd->second.p ) { - descr.erase( ifd++ ); - } else { - ++ifd - } - } - closed_queue.erase( closed_ifd ); + { + std::tr2::lock_guard<std::tr2::mutex> lck( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.find( ev.data.fd ); + if ( closed_ifd != closed_queue.end() ) { + typename fd_container_type::iterator ifd = descr.begin(); + for ( ; ifd != descr.end(); ) { + if ( ifd->second.p == closed_ifd->second.p ) { + descr.erase( ifd++ ); + } else { + ++ifd; } } + closed_queue.erase( closed_ifd ); + } + } +#endif + break; + } + // std::cerr << "listener accept " << fd << std::endl; + if ( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { + throw std::runtime_error( "can't establish nonblock mode" ); + } + sockstream_t* s; + + try { + s = new sockstream_t(); + if ( s->rdbuf()->_open_sockmgr( fd, addr ) ) { + epoll_event ev_add; + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = fd; + fd_info new_info = { fd_info::owner, s, info.p }; + descr[fd] = new_info; -#endif + if ( epoll_ctl( efd, EPOLL_CTL_ADD, fd, &ev_add ) < 0 ) { + std::cerr << "Accept, add " << fd << ", errno " << errno << std::endl; + descr.erase( fd ); + // throw system_error + } + std::cerr << "adopt_new_t()\n"; + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { break; } - // std::cerr << "listener accept " << fd << std::endl; - if ( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { - throw std::runtime_error( "can't establish nonblock mode" ); - } - sockstream_t* s; + } + if ( closed_ifd == closed_queue.end() ) { + (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); + } else { + std::cerr << "@@@ 1\n" << std::endl; + } + } else { + std::cerr << "Accept, delete " << fd << std::endl; + delete s; + } + } + catch ( const std::bad_alloc& ) { + // nothing + } + catch ( ... ) { + descr.erase( fd ); + delete s; + } + } + } else { + // std::cerr << "listener: " << std::hex << ev.events << std::dec << std::endl; + } +} - try { - s = new sockstream_t(); - if ( s->rdbuf()->_open_sockmgr( fd, addr ) ) { - epoll_event ev_add; - ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - ev_add.data.fd = fd; - fd_info new_info = { fd_info::owner, s, info.p }; - descr[fd] = new_info; +template<class charT, class traits, class _Alloc> +void sockmgr<charT,traits,_Alloc>::process_regular( epoll_event& ev, typename sockmgr<charT,traits,_Alloc>::fd_container_type::iterator ifd ) +{ + fd_info& info = ifd->second; - if ( epoll_ctl( efd, EPOLL_CTL_ADD, fd, &ev_add ) < 0 ) { - std::cerr << "Accept, add " << fd << ", errno " << errno << std::endl; - descr.erase( fd ); - // throw system_error - } - std::cerr << "adopt_new_t()\n"; - std::tr2::lock_guard<std::tr2::mutex> lk( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.begin(); - for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { - if ( closed_ifd->second.p == info.p ) { - break; - } - } - if ( closed_ifd == closed_queue.end() ) { - (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); - } else { - std::cerr << "@@@ 1\n" << std::endl; - } - } else { - std::cerr << "Accept, delete " << fd << std::endl; - delete s; - } - } - catch ( const std::bad_alloc& ) { - // nothing - } - catch ( ... ) { - descr.erase( fd ); - delete s; - } + if ( ev.events & EPOLLIN ) { + if ( (info.flags & fd_info::owner) == 0 ) { + // marginal case: me not owner (registerd via push(), + // when I owner, I know destroy point), + // already closed, but I not see closed event yet; + // object may be deleted already, so I can't + // call b->egptr() etc. here + std::tr2::lock_guard<std::tr2::mutex> lck( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.find( ev.data.fd ); + if ( closed_ifd != closed_queue.end() ) { + closed_queue.erase( closed_ifd ); + if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { + // throw system_error + } + descr.erase( ifd ); + return; + } + } + sockbuf_t* b = (info.flags & fd_info::buffer != 0) ? info.s.b : info.s.s->rdbuf(); + errno = 0; + for ( ; ; ) { + if ( b->_ebuf == b->egptr() ) { + // process extract data from buffer too slow for us! + if ( (info.flags & fd_info::level_triggered) == 0 ) { + epoll_event xev; + xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP; + xev.data.fd = ev.data.fd; + info.flags |= fd_info::level_triggered; + if ( epoll_ctl( efd, EPOLL_CTL_MOD, ev.data.fd, &xev ) < 0 ) { + std::cerr << "X " << ev.data.fd << ", " << errno << std::endl; } - } else { - // std::cerr << "listener: " << std::hex << ev[i].events << std::dec << std::endl; } - } else { - // std::cerr << "not listener\n"; - if ( ev[i].events & EPOLLIN ) { - if ( (info.flags & fd_info::owner) == 0 ) { - // marginal case: me not owner (registerd via push(), - // when I owner, I know destroy point), - // already closed, but I not see closed event yet; - // object may be deleted already, so I can't - // call b->egptr() etc. here - std::tr2::lock_guard<std::tr2::mutex> lck( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.find( ev[i].data.fd ); - if ( closed_ifd != closed_queue.end() ) { - closed_queue.erase( closed_ifd ); - if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { - // throw system_error - } - descr.erase( ifd ); - continue; + std::cerr << "Z " << ev.data.fd << ", " << errno << std::endl; + if ( info.p != 0 ) { + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + break; } } - sockbuf_t* b = (info.flags & fd_info::buffer != 0) ? info.s.b : info.s.s->rdbuf(); + if ( closed_ifd == closed_queue.end() ) { + (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); + } else { + std::cerr << "@@@ 2\n" << std::endl; + } + } + break; + } + std::cerr << "ptr " << (void *)b->egptr() << ", " << errno << std::endl; + long offset = read( ev.data.fd, b->egptr(), sizeof(charT) * (b->_ebuf - b->egptr()) ); + std::cerr << "offset " << offset << ", " << errno << std::endl; + if ( offset < 0 ) { + if ( (errno == EAGAIN) || (errno == EINTR) ) { errno = 0; - for ( ; ; ) { - if ( b->_ebuf == b->egptr() ) { - // process extract data from buffer too slow for us! - if ( (info.flags & fd_info::level_triggered) == 0 ) { - epoll_event xev; - xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP; - xev.data.fd = ev[i].data.fd; - info.flags |= fd_info::level_triggered; - if ( epoll_ctl( efd, EPOLL_CTL_MOD, ev[i].data.fd, &xev ) < 0 ) { - std::cerr << "X " << ev[i].data.fd << ", " << errno << std::endl; - } - } - std::cerr << "Z " << ev[i].data.fd << ", " << errno << std::endl; - if ( info.p != 0 ) { - std::tr2::lock_guard<std::tr2::mutex> lk( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.begin(); - for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { - if ( closed_ifd->second.p == info.p ) { - break; - } - } - if ( closed_ifd == closed_queue.end() ) { - (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); - } else { - std::cerr << "@@@ 2\n" << std::endl; - } - } + epoll_event xev; + xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + xev.data.fd = ev.data.fd; + epoll_ctl( efd, EPOLL_CTL_MOD, ev.data.fd, &xev ); + break; + } else { + switch ( errno ) { + // case EINTR: // read was interrupted + // continue; + // break; + case EFAULT: // Bad address + case ECONNRESET: // Connection reset by peer + ev.events |= EPOLLRDHUP; // will be processed below break; - } - std::cerr << "ptr " << (void *)b->egptr() << ", " << errno << std::endl; - long offset = read( ev[i].data.fd, b->egptr(), sizeof(charT) * (b->_ebuf - b->egptr()) ); - std::cerr << "offset " << offset << ", " << errno << std::endl; - if ( offset < 0 ) { - if ( (errno == EAGAIN) || (errno == EINTR) ) { - errno = 0; - epoll_event xev; - xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - xev.data.fd = ev[i].data.fd; - epoll_ctl( efd, EPOLL_CTL_MOD, ev[i].data.fd, &xev ); - break; - } else { - switch ( errno ) { - // case EINTR: // read was interrupted - // continue; - // break; - case EFAULT: // Bad address - case ECONNRESET: // Connection reset by peer - ev[i].events |= EPOLLRDHUP; // will be processed below - break; - default: - std::cerr << "not listener, other " << ev[i].data.fd << std::hex << ev[i].events << std::dec << " : " << errno << std::endl; - break; - } - break; - } - } else if ( offset > 0 ) { - offset /= sizeof(charT); // if offset % sizeof(charT) != 0, rest will be lost! - - if ( info.flags & fd_info::level_triggered ) { - epoll_event xev; - xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - xev.data.fd = ev[i].data.fd; - info.flags &= ~static_cast<unsigned>(fd_info::level_triggered); - if ( epoll_ctl( efd, EPOLL_CTL_MOD, ev[i].data.fd, &xev ) < 0 ) { - std::cerr << "Y " << ev[i].data.fd << ", " << errno << std::endl; - } - } - std::tr2::lock_guard<std::tr2::mutex> lk( b->ulck ); - b->setg( b->eback(), b->gptr(), b->egptr() + offset ); - b->ucnd.notify_one(); - if ( info.p != 0 ) { - // std::cerr << "data here" << std::endl; - std::tr2::lock_guard<std::tr2::mutex> lk( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.begin(); - for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { - if ( closed_ifd->second.p == info.p ) { - break; - } - } - if ( closed_ifd == closed_queue.end() ) { - (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); - } else { - std::cerr << "@@@ 3\n" << std::endl; - } - } - } else { - std::cerr << "K " << ev[i].data.fd << ", " << errno << std::endl; - // EPOLLRDHUP may be missed in kernel, but offset 0 is the same - ev[i].events |= EPOLLRDHUP; // will be processed below + default: + std::cerr << "not listener, other " << ev.data.fd << std::hex << ev.events << std::dec << " : " << errno << std::endl; break; - } } - } else { - std::cerr << "Q\n"; + break; } - if ( (ev[i].events & EPOLLRDHUP) || (ev[i].events & EPOLLHUP) || (ev[i].events & EPOLLERR) ) { - // std::cerr << "Poll EPOLLRDHUP " << ev[i].data.fd << ", " << errno << std::endl; - if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { - // throw system_error + } else if ( offset > 0 ) { + offset /= sizeof(charT); // if offset % sizeof(charT) != 0, rest will be lost! + + if ( info.flags & fd_info::level_triggered ) { + epoll_event xev; + xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + xev.data.fd = ev.data.fd; + info.flags &= ~static_cast<unsigned>(fd_info::level_triggered); + if ( epoll_ctl( efd, EPOLL_CTL_MOD, ev.data.fd, &xev ) < 0 ) { + std::cerr << "Y " << ev.data.fd << ", " << errno << std::endl; } - if ( info.p != 0 ) { - std::tr2::lock_guard<std::tr2::mutex> lk( cll ); - typename fd_container_type::iterator closed_ifd = closed_queue.begin(); - for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { - if ( closed_ifd->second.p == info.p ) { - break; - } + } + std::tr2::lock_guard<std::tr2::mutex> lk( b->ulck ); + b->setg( b->eback(), b->gptr(), b->egptr() + offset ); + b->ucnd.notify_one(); + if ( info.p != 0 ) { + // std::cerr << "data here" << std::endl; + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + break; } - if ( closed_ifd == closed_queue.end() ) { - (*info.p)( *info.s.s, typename socks_processor_t::adopt_close_t() ); - } else { - std::cerr << "@@@ 4\n" << std::endl; - } } - if ( (info.flags & fd_info::owner) != 0 ) { - delete info.s.s; + if ( closed_ifd == closed_queue.end() ) { + (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); } else { - if ( (info.flags & fd_info::buffer) != 0 ) { - info.s.b->close(); - } else { - info.s.s->close(); - } - std::tr2::lock_guard<std::tr2::mutex> lck( cll ); - closed_queue.erase( ev[i].data.fd ); + std::cerr << "@@@ 3\n" << std::endl; } - descr.erase( ifd ); } - // if ( ev[i].events & EPOLLHUP ) { - // std::cerr << "Poll HUP" << std::endl; - // } - // if ( ev[i].events & EPOLLERR ) { - // std::cerr << "Poll ERR" << std::endl; - // } - if ( ev[i].events & EPOLLPRI ) { - std::cerr << "Poll PRI" << std::endl; + } else { + std::cerr << "K " << ev.data.fd << ", " << errno << std::endl; + // EPOLLRDHUP may be missed in kernel, but offset 0 is the same + ev.events |= EPOLLRDHUP; // will be processed below + break; + } + } + } else { + std::cerr << "Q\n"; + } + + if ( (ev.events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR) ) != 0 ) { + // std::cerr << "Poll EPOLLRDHUP " << ev.data.fd << ", " << errno << std::endl; + if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { + // throw system_error + } + if ( info.p != 0 ) { + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + break; } - if ( ev[i].events & EPOLLRDNORM ) { - std::cerr << "Poll RDNORM" << std::endl; - } - if ( ev[i].events & EPOLLRDBAND ) { - std::cerr << "Poll RDBAND" << std::endl; - } - if ( ev[i].events & EPOLLMSG ) { - std::cerr << "Poll MSG" << std::endl; - } } + if ( closed_ifd == closed_queue.end() ) { + (*info.p)( *info.s.s, typename socks_processor_t::adopt_close_t() ); + } else { + std::cerr << "@@@ 4\n" << std::endl; + } } + if ( (info.flags & fd_info::owner) != 0 ) { + delete info.s.s; + } else { + if ( (info.flags & fd_info::buffer) != 0 ) { + info.s.b->close(); + } else { + info.s.s->close(); + } + std::tr2::lock_guard<std::tr2::mutex> lck( cll ); + closed_queue.erase( ev.data.fd ); + } + descr.erase( ifd ); } + // if ( ev.events & EPOLLHUP ) { + // std::cerr << "Poll HUP" << std::endl; + // } + // if ( ev.events & EPOLLERR ) { + // std::cerr << "Poll ERR" << std::endl; + // } + if ( ev.events & EPOLLPRI ) { + std::cerr << "Poll PRI" << std::endl; } - catch ( std::exception& e ) { - std::cerr << e.what() << std::endl; + if ( ev.events & EPOLLRDNORM ) { + std::cerr << "Poll RDNORM" << std::endl; } + if ( ev.events & EPOLLRDBAND ) { + std::cerr << "Poll RDBAND" << std::endl; + } + if ( ev.events & EPOLLMSG ) { + std::cerr << "Poll MSG" << std::endl; + } } } //detail This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-02 07:23:17
|
Revision: 1840 http://complement.svn.sourceforge.net/complement/?rev=1840&view=rev Author: complement Date: 2008-04-02 00:23:05 -0700 (Wed, 02 Apr 2008) Log Message: ----------- simplify sock_processor_base; partially fix absent of destruction of Connect elements when server died; still under construction Modified Paths: -------------- branches/complement-sockios/explore/include/sockios/sp.h branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc Modified: branches/complement-sockios/explore/include/sockios/sp.h =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.h 2008-04-01 14:44:59 UTC (rev 1839) +++ branches/complement-sockios/explore/include/sockios/sp.h 2008-04-02 07:23:05 UTC (rev 1840) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/04/01 18:40:57 yeti> +// -*- C++ -*- Time-stamp: <08/04/02 10:25:57 ptr> /* * Copyright (c) 2008 @@ -53,34 +53,54 @@ template <class charT, class traits, class _Alloc> class basic_sockstream2; template <class charT, class traits, class _Alloc> class sock_processor_base; -namespace detail { - -template<class charT, class traits, class _Alloc> -class _sock_processor_base : +template <class charT, class traits, class _Alloc> +class sock_processor_base : public sock_base2, public basic_socket<charT,traits,_Alloc> { private: typedef basic_socket<charT,traits,_Alloc> basic_socket_t; - protected: - _sock_processor_base() : + public: + typedef basic_sockstream2<charT,traits,_Alloc> sockstream_t; + + struct adopt_new_t { }; + struct adopt_close_t { }; + struct adopt_data_t { }; + + sock_processor_base() : _mode( ios_base::in | ios_base::out ), _state( ios_base::goodbit ) { } - virtual ~_sock_processor_base() + explicit sock_processor_base( int port, sock_base2::stype t = sock_base2::sock_stream ) + { sock_processor_base::open( port, t, sock_base2::inet ); } + + virtual ~sock_processor_base() + { sock_processor_base::close(); } + + void open( const in_addr& addr, int port, sock_base2::stype type, sock_base2::protocol prot ); + + void open( unsigned long addr, int port, sock_base2::stype type, sock_base2::protocol prot ) { - _sock_processor_base::close(); + in_addr _addr; + _addr.s_addr = htonl( addr ); + sock_processor_base::open( _addr, port, type, prot ); } - public: - void open( const in_addr& addr, int port, sock_base2::stype type, sock_base2::protocol prot ); - void open( unsigned long addr, int port, sock_base2::stype type, sock_base2::protocol prot ); - void open( int port, sock_base2::stype type, sock_base2::protocol prot ); + void open( int port, sock_base2::stype type, sock_base2::protocol prot ) + { sock_processor_base::open(INADDR_ANY, port, type, prot); } virtual void close(); + virtual void operator ()( sockstream_t& s, const adopt_new_t& ) = 0; + virtual void operator ()( sockstream_t& s, const adopt_close_t& ) = 0; + virtual void operator ()( sockstream_t& s, const adopt_data_t& ) = 0; + + private: + sock_processor_base( const sock_processor_base& ); + sock_processor_base& operator =( const sock_processor_base& ); + protected: void setoptions_unsafe( sock_base2::so_t optname, bool on_off = true, int __v = 0 ); @@ -101,20 +121,15 @@ } private: - _sock_processor_base( const _sock_processor_base& ); - _sock_processor_base& operator =( const _sock_processor_base& ); - - private: unsigned long _mode; // open mode unsigned long _state; // state flags protected: std::tr2::mutex _fd_lck; - // xmt::condition _loop_cnd; }; template<class charT, class traits, class _Alloc> -void _sock_processor_base<charT,traits,_Alloc>::open( const in_addr& addr, int port, sock_base2::stype type, sock_base2::protocol prot ) +void sock_processor_base<charT,traits,_Alloc>::open( const in_addr& addr, int port, sock_base2::stype type, sock_base2::protocol prot ) { std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); if ( basic_socket_t::is_open_unsafe() ) { @@ -156,7 +171,7 @@ // I am shure, this is socket of type SOCK_STREAM | SOCK_SEQPACKET, // so don't check return code from listen ::listen( basic_socket_t::_fd, SOMAXCONN ); - basic_socket_t::mgr->push( dynamic_cast<sock_processor_base<charT,traits,_Alloc>&>(*this) ); + basic_socket_t::mgr->push( *this ); } } else if ( prot == sock_base2::local ) { return; @@ -169,27 +184,13 @@ } template<class charT, class traits, class _Alloc> -void _sock_processor_base<charT,traits,_Alloc>::open( unsigned long addr, int port, sock_base2::stype type, sock_base2::protocol prot ) +void sock_processor_base<charT,traits,_Alloc>::close() { - in_addr _addr; - _addr.s_addr = htonl( addr ); - _sock_processor_base::open( _addr, port, type, prot ); -} - -template<class charT, class traits, class _Alloc> -void _sock_processor_base<charT,traits,_Alloc>::open( int port, sock_base2::stype type, sock_base2::protocol prot ) -{ - _sock_processor_base::open(INADDR_ANY, port, type, prot); -} - -template<class charT, class traits, class _Alloc> -void _sock_processor_base<charT,traits,_Alloc>::close() -{ std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); if ( !basic_socket_t::is_open_unsafe() ) { return; } - basic_socket<charT,traits,_Alloc>::mgr->pop( dynamic_cast<sock_processor_base<charT,traits,_Alloc>&>(*this), basic_socket_t::_fd ); + basic_socket<charT,traits,_Alloc>::mgr->pop( *this, basic_socket_t::_fd ); #ifdef WIN32 ::closesocket( basic_socket_t::_fd ); #else @@ -200,7 +201,7 @@ } template<class charT, class traits, class _Alloc> -void _sock_processor_base<charT,traits,_Alloc>::shutdown( sock_base2::shutdownflg dir ) +void sock_processor_base<charT,traits,_Alloc>::shutdown( sock_base2::shutdownflg dir ) { std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); if ( basic_socket_t::is_open_unsafe() ) { @@ -216,7 +217,7 @@ } template<class charT, class traits, class _Alloc> -void _sock_processor_base<charT,traits,_Alloc>::setoptions_unsafe( sock_base2::so_t optname, bool on_off, int __v ) +void sock_processor_base<charT,traits,_Alloc>::setoptions_unsafe( sock_base2::so_t optname, bool on_off, int __v ) { #ifdef __unix if ( basic_socket_t::is_open_unsafe() ) { @@ -242,36 +243,6 @@ #endif // __unix } -} // namespace detail - -template <class charT, class traits, class _Alloc> -class sock_processor_base : - public detail::_sock_processor_base<charT,traits,_Alloc> -{ - private: - typedef detail::_sock_processor_base<charT,traits,_Alloc> sp_base_t; - - public: - typedef basic_sockstream2<charT,traits,_Alloc> sockstream_t; - - struct adopt_new_t { }; - struct adopt_close_t { }; - struct adopt_data_t { }; - - sock_processor_base() - { } - - explicit sock_processor_base( int port, sock_base2::stype t = sock_base2::sock_stream ) - { - sp_base_t::open( port, t, sock_base2::inet ); - } - - - virtual void operator ()( sockstream_t& s, const adopt_new_t& ) = 0; - virtual void operator ()( sockstream_t& s, const adopt_close_t& ) = 0; - virtual void operator ()( sockstream_t& s, const adopt_data_t& ) = 0; -}; - typedef sock_processor_base<char,char_traits<char>,allocator<char> > sock_basic_processor; template <class Connect, class charT = char, class traits = std::char_traits<charT>, class _Alloc = std::allocator<charT>, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& ) = &Connect::connect > @@ -294,6 +265,7 @@ static void __at_fork_prepare(); static void __at_fork_child(); static void __at_fork_parent(); + static std::tr2::mutex _init_lock; static int _count; static bool _at_fork; }; @@ -320,6 +292,18 @@ if ( ploop.joinable() ) { ploop.join(); } + // { + // std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); + for ( typename worker_pool_t::iterator i = worker_pool.begin(); i != worker_pool.end(); ++i ) { + delete i->second; + } + worker_pool.clear(); + // } + for ( typename ready_pool_t::iterator j = ready_pool.begin(); j != ready_pool.end(); ++j ) { + delete j->c; + } + ready_pool.clear(); + ((Init *)Init_buf)->~Init(); } @@ -428,10 +412,11 @@ bool connect_processor<Connect, charT, traits, _Alloc, C>::Init::_at_fork = false; template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +std::tr2::mutex connect_processor<Connect, charT, traits, _Alloc, C>::Init::_init_lock; + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> void connect_processor<Connect, charT, traits, _Alloc, C>::Init::_guard( int direction ) { - static std::tr2::mutex _init_lock; - if ( direction ) { std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); if ( _count++ == 0 ) { @@ -455,22 +440,23 @@ template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_prepare() -{ } +{ _init_lock.lock(); } template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_child() { - std::cerr << "SHOULD NEVER HAPPEN!!!!\n"; + _init_lock.unlock(); if ( _count != 0 ) { - + // std::cerr << "SHOULD NEVER HAPPEN!!!!\n"; + throw std::logic_error( "Fork while connect_processor working may has unexpected behaviour in child process" ); } // _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); } template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_parent() -{ } +{ _init_lock.unlock(); } template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> char connect_processor<Connect, charT, traits, _Alloc, C>::Init_buf[128]; @@ -586,8 +572,9 @@ processor p; while ( pop_ready( p ) ) { - // std::cerr << "worker 1\n"; + std::cerr << "worker 1\n"; (p.c->*C)( *p.s ); + std::cerr << "worker 2\n"; if ( p.s->rdbuf()->in_avail() ) { std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); ready_pool.push_back( p ); @@ -595,6 +582,7 @@ std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); worker_pool[p.s] = p.c; } + std::cerr << "worker 3\n"; } } @@ -875,7 +863,7 @@ epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ); // walk through descr and detach every .p ? descr.erase( ifd ); - // std::cerr << "Remove listener EPOLLRDHUP\n"; + std::cerr << "Remove listener EPOLLRDHUP\n"; } else if ( ev[i].events & EPOLLIN ) { sockaddr addr; socklen_t sz = sizeof( sockaddr_in ); @@ -891,6 +879,24 @@ // std::cerr << "Accept, listener " << ev[i].data.fd << ", errno " << errno << std::endl; // throw system_error ? } +#if 0 + { + std::tr2::lock_guard<std::tr2::mutex> lck( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.find( ev[i].data.fd ); + if ( closed_ifd != closed_queue.end() ) { + typename fd_container_type::iterator ifd = descr.begin(); + for ( ; ifd != descr.end(); ) { + if ( ifd->second.p == closed_ifd->second.p ) { + descr.erase( ifd++ ); + } else { + ++ifd + } + } + closed_queue.erase( closed_ifd ); + } + } + +#endif break; } // std::cerr << "listener accept " << fd << std::endl; @@ -923,6 +929,8 @@ } if ( closed_ifd == closed_queue.end() ) { (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); + } else { + std::cerr << "@@@ 1\n" << std::endl; } } else { std::cerr << "Accept, delete " << fd << std::endl; @@ -985,6 +993,8 @@ } if ( closed_ifd == closed_queue.end() ) { (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); + } else { + std::cerr << "@@@ 2\n" << std::endl; } } break; @@ -1041,6 +1051,8 @@ } if ( closed_ifd == closed_queue.end() ) { (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); + } else { + std::cerr << "@@@ 3\n" << std::endl; } } } else { @@ -1068,6 +1080,8 @@ } if ( closed_ifd == closed_queue.end() ) { (*info.p)( *info.s.s, typename socks_processor_t::adopt_close_t() ); + } else { + std::cerr << "@@@ 4\n" << std::endl; } } if ( (info.flags & fd_info::owner) != 0 ) { Modified: branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc =================================================================== --- branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc 2008-04-01 14:44:59 UTC (rev 1839) +++ branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc 2008-04-02 07:23:05 UTC (rev 1840) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/27 07:22:24 ptr> +// -*- C++ -*- Time-stamp: <08/04/02 01:48:59 ptr> /* * @@ -42,6 +42,9 @@ sock_basic_processor( port, t ) { } + ~simple_mgr() + { cerr << "In destructor\n"; } + protected: virtual void operator ()( sockstream_t& s, const adopt_new_t& ) { lock_guard<mutex> lk(lock); b.wait(); ++n_cnt; } @@ -301,7 +304,7 @@ // } unique_lock<mutex> lk( worker::lock ); - worker::cnd.timed_wait( lk, milliseconds( 100 ), visits_counter2 ); + worker::cnd.timed_wait( lk, milliseconds( 500 ), visits_counter2 ); EXAM_CHECK( worker::visits == 2 ); worker::visits = 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-04-01 14:45:04
|
Revision: 1839 http://complement.svn.sourceforge.net/complement/?rev=1839&view=rev Author: complement Date: 2008-04-01 07:44:59 -0700 (Tue, 01 Apr 2008) Log Message: ----------- under debugging Modified Paths: -------------- branches/complement-sockios/explore/include/sockios/sp.h branches/complement-sockios/explore/lib/sockios/ut/Makefile Modified: branches/complement-sockios/explore/include/sockios/sp.h =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.h 2008-03-28 21:09:36 UTC (rev 1838) +++ branches/complement-sockios/explore/include/sockios/sp.h 2008-04-01 14:44:59 UTC (rev 1839) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/27 17:53:40 yeti> +// -*- C++ -*- Time-stamp: <08/04/01 18:40:57 yeti> /* * Copyright (c) 2008 @@ -189,6 +189,7 @@ if ( !basic_socket_t::is_open_unsafe() ) { return; } + basic_socket<charT,traits,_Alloc>::mgr->pop( dynamic_cast<sock_processor_base<charT,traits,_Alloc>&>(*this), basic_socket_t::_fd ); #ifdef WIN32 ::closesocket( basic_socket_t::_fd ); #else @@ -632,7 +633,8 @@ socks_processor_t *p; }; - struct ctl { + struct ctl + { int cmd; union { int fd; @@ -677,6 +679,7 @@ if ( _worker->joinable() ) { ctl _ctl; _ctl.cmd = rqstop; + _ctl.data.ptr = 0; ::write( pipefd[1], &_ctl, sizeof(ctl) ); @@ -724,6 +727,13 @@ } } + void pop( socks_processor_t& p, int _fd ) + { + fd_info info = { fd_info::listener, 0, &p }; + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + closed_queue[_fd] = info; + } + void exit_notify( sockbuf_t* b, int fd ) { fd_info info = { 0, reinterpret_cast<sockstream_t*>(b), 0 }; @@ -904,7 +914,16 @@ // throw system_error } std::cerr << "adopt_new_t()\n"; - (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + break; + } + } + if ( closed_ifd == closed_queue.end() ) { + (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); + } } else { std::cerr << "Accept, delete " << fd << std::endl; delete s; @@ -957,7 +976,16 @@ } std::cerr << "Z " << ev[i].data.fd << ", " << errno << std::endl; if ( info.p != 0 ) { - (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + break; + } + } + if ( closed_ifd == closed_queue.end() ) { + (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); + } } break; } @@ -1004,7 +1032,16 @@ b->ucnd.notify_one(); if ( info.p != 0 ) { // std::cerr << "data here" << std::endl; - (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + break; + } + } + if ( closed_ifd == closed_queue.end() ) { + (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); + } } } else { std::cerr << "K " << ev[i].data.fd << ", " << errno << std::endl; @@ -1022,7 +1059,16 @@ // throw system_error } if ( info.p != 0 ) { - (*info.p)( *info.s.s, typename socks_processor_t::adopt_close_t() ); + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.begin(); + for ( ; closed_ifd != closed_queue.end(); ++closed_ifd ) { + if ( closed_ifd->second.p == info.p ) { + break; + } + } + if ( closed_ifd == closed_queue.end() ) { + (*info.p)( *info.s.s, typename socks_processor_t::adopt_close_t() ); + } } if ( (info.flags & fd_info::owner) != 0 ) { delete info.s.s; Modified: branches/complement-sockios/explore/lib/sockios/ut/Makefile =================================================================== --- branches/complement-sockios/explore/lib/sockios/ut/Makefile 2008-03-28 21:09:36 UTC (rev 1838) +++ branches/complement-sockios/explore/lib/sockios/ut/Makefile 2008-04-01 14:44:59 UTC (rev 1839) @@ -23,8 +23,6 @@ stldbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBSOCK_DIR}/${OUTPUT_DIR_STLDBG} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR_STLDBG}:${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG}:${LIBSOCK_DIR}/${OUTPUT_DIR_STLDBG}:${STLPORT_LIB_DIR} endif dbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_DBG} -L${LIBEXAM_DIR}/${OUTPUT_DIR_DBG} -L${LIBSOCK_DIR}/${OUTPUT_DIR_DBG} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR_DBG}:${LIBEXAM_DIR}/${OUTPUT_DIR_DBG}:${LIBSOCK_DIR}/${OUTPUT_DIR_DBG}:${STLPORT_LIB_DIR} - -dbg-shared: CXXFLAGS += -fkeep-inline-functions endif release-shared : LDLIBS = -lxmt -lsockios -lexam This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-03-28 21:09:46
|
Revision: 1838 http://complement.svn.sourceforge.net/complement/?rev=1838&view=rev Author: complement Date: 2008-03-28 14:09:36 -0700 (Fri, 28 Mar 2008) Log Message: ----------- debug Modified Paths: -------------- branches/complement-sockios/explore/include/sockios/sockstream2 branches/complement-sockios/explore/include/sockios/sp.h branches/complement-sockios/explore/lib/sockios/ut/Makefile Modified: branches/complement-sockios/explore/include/sockios/sockstream2 =================================================================== --- branches/complement-sockios/explore/include/sockios/sockstream2 2008-03-27 12:19:58 UTC (rev 1837) +++ branches/complement-sockios/explore/include/sockios/sockstream2 2008-03-28 21:09:36 UTC (rev 1838) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/27 08:52:14 ptr> +// -*- C++ -*- Time-stamp: <08/03/27 17:18:22 yeti> /* * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 @@ -315,6 +315,9 @@ } else { std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); if ( --_count == 0 ) { + if ( basic_socket<charT,traits,_Alloc>::mgr == 0 ) { + std::cerr << __FILE__ << ":" << __LINE__ << " shit happens\n"; + } delete basic_socket<charT,traits,_Alloc>::mgr; basic_socket<charT,traits,_Alloc>::mgr = 0; } @@ -331,6 +334,7 @@ { if ( _count != 0 ) { // stop mgr + _count = 1; delete basic_socket<charT,traits,_Alloc>::mgr; basic_socket<charT,traits,_Alloc>::mgr = new detail::sockmgr<charT,traits,_Alloc>(); } Modified: branches/complement-sockios/explore/include/sockios/sp.h =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.h 2008-03-27 12:19:58 UTC (rev 1837) +++ branches/complement-sockios/explore/include/sockios/sp.h 2008-03-28 21:09:36 UTC (rev 1838) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/27 09:28:41 ptr> +// -*- C++ -*- Time-stamp: <08/03/27 17:53:40 yeti> /* * Copyright (c) 2008 @@ -294,6 +294,7 @@ static void __at_fork_child(); static void __at_fork_parent(); static int _count; + static bool _at_fork; }; static char Init_buf[]; @@ -312,7 +313,7 @@ ploop( loop, this ) { new( Init_buf ) Init(); } - ~connect_processor() + virtual ~connect_processor() { connect_processor::close(); if ( ploop.joinable() ) { @@ -338,6 +339,13 @@ void worker(); private: + connect_processor( const connect_processor& ) + { } + + connect_processor& operator =( const connect_processor& ) + { return *this; } + + struct processor { processor() : @@ -401,7 +409,7 @@ worker_pool_t worker_pool; ready_pool_t ready_pool; - volatile bool _in_work; + bool _in_work; std::tr2::mutex wklock; std::tr2::mutex rdlock; std::tr2::condition_variable cnd; @@ -416,6 +424,9 @@ int connect_processor<Connect, charT, traits, _Alloc, C>::Init::_count = 0; template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +bool connect_processor<Connect, charT, traits, _Alloc, C>::Init::_at_fork = false; + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> void connect_processor<Connect, charT, traits, _Alloc, C>::Init::_guard( int direction ) { static std::tr2::mutex _init_lock; @@ -423,10 +434,14 @@ if ( direction ) { std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); if ( _count++ == 0 ) { - -// #ifdef __FIT__PTHREADS -// pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ); -// #endif +#ifdef __FIT_PTHREADS + if ( !_at_fork ) { // call only once + if ( pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ) ) { + // throw system_error + } + _at_fork = true; + } +#endif // _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); } } else { @@ -444,6 +459,8 @@ template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_child() { + std::cerr << "SHOULD NEVER HAPPEN!!!!\n"; + if ( _count != 0 ) { } @@ -633,8 +650,13 @@ efd = epoll_create( hint ); if ( efd < 0 ) { // throw system_error( errno ) + throw std::runtime_error( "epoll_create" ); } - pipe( pipefd ); // check err + if ( pipe( pipefd ) < 0 ) { // check err + ::close( efd ); + // throw system_error; + throw std::runtime_error( "pipe" ); + } // cfd = pipefd[1]; epoll_event ev_add; @@ -656,13 +678,13 @@ ctl _ctl; _ctl.cmd = rqstop; - write( pipefd[1], &_ctl, sizeof(ctl) ); + ::write( pipefd[1], &_ctl, sizeof(ctl) ); _worker->join(); } - close( pipefd[1] ); - close( pipefd[0] ); - close( efd ); + ::close( pipefd[1] ); + ::close( pipefd[0] ); + ::close( efd ); delete _worker; } @@ -672,7 +694,10 @@ _ctl.cmd = listener; _ctl.data.ptr = static_cast<void *>(&p); - write( pipefd[1], &_ctl, sizeof(ctl) ); + int r = ::write( pipefd[1], &_ctl, sizeof(ctl) ); + if ( r < 0 || r != sizeof(ctl) ) { + throw std::runtime_error( "can't write to pipe" ); + } } #if 0 @@ -693,7 +718,10 @@ _ctl.data.ptr = static_cast<void *>(&s); errno = 0; - int r = write( pipefd[1], &_ctl, sizeof(ctl) ); + int r = ::write( pipefd[1], &_ctl, sizeof(ctl) ); + if ( r < 0 || r != sizeof(ctl) ) { + throw std::runtime_error( "can't write to pipe" ); + } } void exit_notify( sockbuf_t* b, int fd ) Modified: branches/complement-sockios/explore/lib/sockios/ut/Makefile =================================================================== --- branches/complement-sockios/explore/lib/sockios/ut/Makefile 2008-03-27 12:19:58 UTC (rev 1837) +++ branches/complement-sockios/explore/lib/sockios/ut/Makefile 2008-03-28 21:09:36 UTC (rev 1838) @@ -23,6 +23,8 @@ stldbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBSOCK_DIR}/${OUTPUT_DIR_STLDBG} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR_STLDBG}:${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG}:${LIBSOCK_DIR}/${OUTPUT_DIR_STLDBG}:${STLPORT_LIB_DIR} endif dbg-shared: LDSEARCH += -L${LIBMT_DIR}/${OUTPUT_DIR_DBG} -L${LIBEXAM_DIR}/${OUTPUT_DIR_DBG} -L${LIBSOCK_DIR}/${OUTPUT_DIR_DBG} -Wl,--rpath=${LIBMT_DIR}/${OUTPUT_DIR_DBG}:${LIBEXAM_DIR}/${OUTPUT_DIR_DBG}:${LIBSOCK_DIR}/${OUTPUT_DIR_DBG}:${STLPORT_LIB_DIR} + +dbg-shared: CXXFLAGS += -fkeep-inline-functions endif release-shared : LDLIBS = -lxmt -lsockios -lexam This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-03-27 12:20:02
|
Revision: 1837 http://complement.svn.sourceforge.net/complement/?rev=1837&view=rev Author: complement Date: 2008-03-27 05:19:58 -0700 (Thu, 27 Mar 2008) Log Message: ----------- read0 test, under debugging Modified Paths: -------------- branches/complement-sockios/explore/include/sockios/sockstream2 branches/complement-sockios/explore/include/sockios/sp.h branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.h branches/complement-sockios/explore/lib/sockios/ut/names.cc branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.h branches/complement-sockios/explore/lib/sockios/ut/sockios_test_suite.cc Modified: branches/complement-sockios/explore/include/sockios/sockstream2 =================================================================== --- branches/complement-sockios/explore/include/sockios/sockstream2 2008-03-26 11:45:54 UTC (rev 1836) +++ branches/complement-sockios/explore/include/sockios/sockstream2 2008-03-27 12:19:58 UTC (rev 1837) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/26 09:54:59 ptr> +// -*- C++ -*- Time-stamp: <08/03/27 08:52:14 ptr> /* * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 @@ -316,6 +316,7 @@ std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); if ( --_count == 0 ) { delete basic_socket<charT,traits,_Alloc>::mgr; + basic_socket<charT,traits,_Alloc>::mgr = 0; } } } @@ -344,7 +345,7 @@ char basic_socket<charT,traits,_Alloc>::Init_buf[128]; template <class charT, class traits, class _Alloc> -detail::sockmgr<charT,traits,_Alloc>* basic_socket<charT,traits,_Alloc>::mgr; +detail::sockmgr<charT,traits,_Alloc>* basic_socket<charT,traits,_Alloc>::mgr = 0; #ifdef STLPORT _STLP_END_NAMESPACE Modified: branches/complement-sockios/explore/include/sockios/sp.h =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.h 2008-03-26 11:45:54 UTC (rev 1836) +++ branches/complement-sockios/explore/include/sockios/sp.h 2008-03-27 12:19:58 UTC (rev 1837) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/26 09:55:19 ptr> +// -*- C++ -*- Time-stamp: <08/03/27 09:28:41 ptr> /* * Copyright (c) 2008 @@ -483,7 +483,7 @@ cnd.notify_one(); } else { std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); - worker_pool[&s] = c; + worker_pool.insert( std::make_pair( &s, c ) ); } } @@ -768,7 +768,7 @@ // throw system_error // std::cerr << "Read pipe\n"; } else if ( r == 0 ) { - // std::cerr << "Read pipe 0\n"; + std::cerr << "Read pipe 0\n"; return; } @@ -845,6 +845,7 @@ for ( ; ; ) { int fd = accept( ev[i].data.fd, &addr, &sz ); if ( fd < 0 ) { + std::cerr << "Accept, listener # " << ev[i].data.fd << ", errno " << errno << std::endl; if ( (errno == EINTR) || (errno == ECONNABORTED) /* || (errno == ERESTARTSYS) */ ) { continue; } @@ -870,13 +871,14 @@ descr[fd] = new_info; if ( epoll_ctl( efd, EPOLL_CTL_ADD, fd, &ev_add ) < 0 ) { - // std::cerr << "Accept, add " << fd << ", errno " << errno << std::endl; + std::cerr << "Accept, add " << fd << ", errno " << errno << std::endl; descr.erase( fd ); // throw system_error } + std::cerr << "adopt_new_t()\n"; (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); } else { - // std::cerr << "Accept, delete " << fd << std::endl; + std::cerr << "Accept, delete " << fd << std::endl; delete s; } } @@ -931,9 +933,11 @@ } break; } + std::cerr << "ptr " << (void *)b->egptr() << ", " << errno << std::endl; long offset = read( ev[i].data.fd, b->egptr(), sizeof(charT) * (b->_ebuf - b->egptr()) ); + std::cerr << "offset " << offset << ", " << errno << std::endl; if ( offset < 0 ) { - if ( errno == EAGAIN ) { + if ( (errno == EAGAIN) || (errno == EINTR) ) { errno = 0; epoll_event xev; xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; @@ -941,8 +945,19 @@ epoll_ctl( efd, EPOLL_CTL_MOD, ev[i].data.fd, &xev ); break; } else { - // process error - std::cerr << "not listener, other " << ev[i].data.fd << std::hex << ev[i].events << std::dec << errno << std::endl; + switch ( errno ) { + // case EINTR: // read was interrupted + // continue; + // break; + case EFAULT: // Bad address + case ECONNRESET: // Connection reset by peer + ev[i].events |= EPOLLRDHUP; // will be processed below + break; + default: + std::cerr << "not listener, other " << ev[i].data.fd << std::hex << ev[i].events << std::dec << " : " << errno << std::endl; + break; + } + break; } } else if ( offset > 0 ) { offset /= sizeof(charT); // if offset % sizeof(charT) != 0, rest will be lost! @@ -964,14 +979,16 @@ (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); } } else { - // std::cerr << "K " << ev[i].data.fd << ", " << errno << std::endl; + std::cerr << "K " << ev[i].data.fd << ", " << errno << std::endl; // EPOLLRDHUP may be missed in kernel, but offset 0 is the same ev[i].events |= EPOLLRDHUP; // will be processed below break; } } + } else { + std::cerr << "Q\n"; } - if ( ev[i].events & EPOLLRDHUP ) { + if ( (ev[i].events & EPOLLRDHUP) || (ev[i].events & EPOLLHUP) || (ev[i].events & EPOLLERR) ) { // std::cerr << "Poll EPOLLRDHUP " << ev[i].data.fd << ", " << errno << std::endl; if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { // throw system_error @@ -992,15 +1009,12 @@ } descr.erase( ifd ); } - if ( ev[i].events & EPOLLHUP ) { - std::cerr << "Poll HUP" << std::endl; - } - if ( ev[i].events & EPOLLERR ) { - std::cerr << "Poll ERR" << std::endl; - } - if ( ev[i].events & EPOLLERR ) { - std::cerr << "Poll ERR" << std::endl; - } + // if ( ev[i].events & EPOLLHUP ) { + // std::cerr << "Poll HUP" << std::endl; + // } + // if ( ev[i].events & EPOLLERR ) { + // std::cerr << "Poll ERR" << std::endl; + // } if ( ev[i].events & EPOLLPRI ) { std::cerr << "Poll PRI" << std::endl; } Modified: branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.h =================================================================== --- branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.h 2008-03-26 11:45:54 UTC (rev 1836) +++ branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.h 2008-03-27 12:19:58 UTC (rev 1837) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 12:12:20 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 23:56:53 ptr> /* * Copyright (c) 2006-2008 Modified: branches/complement-sockios/explore/lib/sockios/ut/names.cc =================================================================== --- branches/complement-sockios/explore/lib/sockios/ut/names.cc 2008-03-26 11:45:54 UTC (rev 1836) +++ branches/complement-sockios/explore/lib/sockios/ut/names.cc 2008-03-27 12:19:58 UTC (rev 1837) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/02/07 10:28:34 ptr> +// -*- C++ -*- Time-stamp: <08/03/27 11:04:23 ptr> /* * @@ -13,13 +13,10 @@ #include <exam/suite.h> -#include <sockios/sockstream> -#include <sockios/sockmgr.h> +#include <sockios/netinfo.h> #include <list> -#include <arpa/inet.h> - using namespace std; /* ************************************************************ */ Modified: branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc =================================================================== --- branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc 2008-03-26 11:45:54 UTC (rev 1836) +++ branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc 2008-03-27 12:19:58 UTC (rev 1837) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/26 11:48:40 ptr> +// -*- C++ -*- Time-stamp: <08/03/27 07:22:24 ptr> /* * @@ -444,3 +444,219 @@ return EXAM_RESULT; } + +class stream_reader +{ + public: + stream_reader( sockstream2& ) + { } + + ~stream_reader() + { } + + void connect( sockstream2& s ) + { + char buf[1024]; + + s.read( buf, 1024 ); + s.write( buf, 1024 ); + s.flush(); + } + + static void load_generator( barrier* b ) + { + sockstream2 s( "localhost", 2008 ); + + char buf[1024]; + + fill( buf, buf + 1024, 0 ); + + b->wait(); + + while( true ) { + s.write( buf, 1024 ); + s.flush(); + + s.read( buf, 1024 ); + this_thread::yield(); + } + } + +}; + +int EXAM_IMPL(sockios2_test::srv_sigpipe) +{ + const char fname[] = "/tmp/sockios2_test.shm"; + try { + xmt::shm_alloc<0> seg; + seg.allocate( fname, 4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + + xmt::allocator_shm<barrier_ip,0> shm; + barrier_ip& b = *new ( shm.allocate( 1 ) ) barrier_ip(); + try { + this_thread::fork(); + + b.wait(); + /* + * This process will be killed, + * so I don't care about safe termination. + */ + + const int b_count = 10; + barrier bb( b_count ); + + thread* th1 = new thread( stream_reader::load_generator, &bb ); + + for ( int i = 0; i < (b_count - 1); ++i ) { + new thread( stream_reader::load_generator, &bb ); + } + + this_thread::sleep( milliseconds( 100 ) ); + + b.wait(); + + th1->join(); // Will be interrupted! + + exit( 0 ); + } + catch ( std::tr2::fork_in_parent& child ) { + connect_processor<stream_reader> r( 2008 ); + + EXAM_CHECK( r.good() ); + EXAM_CHECK( r.is_open() ); + + b.wait(); + b.wait(); + + kill( child.pid(), SIGTERM ); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + // EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + EXAM_ERROR( "child should be interrupted" ); + } else { + EXAM_MESSAGE( "child interrupted" ); + } + + EXAM_CHECK( r.good() ); + EXAM_CHECK( r.is_open() ); + + } + shm.deallocate( &b ); + seg.deallocate(); + unlink( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + + +class interrupted_writer +{ + public: + interrupted_writer( sockstream2& s ) + { + EXAM_CHECK_ASYNC( s.good() ); + + int n = 1; + + cerr << "align 3\n"; + bb->wait(); // <-- align 3 + + cerr << "align 3 pass\n"; + s.write( (const char *)&n, sizeof( int ) ).flush(); + EXAM_CHECK_ASYNC( s.good() ); + } + + ~interrupted_writer() + { cerr << "~~\n"; } + + void connect( sockstream2& s ) + { } + + static void read_generator( barrier* b ) + { + sockstream2 s( "localhost", 2008 ); + + int buff = 0; + cerr << "align 2" << endl; + b->wait(); // <-- align 2 + cerr << "align pass" << endl; + + EXAM_CHECK_ASYNC( s.read( (char *)&buff, sizeof(int) ).good() ); // <---- key line + EXAM_CHECK_ASYNC( buff == 1 ); + } + + static barrier_ip* bb; +}; + +barrier_ip* interrupted_writer::bb = 0; + +int EXAM_IMPL(sockios2_test::read0) +{ + const char fname[] = "/tmp/sockios2_test.shm"; + try { + xmt::shm_alloc<0> seg; + seg.allocate( fname, 4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + + xmt::allocator_shm<barrier_ip,0> shm; + barrier_ip& b = *new ( shm.allocate( 1 ) ) barrier_ip(); + barrier_ip& bnew = *new ( shm.allocate( 1 ) ) barrier_ip(); + interrupted_writer::bb = &bnew; + + try { + this_thread::fork(); + + b.wait(); // <-- align 1 + + barrier bb; + + thread t( interrupted_writer::read_generator, &bb ); + + bb.wait(); // <-- align 2 + + cerr << "system" << endl; + system( "echo > /dev/null" ); // <------ key line + cerr << "after system" << endl; + + bnew.wait(); // <-- align 3 + cerr << "after align 3" << endl; + + t.join(); + + exit( 0 ); + } + catch ( std::tr2::fork_in_parent& child ) { + connect_processor<interrupted_writer> r( 2008 ); + + EXAM_CHECK( r.good() ); + EXAM_CHECK( r.is_open() ); + + b.wait(); // <-- align 1 + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + + EXAM_CHECK( r.good() ); + EXAM_CHECK( r.is_open() ); + } + shm.deallocate( &bnew ); + shm.deallocate( &b ); + seg.deallocate(); + unlink( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} Modified: branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.h =================================================================== --- branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.h 2008-03-26 11:45:54 UTC (rev 1836) +++ branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.h 2008-03-27 12:19:58 UTC (rev 1837) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/25 06:22:29 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 23:57:59 ptr> /* * @@ -25,6 +25,8 @@ int EXAM_DECL(connect_disconnect); int EXAM_DECL(processor_core); int EXAM_DECL(fork); + int EXAM_DECL(srv_sigpipe); + int EXAM_DECL(read0); }; #endif // __sockios2_test_h Modified: branches/complement-sockios/explore/lib/sockios/ut/sockios_test_suite.cc =================================================================== --- branches/complement-sockios/explore/lib/sockios/ut/sockios_test_suite.cc 2008-03-26 11:45:54 UTC (rev 1836) +++ branches/complement-sockios/explore/lib/sockios/ut/sockios_test_suite.cc 2008-03-27 12:19:58 UTC (rev 1837) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/25 07:48:17 ptr> +// -*- C++ -*- Time-stamp: <08/03/27 00:48:22 ptr> /* * @@ -80,10 +80,12 @@ sockios2_test test2; - t.add( &sockios2_test::fork, test2, "sockios2_test::fork", - t.add( &sockios2_test::processor_core, test2, "sockios2_test::processor_core", - t.add( &sockios2_test::connect_disconnect, test2, "sockios2_test::connect_disconnect", - t.add( &sockios2_test::srv_core, test2, "sockios2_test::srv_core" ) ) ) ); + t.add( &sockios2_test::read0, test2, "sockios2_test::read0", + t.add( &sockios2_test::srv_sigpipe, test2, "sockios2_test::srv_sigpipe", + t.add( &sockios2_test::fork, test2, "sockios2_test::fork", + t.add( &sockios2_test::processor_core, test2, "sockios2_test::processor_core", + t.add( &sockios2_test::connect_disconnect, test2, "sockios2_test::connect_disconnect", + t.add( &sockios2_test::srv_core, test2, "sockios2_test::srv_core" ) ) ) ) ) ); return t.girdle(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-03-26 11:45:55
|
Revision: 1836 http://complement.svn.sourceforge.net/complement/?rev=1836&view=rev Author: complement Date: 2008-03-26 04:45:54 -0700 (Wed, 26 Mar 2008) Log Message: ----------- merge -r1833:1834 https://complement.svn.sourceforge.net/svnroot/complement/branches/complement-sockios/explore (fixes and improvements of xmt, C++ 0x) Modified Paths: -------------- trunk/complement/explore/include/mt/condition_variable trunk/complement/explore/include/mt/mutex trunk/complement/explore/include/mt/shm.h trunk/complement/explore/include/mt/thread trunk/complement/explore/lib/janus/ut/Makefile trunk/complement/explore/lib/janus/ut/unit_test.cc trunk/complement/explore/lib/mt/ChangeLog trunk/complement/explore/lib/mt/Makefile.inc trunk/complement/explore/lib/mt/thread.cc trunk/complement/explore/lib/mt/ut/Makefile.inc trunk/complement/explore/lib/mt/ut/mt_test.cc trunk/complement/explore/lib/mt/ut/mt_test.h trunk/complement/explore/lib/mt/ut/mt_test_suite.cc trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc trunk/complement/explore/lib/mt/ut/mt_test_wg21.h Added Paths: ----------- trunk/complement/explore/lib/mt/ut/shm_test.cc trunk/complement/explore/lib/mt/ut/shm_test.h Modified: trunk/complement/explore/include/mt/condition_variable =================================================================== --- trunk/complement/explore/include/mt/condition_variable 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/include/mt/condition_variable 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/06 13:23:11 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:18:13 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -768,7 +768,7 @@ }; typedef __barrier<false> barrier; -typedef __barrier<false> barrier_ip; +typedef __barrier<true> barrier_ip; } // namespace tr2 Modified: trunk/complement/explore/include/mt/mutex =================================================================== --- trunk/complement/explore/include/mt/mutex 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/include/mt/mutex 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/02 14:43:55 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:20:36 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -831,6 +831,7 @@ typedef __mutex<true,true> recursive_mutex_ip; #ifdef __FIT_RWLOCK typedef __rw_mutex<false> rw_mutex; +typedef __rw_mutex<true> rw_mutex_ip; #endif // __FIT_RWLOCK #ifdef __FIT_PTHREAD_SPINLOCK typedef __spinlock<false,false> spinlock; Modified: trunk/complement/explore/include/mt/shm.h =================================================================== --- trunk/complement/explore/include/mt/shm.h 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/include/mt/shm.h 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/08/03 09:47:53 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:37:01 ptr> /* - * Copyright (c) 2006, 2007 + * Copyright (c) 2006-2008 * Petr Ovtchenkov * * Licensed under the Academic Free License version 3.0 @@ -25,6 +25,9 @@ #include <mt/xmt.h> +#include <mt/mutex> +#include <mt/condition_variable> + namespace xmt { struct shm_base @@ -94,12 +97,22 @@ __SPEC_FULL(is_ipc_sharable,float,true); __SPEC_FULL(is_ipc_sharable,double,true); __SPEC_FULL(is_ipc_sharable,long double,true); + __SPEC_FULL(is_ipc_sharable,xmt::__condition<true>,true); __SPEC_FULL(is_ipc_sharable,xmt::__semaphore<true>,true); __SPEC_FULL(is_ipc_sharable,xmt::__barrier<true>,true); __SPEC_FULL(is_ipc_sharable,xmt::shared_mutex,true); __SPEC_FULL(is_ipc_sharable,xmt::shared_recursive_mutex,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::condition_variable_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::condition_variable_any_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::semaphore_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::barrier_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::mutex_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::recursive_mutex_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::rw_mutex_ip,true); + + #undef __SPEC_FULL #undef __SPEC_ @@ -307,7 +320,7 @@ template <class T> void named( const T& obj, int name ) { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); if ( _last == 255 ) { throw std::range_error( "too many named objects" ); } @@ -332,7 +345,7 @@ template <class T> T& named( int name ) { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { ++_nm_table[i].count; @@ -345,7 +358,7 @@ template <class T> const T& named( int name ) const { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { ++_nm_table[i].count; @@ -358,7 +371,7 @@ template <class T> void release( int name ) { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { if ( --_nm_table[i].count == 0 ) { @@ -375,7 +388,7 @@ int count( int name ) const throw() { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { return _nm_table[i].count; @@ -395,7 +408,7 @@ shm_name_mgr& operator =( const shm_name_mgr& ) { return *this; } - xmt::__mutex<false,true> _lock; + std::tr2::mutex_ip _lock; struct _name_rec { int name; @@ -424,7 +437,7 @@ { uint64_t _magic; size_type _first; - xmt::__mutex<false,true> _lock; + std::tr2::mutex_ip _lock; size_type _nm; }; @@ -466,8 +479,9 @@ pointer p = _seg.address(); if ( p != reinterpret_cast<pointer>(-1) && (force || _seg.count() <= 1) ) { + using namespace std::tr2; _master *m = reinterpret_cast<_master *>( _seg.address() ); - (&m->_lock)->~__mutex<false,true>(); + (&m->_lock)->~mutex_ip(); if ( m->_nm != 0 ) { reinterpret_cast<shm_name_mgr<_Inst> *>(reinterpret_cast<char *>(p) + m->_nm)->~shm_name_mgr<_Inst>(); } @@ -484,7 +498,7 @@ if ( p != reinterpret_cast<pointer>(-1) ) { _master *m = reinterpret_cast<_master *>( p ); if ( m->_nm == 0 ) { - xmt::basic_lock<xmt::__mutex<false,true> > lk( m->_lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m->_lock ); void *nm = _traverse( &m->_first, sizeof(shm_name_mgr<_Inst>) ); m->_nm = reinterpret_cast<char *>(nm) - reinterpret_cast<char *>(p); return *new ( nm ) shm_name_mgr<_Inst>(); @@ -500,7 +514,7 @@ { _master *m = reinterpret_cast<_master *>( _seg.address() ); if ( m != reinterpret_cast<_master *>(-1) ) { - xmt::basic_lock<xmt::__mutex<false,true> > lk( m->_lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m->_lock ); return _traverse( &m->_first, n ); } @@ -516,8 +530,8 @@ static void init( _master& m ) { m._magic = MAGIC; - new ( &m._lock ) xmt::__mutex<false,true>(); - xmt::basic_lock<xmt::__mutex<false,true> > lk( m._lock ); + new ( &m._lock ) std::tr2::mutex_ip(); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m._lock ); m._first = sizeof( _master ); m._nm = 0; _fheader& h = *new ( reinterpret_cast<char *>(&m) + sizeof(_master) ) _fheader(); @@ -539,7 +553,7 @@ n = std::max( n + (__align - n % __align) % __align, sizeof(_fheader) ); _master *m = reinterpret_cast<_master *>( _seg.address() ); if ( m != reinterpret_cast<_master *>(-1) && (reinterpret_cast<char *>(p) - reinterpret_cast<char *>(_seg.address())) < (_seg.max_size() + sizeof(_master) + sizeof(_aheader) ) ) { - xmt::basic_lock<xmt::__mutex<false,true> > lk( m->_lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m->_lock ); _aheader *a = reinterpret_cast<_aheader *>( reinterpret_cast<char *>(p) - sizeof(_aheader) ); size_type off = reinterpret_cast<char *>(p) - reinterpret_cast<char *>(_seg.address()); if ( m->_first == 0 ) { Modified: trunk/complement/explore/include/mt/thread =================================================================== --- trunk/complement/explore/include/mt/thread 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/include/mt/thread 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/02 14:44:16 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 01:58:08 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -78,6 +78,8 @@ }; #endif // !_WIN32 +__FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); + class thread_base { public: @@ -135,6 +137,7 @@ friend class thread_base; friend id get_id(void); + // friend __FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); }; enum { @@ -161,6 +164,9 @@ Init(); ~Init(); private: + static void __at_fork_prepare(); + static void __at_fork_parent(); + static void __at_fork_child(); static int& _count; }; @@ -203,6 +209,7 @@ std::string _stack_on_create; #endif friend class Init; + friend __FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); }; template <unsigned F, size_t S> @@ -605,11 +612,18 @@ // trick to declare thread_base::id get_id() as friend in thread_base::id thread_base::id get_id(); +pid_t getpid(); +pid_t getppid(); + namespace this_thread { - // std::thread_base::id get_id(); - using tr2::get_id; +using tr2::fork; +__FIT_DECLSPEC void become_daemon() throw( fork_in_parent, std::runtime_error ); + +// std::thread_base::id get_id(); +using tr2::get_id; + inline void yield() { #ifdef __FIT_PTHREADS Modified: trunk/complement/explore/lib/janus/ut/Makefile =================================================================== --- trunk/complement/explore/lib/janus/ut/Makefile 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/janus/ut/Makefile 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -# -*- Makefile -*- Time-stamp: <07/08/08 22:18:48 ptr> +# -*- Makefile -*- Time-stamp: <08/02/25 19:21:09 ptr> SRCROOT := ../../.. COMPILER_NAME := gcc @@ -20,7 +20,7 @@ ifeq ($(OSNAME),linux) -release-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR} -L$(LIBXMT_DIR)/${OUTPUT_DIR} -L$(LIBSOCKIOS_DIR)/${OUTPUT_DIR} -L$(LIBSTEM_DIR)/${OUTPUT_DIR} -L$(LIBJANUS_DIR)/${OUTPUT_DIR} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR}:$(LIBXMT_DIR)/${OUTPUT_DIR}:${LIBSOCKIOS_DIR}/${OUTPUT_DIR}:${LIBSTEM_DIR}/${OUTPUT_DIR}:${LIBJANUS_DIR}${OUTPUT_DIR}:${STLPORT_LIB_DIR} +release-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR} -L$(LIBXMT_DIR)/${OUTPUT_DIR} -L$(LIBSOCKIOS_DIR)/${OUTPUT_DIR} -L$(LIBSTEM_DIR)/${OUTPUT_DIR} -L$(LIBJANUS_DIR)/${OUTPUT_DIR} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR}:$(LIBXMT_DIR)/${OUTPUT_DIR}:${LIBSOCKIOS_DIR}/${OUTPUT_DIR}:${LIBSTEM_DIR}/${OUTPUT_DIR}:${LIBJANUS_DIR}/${OUTPUT_DIR}:${STLPORT_LIB_DIR} dbg-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR_DBG} -L$(LIBXMT_DIR)/${OUTPUT_DIR_DBG} -L$(LIBSOCKIOS_DIR)/${OUTPUT_DIR_DBG} -L$(LIBSTEM_DIR)/${OUTPUT_DIR_DBG} -L$(LIBJANUS_DIR)/${OUTPUT_DIR_DBG} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR_DBG}:$(LIBXMT_DIR)/${OUTPUT_DIR_DBG}:${LIBSOCKIOS_DIR}/${OUTPUT_DIR_DBG}:${LIBSTEM_DIR}/${OUTPUT_DIR_DBG}:${LIBJANUS_DIR}/${OUTPUT_DIR_DBG}:${STLPORT_LIB_DIR} Modified: trunk/complement/explore/lib/janus/ut/unit_test.cc =================================================================== --- trunk/complement/explore/lib/janus/ut/unit_test.cc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/janus/ut/unit_test.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/08/16 09:04:40 ptr> +// -*- C++ -*- Time-stamp: <08/02/25 22:21:57 ptr> #include "vt_operations.h" @@ -14,6 +14,8 @@ janus::vtime_operations vt_oper; + t.flags( /* exam::base_logger::trace */ exam::base_logger::verbose ); + t.add( &vtime_operations::vt_max, vt_oper, "Max", tc[1] = t.add( &vtime_operations::vt_add, vt_oper, "Additions", tc[0] = t.add( &vtime_operations::vt_compare, vt_oper, "Compare" ) ) ); Modified: trunk/complement/explore/lib/mt/ChangeLog =================================================================== --- trunk/complement/explore/lib/mt/ChangeLog 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ChangeLog 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,3 +1,29 @@ +2008-03-26 Petr Ovtchenkov <pt...@is...> + + * mutex: add rw_mutex_ip typedef; + + * condition_variable: fix wrong typedef for barrier_ip; + + * thread, thread.cc: __at_fork_* handlers moved into Init; + added fork call; on fork down thread's ids to bad id, + except thread that call fork; set __at_fork_* handlers + only once; lock all threads mutexes before fork and + release all ones after---safe fork; + + * shm.h: based on JTC1/SC22/WG21 threads interfaces, but + still in xmt namespace for compatibility; + + * note: implementation of threads interfaces are close + to JTC1/SC22/WG21 C++ 0x working draft, see + http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2521.pdf + + * ut/mt_test.cc, ut/mt_test.h, ut/shm_test.h, ut/shm_test.cc: + move shared memory test suite into separate file; + + * ut/mt_test_wg21.h, ut/mt_test_wg21.cc: test for fork; + + * libxmt: version 2.0.1. + 2008-03-06 Petr Ovtchenkov <pt...@is...> * condition_variable: const casts for pthread_cond_* calls; Modified: trunk/complement/explore/lib/mt/Makefile.inc =================================================================== --- trunk/complement/explore/lib/mt/Makefile.inc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/Makefile.inc 2008-03-26 11:45:54 UTC (rev 1836) @@ -3,7 +3,7 @@ LIBNAME = xmt MAJOR = 2 MINOR = 0 -PATCH = 0 +PATCH = 1 SRC_CC = xmt.cc thr_mgr.cc time.cc uid.cc shm.cc callstack.cc system_error.cc thread.cc \ date_time.cc SRC_C = fl.c Modified: trunk/complement/explore/lib/mt/thread.cc =================================================================== --- trunk/complement/explore/lib/mt/thread.cc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/thread.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/02 14:54:25 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 02:02:03 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -41,17 +41,77 @@ #include <stdio.h> #include <syscall.h> +#ifdef STLPORT +// # include <unordered_map> +# include <unordered_set> +// # include <hash_map> +// # include <hash_set> +// # define __USE_STLPORT_HASH +# define __USE_STLPORT_TR1 +#else +# if defined(__GNUC__) && (__GNUC__ < 4) +// # include <ext/hash_map> +# include <ext/hash_set> +# define __USE_STD_HASH +# else +// # include <tr1/unordered_map> +# include <tr1/unordered_set> +# define __USE_STD_TR1 +# endif +#endif + + #ifdef WIN32 # pragma warning( disable : 4290) // using namespace std; #endif +#if defined(__USE_STLPORT_HASH) || defined(__USE_STLPORT_TR1) || defined(__USE_STD_TR1) +# define __HASH_NAMESPACE std +#endif +#if defined(__USE_STD_HASH) +# define __HASH_NAMESPACE __gnu_cxx +#endif + +namespace __HASH_NAMESPACE { + +#ifdef __USE_STD_TR1 +namespace tr1 { +#endif + +template <> +struct hash<std::tr2::thread_base*> +{ + size_t operator()(const std::tr2::thread_base* __x) const + { return reinterpret_cast<size_t>(__x); } +}; + +#ifdef __USE_STD_TR1 +} +#endif + +} // namespace __HASH_NAMESPACE + + namespace std { namespace tr2 { namespace detail { +#ifdef __USE_STLPORT_HASH +typedef std::hash_set<thread_base*> thread_pool_t; +#endif +#ifdef __USE_STD_HASH +typedef __gnu_cxx::hash_set<thread_base*> thread_pool_t; +#endif +#if defined(__USE_STLPORT_TR1) || defined(__USE_STD_TR1) +typedef std::tr1::unordered_set<thread_base*> thread_pool_t; +#endif + +static mutex thrpool_lock; +static thread_pool_t thread_pool; + int Init_count = 0; // problem: ::getpid() really return cached value, so pid returned may be @@ -141,45 +201,6 @@ return user_words + __idx + 1; } - -void __at_fork_prepare() -{ -#ifdef __FIT_PTHREADS - if ( Init_count > 0 ) { - _uw_save = pthread_getspecific( _mt_key ); - } -#endif -} - -void __at_fork_parent() -{ -} - -void __at_fork_child() -{ -#ifdef __FIT_PTHREADS - if ( Init_count > 0 ) { - // otherwise we do it in Thread::Init::Init() below -# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) - // I am misunderstand this point, Solaris 7 require this (to be restored) - - // pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ); - - // while Linux (and other) inherit this setting from parent process? - // At least Linux glibc 2.2.5 try to made lock in recursive - // call of pthread_atfork -# else -// should be fixed... -# endif // !(__FreeBSD__ || __OpenBSD__) - pthread_key_create( &_mt_key, 0 ); // take new key - pthread_setspecific( _mt_key, _uw_save ); // store preserved user words array - _uw_save = 0; - // Note, that only calling thread inherited when we use POSIX: - Init_count = 1; // i.e. only ONE (calling) thread... - } -#endif -} - } // namespace detail } // namespace tr2 } // namespace std @@ -196,6 +217,7 @@ char *Init_buf[32]; int& thread_base::Init::_count( detail::Init_count ); // trick to avoid friend declarations +bool _at_fork_set = false; const std::string msg1( "Can't create thread" ); const std::string msg2( "Can't fork" ); @@ -213,8 +235,11 @@ if ( _count++ == 0 ) { #ifdef __FIT_PTHREADS # if !(defined(__FreeBSD__) || defined(__OpenBSD__)) - if ( pthread_atfork( detail::__at_fork_prepare, detail::__at_fork_parent, detail::__at_fork_child ) ) { - throw std::runtime_error( "Problems with pthread_atfork" ); + if ( !_at_fork_set ) { // call only once + if ( pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ) ) { + throw std::runtime_error( "Problems with pthread_atfork" ); + } + _at_fork_set = true; } # endif // !(__FreeBSD__ || __OpenBSD__) pthread_key_create( &detail::_mt_key, 0 ); @@ -253,6 +278,73 @@ # endif // !(__FreeBSD__ || __OpenBSD__) #endif // __FIT_UITHREADS || _PTHREADS +void thread_base::Init::__at_fork_prepare() +{ +#ifdef __FIT_PTHREADS + detail::_F_lock.lock(); + detail::thrpool_lock.lock(); + + if ( detail::Init_count > 0 ) { + detail::_uw_save = pthread_getspecific( detail::_mt_key ); + } + + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id != _bad_thread_id ) { + const_cast<thread_base*>(*i)->_id_lock.lock(); + } + } + +#endif +} + +void thread_base::Init::__at_fork_parent() +{ +#ifdef __FIT_PTHREADS + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id != _bad_thread_id ) { + const_cast<thread_base*>(*i)->_id_lock.unlock(); + } + } + + detail::thrpool_lock.unlock(); + detail::_F_lock.unlock(); +#endif +} + +void thread_base::Init::__at_fork_child() +{ +#ifdef __FIT_PTHREADS + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id != _bad_thread_id ) { + const_cast<thread_base*>(*i)->_id_lock.unlock(); + } + } + + detail::thrpool_lock.unlock(); + + if ( detail::Init_count > 0 ) { + // otherwise we do it in Thread::Init::Init() below +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + // I am misunderstand this point, Solaris 7 require this (to be restored) + + // pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ); + + // while Linux (and other) inherit this setting from parent process? + // At least Linux glibc 2.2.5 try to made lock in recursive + // call of pthread_atfork +# else +// should be fixed... +# endif // !(__FreeBSD__ || __OpenBSD__) + pthread_key_create( &detail::_mt_key, 0 ); // take new key + pthread_setspecific( detail::_mt_key, detail::_uw_save ); // store preserved user words array + detail::_uw_save = 0; + // Note, that only calling thread inherited when we use POSIX: + detail::Init_count = 1; // i.e. only ONE (calling) thread... + } + detail::_F_lock.unlock(); +#endif +} + thread_base::id::id() : _id( _bad_thread_id ) { } @@ -262,6 +354,9 @@ _id( _bad_thread_id ) { new( Init_buf ) Init(); + + lock_guard<mutex> lk( detail::thrpool_lock ); + detail::thread_pool.insert( this ); } __FIT_DECLSPEC @@ -269,6 +364,9 @@ { if ( joinable() ) { thread_base::join(); + } else { + lock_guard<mutex> lk( detail::thrpool_lock ); + detail::thread_pool.erase( this ); } ((Init *)Init_buf)->~Init(); @@ -294,6 +392,12 @@ #endif // __FIT_WIN32THREADS #ifdef __FIT_PTHREADS pthread_join( _id, 0 ); + + { + lock_guard<mutex> lk(detail::thrpool_lock); + detail::thread_pool.erase( this ); + } + _id = _bad_thread_id; // lock not required here, only one thread #endif // PTHREADS } @@ -306,14 +410,44 @@ if ( pthread_detach( _id ) ) { // throw system_error; } + { + lock_guard<mutex> lk(detail::thrpool_lock); + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id == _id ) { + detail::thread_pool.erase( i ); + break; + } + } + } _id = _bad_thread_id; #endif } +pid_t getpid() +{ + return detail::_pid; +} + +pid_t getppid() +{ + return detail::_ppid; +} + +thread_base::id get_id() +{ +#ifdef __FIT_PTHREADS + return thread_base::id( pthread_self() ); +#endif +#ifdef __FIT_WIN32THREADS + return thread_base::id( GetCurrentThread() ); +#endif +} + +__FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ) { #ifdef __unix - // MT_REENTRANT( detail::_F_lock, _1 ); + thread_base::id fthr = this_thread::get_id(); fork_in_parent f( ::fork() ); if ( f.pid() > 0 ) { throw f; @@ -323,15 +457,29 @@ } detail::_ppid = detail::_pid; detail::_pid = syscall( SYS_getpid ); + + // lock not required: it in child and only one thread yet + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ) { + if ( (*i)->get_id() != fthr ) { + const_cast<thread_base*>(*i)->_id = _bad_thread_id; + detail::thread_pool.erase( i++ ); + } else { + ++i; + } + } + #endif } +namespace this_thread +{ + __FIT_DECLSPEC void become_daemon() throw( fork_in_parent, std::runtime_error ) { #ifdef __unix try { - std::tr2::fork(); + std::tr2::this_thread::fork(); ::chdir( "/var/tmp" ); // for CWD: if not done, process remain with same WD // and don't allow unmount volume, for example @@ -353,29 +501,6 @@ #endif } -pid_t getpid() -{ - return detail::_pid; -} - -pid_t getppid() -{ - return detail::_ppid; -} - -thread_base::id get_id() -{ -#ifdef __FIT_PTHREADS - return thread_base::id( pthread_self() ); -#endif -#ifdef __FIT_WIN32THREADS - return thread_base::id( GetCurrentThread() ); -#endif -} - -namespace this_thread -{ - #if 0 std::thread_base::id get_id() { Modified: trunk/complement/explore/lib/mt/ut/Makefile.inc =================================================================== --- trunk/complement/explore/lib/mt/ut/Makefile.inc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/Makefile.inc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,7 +1,7 @@ -# -*- makefile -*- Time-stamp: <08/02/15 22:36:40 ptr> +# -*- makefile -*- Time-stamp: <08/03/26 10:12:36 ptr> PRGNAME = mt_ut SRC_CC = unit_test.cc timespec.cc \ signal-1.cc signal-3.cc \ - mt_test.cc mt_test_suite.cc \ + mt_test.cc shm_test.cc mt_test_suite.cc \ mt_test_wg21.cc Modified: trunk/complement/explore/lib/mt/ut/mt_test.cc =================================================================== --- trunk/complement/explore/lib/mt/ut/mt_test.cc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/mt_test.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/09/14 22:10:35 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:09:40 ptr> /* * Copyright (c) 2006, 2007 @@ -516,454 +516,7 @@ return EXAM_RESULT; } -/* ****************************************************** */ - -int EXAM_IMPL(shm_test::shm_segment) -{ - const char fname[] = "/tmp/mt_test.shm"; - try { - xmt::detail::__shm_alloc<0> seg( 5000, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - - EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); - seg.deallocate(); - EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); - - EXAM_REQUIRE( !fs::exists( fname ) ); - - seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); - seg.deallocate(); - EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); - EXAM_CHECK( fs::exists( fname ) ); // well, now I don't remove ref file, because shm segment may be created with another way - - // not exclusive, should pass - seg.allocate( fname, 1024, xmt::shm_base::create, 0660 ); - EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); - try { - // This instance has segment in usage, should throw - seg.allocate( fname, 1024, 0, 0660 ); - EXAM_CHECK( false ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_CHECK( true ); // Ok - } - - /* - - I will treat another instanse (<1>) as interface to another - segment, so this sample not work. - - try { - // But this is another instanse, it's ok: - xmt::detail::__shm_alloc<1> seg1( fname, 1024, 0, 0660 ); - BOOST_CHECK( seg1.address() != reinterpret_cast<void *>(-1) ); - // Don't call seg1.deallocate() here, it destroy - } - catch ( xmt::shm_bad_alloc& err ) { - BOOST_CHECK( false ); // Fail - } - */ - - seg.deallocate(); - EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); - - // ---- - try { - // exclusive, should throw - seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - EXAM_CHECK( false ); // Fail, should throw - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_CHECK( true ); // Ok - } - EXAM_CHECK( fs::exists( fname ) ); - // ---- - - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** */ - -int EXAM_IMPL(shm_test::shm_alloc) -{ - const char fname[] = "/tmp/mt_test.shm"; - try { - xmt::shm_alloc<0> seg; - - seg.allocate( fname, 7000, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - - { - xmt::allocator_shm<char,0> shmall; - size_t sz = shmall.max_size(); - // two blocks - char *ch1 = shmall.allocate( 3500 ); - EXAM_CHECK( ch1 != 0 ); - char *ch2 = shmall.allocate( 3500 ); - EXAM_CHECK( ch2 != 0 ); - try { - // try to allocate third block, not enough room - char *ch3 = shmall.allocate( 8 * 1024 - 7000 ); - EXAM_CHECK( false ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_CHECK( true ); - } - // free first blocks - shmall.deallocate( ch1, 3500 ); - ch1 = shmall.allocate( 3500 ); - // allocate [first] block again - EXAM_CHECK( ch1 != 0 ); - // free second block - shmall.deallocate( ch2, 3500 ); - // allocate [second] block again - ch2 = shmall.allocate( 3500 ); - EXAM_CHECK( ch2 != 0 ); - // free both blocks - shmall.deallocate( ch1, 3500 ); - shmall.deallocate( ch2, 3500 ); - // allocate big block, enough for initial memory chunk - ch1 = shmall.allocate( 7000 ); - EXAM_CHECK( ch1 != 0 ); - // free it - shmall.deallocate( ch1, 7000 ); - // allocate block of maximum size - ch1 = shmall.allocate( sz ); - EXAM_CHECK( ch1 != 0 ); - // free it - shmall.deallocate( ch1, sz ); - // allocate block, enough for initial memory chunk - ch1 = shmall.allocate( 7000 ); - EXAM_CHECK( ch1 != 0 ); - // free it - shmall.deallocate( ch1, 7000 ); - ch1 = shmall.allocate( 3000 ); - EXAM_CHECK( ch1 != 0 ); - ch2 = shmall.allocate( 400 ); - EXAM_CHECK( ch2 != 0 ); - char *ch3 = shmall.allocate( 3500 ); - EXAM_CHECK( ch3 != 0 ); - shmall.deallocate( ch1, 3000 ); - shmall.deallocate( ch2, 400 ); - shmall.deallocate( ch3, 3500 ); - ch1 = shmall.allocate( sz ); - EXAM_CHECK( ch1 != 0 ); - shmall.deallocate( ch1, sz ); - } - seg.deallocate(); - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - - /* ****************************************************** - * This test is similar mt_test::fork() above, but instead plain shm_* - * functions it use allocator based on shared memory segment - */ -int EXAM_IMPL(shm_test::fork_shm) -{ - const char fname[] = "/tmp/mt_test.shm"; - try { - xmt::shm_alloc<0> seg; - - seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - xmt::allocator_shm<char,0> shm; - - xmt::__condition<true>& fcnd = *new( shm.allocate( sizeof(xmt::__condition<true>) ) ) xmt::__condition<true>(); - fcnd.set( false ); - try { - xmt::fork(); - - try { - - // Child code - fcnd.try_wait(); - - } - catch ( ... ) { - } - - exit( 0 ); - } - catch ( xmt::fork_in_parent& child ) { - try { - EXAM_CHECK( child.pid() > 0 ); - - fcnd.set( true ); - - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - catch ( ... ) { - } - } - catch ( ... ) { - } - - (&fcnd)->~__condition<true>(); - shm.deallocate( reinterpret_cast<char *>(&fcnd), sizeof(xmt::__condition<true>) ); - seg.deallocate(); - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** - * Test: how to take named object in shared memory segment - */ -int EXAM_IMPL(shm_test::shm_named_obj) -{ - const char fname[] = "/tmp/mt_test.shm"; - enum { - test_Condition_Object = 1 - }; - try { - xmt::shm_alloc<0> seg; - - seg.allocate( fname, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - xmt::shm_name_mgr<0>& nm = seg.name_mgr(); - - xmt::allocator_shm<xmt::__condition<true>,0> shm; - - xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); - nm.named( fcnd, test_Condition_Object ); - fcnd.set( false ); - - try { - xmt::fork(); - - int eflag = 0; - - try { - - // Child code - xmt::shm_alloc<0> seg_ch; - - if ( seg_ch.max_size() == 0 ) { // just illustration, if seg and seg_ch - // (really xmt::shm_alloc<0>) - // in totally different address spaces - // in our case xmt::shm_name_mgr<0> instance derived from parent - // process - seg.allocate( fname, 4*4096, 0, 0660 ); - } - - xmt::shm_name_mgr<0>& nm_ch = seg_ch.name_mgr(); - xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( test_Condition_Object ); - fcnd_ch.set( true ); - } - catch ( const xmt::shm_bad_alloc& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - catch ( ... ) { - EXAM_ERROR_ASYNC_F( "Fail in child", eflag ); - } - - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - try { - EXAM_CHECK( child.pid() > 0 ); - - fcnd.try_wait(); - - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - catch ( ... ) { - EXAM_ERROR( "Fail in parent" ); - } - } - catch ( ... ) { - EXAM_ERROR( "Fail in fork" ); - } - - (&fcnd)->~__condition<true>(); - shm.deallocate( &fcnd, 1 ); - seg.deallocate(); - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** - */ -const char shm_test::fname1[] = "/tmp/mt_test.shm.1"; - -shm_test::shm_test() -{ - try { - seg1.allocate( fname1, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR_ASYNC( err.what() ); - } -} - -/* ****************************************************** - */ -shm_test::~shm_test() -{ - seg1.deallocate(); - fs::remove( fname1 ); -} - -/* ****************************************************** - */ - -int EXAM_IMPL(shm_test::shm_named_obj_more) -{ - enum { - ObjName = 1 - }; - - try { - xmt::shm_name_mgr<1>& nm = seg1.name_mgr(); - - xmt::allocator_shm<xmt::__condition<true>,1> shm; - - xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); - nm.named( fcnd, ObjName ); - fcnd.set( false ); - - try { - xmt::fork(); - - int eflag = 0; - - try { - xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); - xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; - xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); - fcnd_ch.set( true ); - nm_ch.release<xmt::__condition<true> >( ObjName ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - fcnd.try_wait(); - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here - - xmt::__condition<true>& fcnd1 = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); - nm.named( fcnd1, ObjName ); // ObjName should be free here - fcnd1.set( false ); - - try { - xmt::fork(); - - int eflag = 0; - - try { - xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); - xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; - xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); - fcnd_ch.set( true ); - nm_ch.release<xmt::__condition<true> >( ObjName ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - fcnd1.try_wait(); - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here - - xmt::allocator_shm<xmt::__barrier<true>,1> shm_b; - xmt::__barrier<true>& b = *new ( shm_b.allocate( 1 ) ) xmt::__barrier<true>(); - - nm.named( b, ObjName ); // ObjName should be free here - - try { - xmt::fork(); - - int eflag = 0; - try { - xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); - xmt::allocator_shm<xmt::__barrier<true>,1> shm_ch; - xmt::__barrier<true>& b_ch = nm_ch.named<xmt::__barrier<true> >( ObjName ); - b_ch.wait(); - nm_ch.release<xmt::__barrier<true> >( ObjName ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - b.wait(); - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - nm.release<xmt::__barrier<true> >( ObjName ); // barrier should be destroyed here - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** * Thread pool (aka ThreadMgr) test. * * Start 200 threads under ThreadMgr; check that all threads Modified: trunk/complement/explore/lib/mt/ut/mt_test.h =================================================================== --- trunk/complement/explore/lib/mt/ut/mt_test.h 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/mt_test.h 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/05 00:02:19 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:08:36 ptr> /* - * Copyright (c) 2006, 2007 + * Copyright (c) 2006-2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -37,22 +37,4 @@ // static int x; }; -class shm_test -{ - public: - shm_test(); - ~shm_test(); - - int EXAM_DECL(shm_segment); - int EXAM_DECL(shm_alloc); - int EXAM_DECL(fork_shm); - int EXAM_DECL(shm_named_obj); - - int EXAM_DECL(shm_named_obj_more); - - private: - xmt::shm_alloc<1> seg1; - static const char fname1[]; -}; - #endif // __MT_TEST_H Modified: trunk/complement/explore/lib/mt/ut/mt_test_suite.cc =================================================================== --- trunk/complement/explore/lib/mt/ut/mt_test_suite.cc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/mt_test_suite.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 12:17:54 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:12:21 ptr> /* * Copyright (c) 2006-2008 @@ -10,6 +10,7 @@ #include "mt_test_suite.h" #include "mt_test.h" +#include "shm_test.h" #include "mt_test_wg21.h" #include <config/feature.h> @@ -41,7 +42,6 @@ exam::test_suite::test_case_type tc[3]; // t.add( &mt_test::callstack, test, "callstack" ); - tc[0] = t.add( &mt_test::barrier, test, "mt_test::barrier" ); tc[1] = t.add( &mt_test::join_test, test, "mt_test::join_test" ); tc[2] = t.add( &mt_test::yield, test, "mt_test::yield", @@ -74,6 +74,7 @@ t.add( &mt_test_wg21::mutex_test, test_wg21, "mt_test_wg21::mutex_test" ); t.add( &mt_test_wg21::barrier, test_wg21, "mt_test_wg21::barrier" ); t.add( &mt_test_wg21::semaphore, test_wg21, "mt_test_wg21::semaphore" ); + t.add( &mt_test_wg21::fork, test_wg21, "mt_test_wg21::fork" ); return t.girdle(); }; Modified: trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc =================================================================== --- trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 13:01:59 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 01:53:46 ptr> /* * Copyright (c) 2006-2008 @@ -19,6 +19,10 @@ #include <iostream> +#include <sys/wait.h> +#include <sys/ipc.h> +#include <sys/shm.h> + int EXAM_IMPL(mt_test_wg21::date_time) { // using namespace std::tr2; @@ -202,3 +206,111 @@ return EXAM_RESULT; } + +int EXAM_IMPL(mt_test_wg21::fork) +{ + // trivial fork + + int v = 3; + try { + std::tr2::this_thread::fork(); + + try { + + // Child code + EXAM_CHECK_ASYNC( v == 3 ); + + v = 5; + } + catch ( ... ) { + } + + exit( 0 ); + } + catch ( std::tr2::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + EXAM_CHECK( v == 3 ); + } + catch ( ... ) { + } + } + catch ( ... ) { + } + + + // less trivial fork: check interprocess communication via shared memory + + shmid_ds ds; + int id = shmget( 5000, 1024, IPC_CREAT | IPC_EXCL | 0600 ); + EXAM_REQUIRE( id != -1 ); + // if ( id == -1 ) { + // cerr << "Error on shmget" << endl; + // } + EXAM_REQUIRE( shmctl( id, IPC_STAT, &ds ) != -1 ); + // if ( shmctl( id, IPC_STAT, &ds ) == -1 ) { + // cerr << "Error on shmctl" << endl; + // } + void *buf = shmat( id, 0, 0 ); + EXAM_REQUIRE( buf != reinterpret_cast<void *>(-1) ); + // if ( buf == reinterpret_cast<void *>(-1) ) { + // cerr << "Error on shmat" << endl; + // } + + int& x = *new( buf ) int(4); + + EXAM_CHECK( x == 4 ); + + try { + std::tr2::this_thread::fork(); + + try { + + // Child code + EXAM_CHECK_ASYNC( v == 3 ); + + v = 5; + + EXAM_CHECK_ASYNC( x == 4 ); + + x = 6; + } + catch ( ... ) { + } + + exit( 0 ); + } + catch ( std::tr2::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + EXAM_CHECK( v == 3 ); + EXAM_CHECK( x == 6 ); + } + catch ( ... ) { + } + } + catch ( ... ) { + } + + shmdt( buf ); + shmctl( id, IPC_RMID, &ds ); + + return EXAM_RESULT; +} + Modified: trunk/complement/explore/lib/mt/ut/mt_test_wg21.h =================================================================== --- trunk/complement/explore/lib/mt/ut/mt_test_wg21.h 2008-03-26 11:10:43 UTC (rev 1835) +++ trunk/complement/explore/lib/mt/ut/mt_test_wg21.h 2008-03-26 11:45:54 UTC (rev 1836) @@ -24,6 +24,7 @@ int EXAM_DECL(mutex_test); int EXAM_DECL(barrier); int EXAM_DECL(semaphore); + int EXAM_DECL(fork); private: // static xmt::Thread::ret_t thread_entry_call( void * ); Copied: trunk/complement/explore/lib/mt/ut/shm_test.cc (from rev 1834, branches/complement-sockios/explore/lib/mt/ut/shm_test.cc) =================================================================== --- trunk/complement/explore/lib/mt/ut/shm_test.cc (rev 0) +++ trunk/complement/explore/lib/mt/ut/shm_test.cc 2008-03-26 11:45:54 UTC (rev 1836) @@ -0,0 +1,474 @@ +// -*- C++ -*- Time-stamp: <08/03/26 10:11:58 ptr> + +/* + * Copyright (c) 2006, 2007 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License Version 3.0 + * + */ + +#include "shm_test.h" + +#include <mt/xmt.h> +#include <mt/shm.h> + + +#include <sys/shm.h> +#include <sys/wait.h> + +#include <signal.h> + +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> + +#include <iostream> + +using namespace std; +namespace fs = boost::filesystem; + +int EXAM_IMPL(shm_test::shm_segment) +{ + const char fname[] = "/tmp/mt_test.shm"; + try { + xmt::detail::__shm_alloc<0> seg( 5000, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + + EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); + seg.deallocate(); + EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); + + EXAM_REQUIRE( !fs::exists( fname ) ); + + seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); + seg.deallocate(); + EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); + EXAM_CHECK( fs::exists( fname ) ); // well, now I don't remove ref file, because shm segment may be created with another way + + // not exclusive, should pass + seg.allocate( fname, 1024, xmt::shm_base::create, 0660 ); + EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); + try { + // This instance has segment in usage, should throw + seg.allocate( fname, 1024, 0, 0660 ); + EXAM_CHECK( false ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_CHECK( true ); // Ok + } + + /* + + I will treat another instanse (<1>) as interface to another + segment, so this sample not work. + + try { + // But this is another instanse, it's ok: + xmt::detail::__shm_alloc<1> seg1( fname, 1024, 0, 0660 ); + BOOST_CHECK( seg1.address() != reinterpret_cast<void *>(-1) ); + // Don't call seg1.deallocate() here, it destroy + } + catch ( xmt::shm_bad_alloc& err ) { + BOOST_CHECK( false ); // Fail + } + */ + + seg.deallocate(); + EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); + + // ---- + try { + // exclusive, should throw + seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + EXAM_CHECK( false ); // Fail, should throw + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_CHECK( true ); // Ok + } + EXAM_CHECK( fs::exists( fname ) ); + // ---- + + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + +/* ****************************************************** */ + +int EXAM_IMPL(shm_test::shm_alloc) +{ + const char fname[] = "/tmp/mt_test.shm"; + try { + xmt::shm_alloc<0> seg; + + seg.allocate( fname, 7000, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + + { + xmt::allocator_shm<char,0> shmall; + size_t sz = shmall.max_size(); + // two blocks + char *ch1 = shmall.allocate( 3500 ); + EXAM_CHECK( ch1 != 0 ); + char *ch2 = shmall.allocate( 3500 ); + EXAM_CHECK( ch2 != 0 ); + try { + // try to allocate third block, not enough room + char *ch3 = shmall.allocate( 8 * 1024 - 7000 ); + EXAM_CHECK( false ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_CHECK( true ); + } + // free first blocks + shmall.deallocate( ch1, 3500 ); + ch1 = shmall.allocate( 3500 ); + // allocate [first] block again + EXAM_CHECK( ch1 != 0 ); + // free second block + shmall.deallocate( ch2, 3500 ); + // allocate [second] block again + ch2 = shmall.allocate( 3500 ); + EXAM_CHECK( ch2 != 0 ); + // free both blocks + shmall.deallocate( ch1, 3500 ); + shmall.deallocate( ch2, 3500 ); + // allocate big block, enough for initial memory chunk + ch1 = shmall.allocate( 7000 ); + EXAM_CHECK( ch1 != 0 ); + // free it + shmall.deallocate( ch1, 7000 ); + // allocate block of maximum size + ch1 = shmall.allocate( sz ); + EXAM_CHECK( ch1 != 0 ); + // free it + shmall.deallocate( ch1, sz ); + // allocate block, enough for initial memory chunk + ch1 = shmall.allocate( 7000 ); + EXAM_CHECK( ch1 != 0 ); + // free it + shmall.deallocate( ch1, 7000 ); + ch1 = shmall.allocate( 3000 ); + EXAM_CHECK( ch1 != 0 ); + ch2 = shmall.allocate( 400 ); + EXAM_CHECK( ch2 != 0 ); + char *ch3 = shmall.allocate( 3500 ); + EXAM_CHECK( ch3 != 0 ); + shmall.deallocate( ch1, 3000 ); + shmall.deallocate( ch2, 400 ); + shmall.deallocate( ch3, 3500 ); + ch1 = shmall.allocate( sz ); + EXAM_CHECK( ch1 != 0 ); + shmall.deallocate( ch1, sz ); + } + seg.deallocate(); + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + + +/* ****************************************************** + * This test is similar mt_test::fork() above, but instead plain shm_* + * functions it use allocator based on shared memory segment + */ +int EXAM_IMPL(shm_test::fork_shm) +{ + const char fname[] = "/tmp/mt_test.shm"; + try { + xmt::shm_alloc<0> seg; + + seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + xmt::allocator_shm<char,0> shm; + + xmt::__condition<true>& fcnd = *new( shm.allocate( sizeof(xmt::__condition<true>) ) ) xmt::__condition<true>(); + fcnd.set( false ); + try { + xmt::fork(); + + try { + + // Child code + fcnd.try_wait(); + + } + catch ( ... ) { + } + + exit( 0 ); + } + catch ( xmt::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + fcnd.set( true ); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + catch ( ... ) { + } + } + catch ( ... ) { + } + + (&fcnd)->~__condition<true>(); + shm.deallocate( reinterpret_cast<char *>(&fcnd), sizeof(xmt::__condition<true>) ); + seg.deallocate(); + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + +/* ****************************************************** + * Test: how to take named object in shared memory segment + */ +int EXAM_IMPL(shm_test::shm_named_obj) +{ + const char fname[] = "/tmp/mt_test.shm"; + enum { + test_Condition_Object = 1 + }; + try { + xmt::shm_alloc<0> seg; + + seg.allocate( fname, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + xmt::shm_name_mgr<0>& nm = seg.name_mgr(); + + xmt::allocator_shm<xmt::__condition<true>,0> shm; + + xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); + nm.named( fcnd, test_Condition_Object ); + fcnd.set( false ); + + try { + xmt::fork(); + + int eflag = 0; + + try { + + // Child code + xmt::shm_alloc<0> seg_ch; + + if ( seg_ch.max_size() == 0 ) { // just illustration, if seg and seg_ch + // (really xmt::shm_alloc<0>) + // in totally different address spaces + // in our case xmt::shm_name_mgr<0> instance derived from parent + // process + seg.allocate( fname, 4*4096, 0, 0660 ); + } + + xmt::shm_name_mgr<0>& nm_ch = seg_ch.name_mgr(); + xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( test_Condition_Object ); + fcnd_ch.set( true ); + } + catch ( const xmt::shm_bad_alloc& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + catch ( ... ) { + EXAM_ERROR_ASYNC_F( "Fail in child", eflag ); + } + + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + fcnd.try_wait(); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + catch ( ... ) { + EXAM_ERROR( "Fail in parent" ); + } + } + catch ( ... ) { + EXAM_ERROR( "Fail in fork" ); + } + + (&fcnd)->~__condition<true>(); + shm.deallocate( &fcnd, 1 ); + seg.deallocate(); + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + +/* ****************************************************** + */ +const char shm_test::fname1[] = "/tmp/mt_test.shm.1"; + +shm_test::shm_test() +{ + try { + seg1.allocate( fname1, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR_ASYNC( err.what() ); + } +} + +/* ****************************************************** + */ +shm_test::~shm_test() +{ + seg1.deallocate(); + fs::remove( fname1 ); +} + +/* ****************************************************** + */ + +int EXAM_IMPL(shm_test::shm_named_obj_more) +{ + enum { + ObjName = 1 + }; + + try { + xmt::shm_name_mgr<1>& nm = seg1.name_mgr(); + + xmt::allocator_shm<xmt::__condition<true>,1> shm; + + xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); + nm.named( fcnd, ObjName ); + fcnd.set( false ); + + try { + xmt::fork(); + + int eflag = 0; + + try { + xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); + xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; + xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); + fcnd_ch.set( true ); + nm_ch.release<xmt::__condition<true> >( ObjName ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + fcnd.try_wait(); + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here + + xmt::__condition<true>& fcnd1 = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); + nm.named( fcnd1, ObjName ); // ObjName should be free here + fcnd1.set( false ); + + try { + xmt::fork(); + + int eflag = 0; + + try { + xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); + xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; + xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); + fcnd_ch.set( true ); + nm_ch.release<xmt::__condition<true> >( ObjName ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + fcnd1.try_wait(); + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here + + xmt::allocator_shm<xmt::__barrier<true>,1> shm_b; + xmt::__barrier<true>& b = *new ( shm_b.allocate( 1 ) ) xmt::__barrier<true>(); + + nm.named( b, ObjName ); // ObjName should be free here + + try { + xmt::fork(); + + int eflag = 0; + try { + xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); + xmt::allocator_shm<xmt::__barrier<true>,1> shm_ch; + xmt::__barrier<true>& b_ch = nm_ch.named<xmt::__barrier<true> >( ObjName ); + b_ch.wait(); + nm_ch.release<xmt::__barrier<true> >( ObjName ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + b.wait(); + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + nm.release<xmt::__barrier<true> >( ObjName ); // barrier should be destroyed here + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + Copied: trunk/complement/explore/lib/mt/ut/shm_test.h (from rev 1834, branches/complement-sockios/explore/lib/mt/ut/shm_test.h) =================================================================== --- trunk/complement/explore/lib/mt/ut/shm_test.h (rev 0) +++ trunk/complement/explore/lib/mt/ut/shm_test.h 2008-03-26 11:45:54 UTC (rev 1836) @@ -0,0 +1,37 @@ +// -*- C++ -*- Time-stamp: <08/03/26 10:10:18 ptr> + +/* + * Copyright (c) 2006, 2007 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License Version 3.0 + * + */ + +#ifndef __SHM_TEST_H +#define __SHM_TEST_H + +#define FIT_EXAM + +#include <exam/suite.h> +#include <mt/shm.h> + +class shm_test +{ + public: + shm_test(); + ~shm_test(); + + int EXAM_DECL(shm_segment); + int EXAM_DECL(shm_alloc); + int EXAM_DECL(fork_shm); + int EXAM_DECL(shm_named_obj); + + int EXAM_DECL(shm_named_obj_more); + + private: + xmt::shm_alloc<1> seg1; + static const char fname1[]; +}; + +#endif // __SHM_TEST_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-03-26 11:10:48
|
Revision: 1835 http://complement.svn.sourceforge.net/complement/?rev=1835&view=rev Author: complement Date: 2008-03-26 04:10:43 -0700 (Wed, 26 Mar 2008) Log Message: ----------- connection processor implemented Modified Paths: -------------- branches/complement-sockios/explore/include/sockios/sockstream2 branches/complement-sockios/explore/include/sockios/sockstream2.cc branches/complement-sockios/explore/include/sockios/sp.h branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.h branches/complement-sockios/explore/lib/sockios/ut/sockios_test_suite.cc Modified: branches/complement-sockios/explore/include/sockios/sockstream2 =================================================================== --- branches/complement-sockios/explore/include/sockios/sockstream2 2008-03-26 10:57:21 UTC (rev 1834) +++ branches/complement-sockios/explore/include/sockios/sockstream2 2008-03-26 11:10:43 UTC (rev 1835) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/07 01:16:27 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 09:54:59 ptr> /* * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 @@ -222,6 +222,7 @@ static void __at_fork_child(); static void __at_fork_parent(); static int _count; + static bool _at_fork; }; static char Init_buf[]; @@ -290,6 +291,9 @@ int basic_socket<charT,traits,_Alloc>::Init::_count = 0; template<class charT, class traits, class _Alloc> +bool basic_socket<charT,traits,_Alloc>::Init::_at_fork = false; + +template<class charT, class traits, class _Alloc> void basic_socket<charT,traits,_Alloc>::Init::_guard( int direction ) { static std::tr2::mutex _init_lock; @@ -298,9 +302,14 @@ std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); if ( _count++ == 0 ) { basic_socket<charT,traits,_Alloc>::mgr = new detail::sockmgr<charT,traits,_Alloc>(); -// #ifdef __FIT__PTHREADS -// pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ); -// #endif +#ifdef __FIT_PTHREADS + if ( !_at_fork ) { // call only once + if ( pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ) ) { + // throw system_error; + } + _at_fork = true; + } +#endif // _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); } } else { @@ -313,7 +322,8 @@ template<class charT, class traits, class _Alloc> void basic_socket<charT,traits,_Alloc>::Init::__at_fork_prepare() -{ } +{ +} template<class charT, class traits, class _Alloc> void basic_socket<charT,traits,_Alloc>::Init::__at_fork_child() Modified: branches/complement-sockios/explore/include/sockios/sockstream2.cc =================================================================== --- branches/complement-sockios/explore/include/sockios/sockstream2.cc 2008-03-26 10:57:21 UTC (rev 1834) +++ branches/complement-sockios/explore/include/sockios/sockstream2.cc 2008-03-26 11:10:43 UTC (rev 1835) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/07 01:16:27 ptr> +// -*- C++ -*- Time-stamp: <08/03/18 09:51:28 ptr> /* * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 @@ -285,7 +285,7 @@ template<class charT, class traits, class _Alloc> void basic_sockbuf2<charT, traits, _Alloc>::shutdown( sock_base2::shutdownflg dir ) { - if ( basic_socket_t::is_open() ) { + if ( basic_socket_t::is_open_unsafe() ) { if ( (dir & (sock_base2::stop_in | sock_base2::stop_out)) == (sock_base2::stop_in | sock_base2::stop_out) ) { ::shutdown( basic_socket_t::_fd, 2 ); Modified: branches/complement-sockios/explore/include/sockios/sp.h =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.h 2008-03-26 10:57:21 UTC (rev 1834) +++ branches/complement-sockios/explore/include/sockios/sp.h 2008-03-26 11:10:43 UTC (rev 1835) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/07 01:40:59 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 09:55:19 ptr> /* * Copyright (c) 2008 @@ -22,6 +22,7 @@ #include <cerrno> #include <mt/thread> #include <mt/mutex> +#include <mt/condition_variable> #ifdef STLPORT # include <unordered_map> @@ -43,6 +44,8 @@ #endif #include <sockios/sockstream> +#include <deque> +#include <functional> namespace std { @@ -270,6 +273,313 @@ typedef sock_processor_base<char,char_traits<char>,allocator<char> > sock_basic_processor; +template <class Connect, class charT = char, class traits = std::char_traits<charT>, class _Alloc = std::allocator<charT>, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& ) = &Connect::connect > +class connect_processor : + public sock_processor_base<charT,traits,_Alloc> +{ + private: + typedef sock_processor_base<charT,traits,_Alloc> base_t; + + class Init + { + public: + Init() + { _guard( 1 ); } + ~Init() + { _guard( 0 ); } + + private: + static void _guard( int direction ); + static void __at_fork_prepare(); + static void __at_fork_child(); + static void __at_fork_parent(); + static int _count; + }; + + static char Init_buf[]; + + public: + connect_processor() : + not_empty( *this ), + _in_work( false ), + ploop( loop, this ) + { new( Init_buf ) Init(); } + + explicit connect_processor( int port ) : + base_t( port, sock_base2::sock_stream ), + not_empty( *this ), + _in_work( false ), + ploop( loop, this ) + { new( Init_buf ) Init(); } + + ~connect_processor() + { + connect_processor::close(); + if ( ploop.joinable() ) { + ploop.join(); + } + ((Init *)Init_buf)->~Init(); + } + + virtual void close(); + + void wait() + { if ( ploop.joinable() ) { ploop.join(); } } + + private: + virtual void operator ()( typename base_t::sockstream_t& s, const typename base_t::adopt_new_t& ); + virtual void operator ()( typename base_t::sockstream_t& s, const typename base_t::adopt_close_t& ); + virtual void operator ()( typename base_t::sockstream_t& s, const typename base_t::adopt_data_t& ); + + + static void loop( connect_processor* me ) + { me->worker(); } + + void worker(); + + private: + struct processor + { + processor() : + c(0), + s(0) + { } + processor( Connect* __c, typename sock_processor_base<charT,traits,_Alloc>::sockstream_t* __s ) : + c(__c), + s(__s) + { } + processor( const processor& p ) : + c( p.c ), + s( p.s ) + { } + + processor& operator =( const processor& p ) + { c = p.c; s = p.s; return *this; } + + Connect* c; + typename sock_processor_base<charT,traits,_Alloc>::sockstream_t* s; + + bool operator ==( const processor& p ) const + { return s == p.s; } + bool operator ==( const typename sock_processor_base<charT,traits,_Alloc>::sockstream_t* st ) const + { return const_cast<const typename sock_processor_base<charT,traits,_Alloc>::sockstream_t*>(s) == st; } + +/* + struct equal_to : + public std::binary_function<processor, typename sock_processor_base<charT,traits,_Alloc>::sockstream_t*, bool> + { + bool operator()(const processor& __x, const typename sock_processor_base<charT,traits,_Alloc>::sockstream_t* __y) const + { return __x == __y; } + }; +*/ + }; + + bool pop_ready( processor& ); + +#ifdef __USE_STLPORT_HASH + typedef std::hash_map<typename base_t::sockstream_t*,Connect*> worker_pool_t; +#endif +#ifdef __USE_STD_HASH + typedef __gnu_cxx::hash_map<typename base_t::sockstream_t*,Connect*> worker_pool_t; +#endif +#if defined(__USE_STLPORT_TR1) || defined(__USE_STD_TR1) + typedef std::tr1::unordered_map<typename base_t::sockstream_t*,Connect*> worker_pool_t; +#endif + typedef std::deque<processor> ready_pool_t; + + struct _not_empty + { + _not_empty( connect_processor& p ) : + me( p ) + { } + + bool operator()() const + { return !me.ready_pool.empty(); } + + connect_processor& me; + } not_empty; + + worker_pool_t worker_pool; + ready_pool_t ready_pool; + volatile bool _in_work; + std::tr2::mutex wklock; + std::tr2::mutex rdlock; + std::tr2::condition_variable cnd; + std::tr2::mutex inwlock; + std::tr2::condition_variable cnd_inwk; + std::tr2::thread ploop; + + friend struct _not_empty; +}; + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +int connect_processor<Connect, charT, traits, _Alloc, C>::Init::_count = 0; + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::Init::_guard( int direction ) +{ + static std::tr2::mutex _init_lock; + + if ( direction ) { + std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); + if ( _count++ == 0 ) { + +// #ifdef __FIT__PTHREADS +// pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ); +// #endif +// _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); + } + } else { + std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); + if ( --_count == 0 ) { + + } + } +} + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_prepare() +{ } + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_child() +{ + if ( _count != 0 ) { + + } + // _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); +} + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::Init::__at_fork_parent() +{ } + +template<class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +char connect_processor<Connect, charT, traits, _Alloc, C>::Init_buf[128]; + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::close() +{ + base_t::close(); + + { + std::tr2::lock_guard<std::tr2::mutex> lk(inwlock); + _in_work = false; // <--- set before cnd.notify_one(); (below in this func) + } + + std::tr2::lock_guard<std::tr2::mutex> lk2( rdlock ); + ready_pool.push_back( processor() ); // make ready_pool not empty + // std::cerr << "=== " << ready_pool.size() << std::endl; + cnd.notify_one(); +} + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_new_t& ) +{ + Connect* c = new Connect( s ); + if ( s.rdbuf()->in_avail() ) { + std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); + ready_pool.push_back( processor( c, &s ) ); + cnd.notify_one(); + } else { + std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); + worker_pool[&s] = c; + } +} + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_close_t& ) +{ + { + std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); + typename worker_pool_t::iterator i = worker_pool.find( &s ); + if ( i != worker_pool.end() ) { + delete i->second; + // std::cerr << "oops\n"; + worker_pool.erase( i ); + return; + } + } + + Connect* c = 0; + { + std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); + typename ready_pool_t::iterator j = std::find( ready_pool.begin(), ready_pool.end(), /* std::bind2nd( typename processor::equal_to(), &s ) */ &s ); + if ( j != ready_pool.end() ) { + // std::cerr << "oops 2\n"; + c = j->c; + ready_pool.erase( j ); + } + } + if ( c != 0 ) { + (c->*C)( s ); + delete c; + } +} + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::operator ()( typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::sockstream_t& s, const typename connect_processor<Connect, charT, traits, _Alloc, C>::base_t::adopt_data_t& ) +{ + Connect* c; + + { + std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); + typename worker_pool_t::const_iterator i = worker_pool.find( &s ); + if ( i == worker_pool.end() ) { + return; + } + c = i->second; + worker_pool.erase( i ); + } + + std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); + ready_pool.push_back( processor( c, &s ) ); + cnd.notify_one(); + // std::cerr << "notify data " << (void *)c << " " << ready_pool.size() << std::endl; +} + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +bool connect_processor<Connect, charT, traits, _Alloc, C>::pop_ready( processor& p ) +{ + { + std::tr2::unique_lock<std::tr2::mutex> lk( rdlock ); + + cnd.wait( lk, not_empty ); + p = ready_pool.front(); // it may contain p.c == 0, p.s == 0, if !in_work() + ready_pool.pop_front(); + // std::cerr << "pop 1\n"; + if ( p.c == 0 ) { // wake up, but _in_work may be still true here (in processor pipe?), + return false; // even I know that _in_work <- false before notification... + } // so, check twice + } + + // std::cerr << "pop 2\n"; + + std::tr2::lock_guard<std::tr2::mutex> lk(inwlock); + return _in_work ? true : false; +} + + +template <class Connect, class charT, class traits, class _Alloc, void (Connect::*C)( std::basic_sockstream2<charT,traits,_Alloc>& )> +void connect_processor<Connect, charT, traits, _Alloc, C>::worker() +{ + _in_work = true; + + processor p; + + while ( pop_ready( p ) ) { + // std::cerr << "worker 1\n"; + (p.c->*C)( *p.s ); + if ( p.s->rdbuf()->in_avail() ) { + std::tr2::lock_guard<std::tr2::mutex> lk( rdlock ); + ready_pool.push_back( p ); + } else { + std::tr2::lock_guard<std::tr2::mutex> lk( wklock ); + worker_pool[p.s] = p.c; + } + } +} + namespace detail { template<class charT, class traits, class _Alloc> @@ -424,7 +734,7 @@ template<class charT, class traits, class _Alloc> void sockmgr<charT,traits,_Alloc>::io_worker() { - epoll_event ev[n_ret]; + epoll_event ev[/*n_ret*/ 512 ]; /* ctl _xctl; @@ -437,22 +747,28 @@ } */ + try { for ( ; ; ) { - int n = epoll_wait( efd, &ev[0], n_ret, -1 ); + int n = epoll_wait( efd, &ev[0], /* n_ret */ 512, -1 ); if ( n < 0 ) { if ( errno == EINTR ) { continue; } // throw system_error } + // std::cerr << "epoll see " << n << std::endl; for ( int i = 0; i < n; ++i ) { + // std::cerr << "epoll i = " << i << std::endl; if ( ev[i].data.fd == pipefd[0] ) { + // std::cerr << "on pipe\n"; epoll_event ev_add; ctl _ctl; int r = read( pipefd[0], &_ctl, sizeof(ctl) ); if ( r < 0 ) { // throw system_error + // std::cerr << "Read pipe\n"; } else if ( r == 0 ) { + // std::cerr << "Read pipe 0\n"; return; } @@ -461,6 +777,10 @@ ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; ev_add.data.fd = static_cast<socks_processor_t*>(_ctl.data.ptr)->fd(); if ( ev_add.data.fd >= 0 ) { + if ( fcntl( ev_add.data.fd, F_SETFL, fcntl( ev_add.data.fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { + // std::cerr << "xxx " << errno << " " << std::tr2::getpid() << std::endl; + throw std::runtime_error( "can't establish nonblock mode on listener" ); + } fd_info new_info = { fd_info::listener, 0, static_cast<socks_processor_t*>(_ctl.data.ptr) }; descr[ev_add.data.fd] = new_info; if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { @@ -496,12 +816,14 @@ } break; case rqstop: + // std::cerr << "Stop request\n"; return; break; } continue; } + // std::cerr << "#\n"; typename fd_container_type::iterator ifd = descr.find( ev[i].data.fd ); if ( ifd == descr.end() ) { @@ -510,49 +832,67 @@ fd_info& info = ifd->second; if ( info.flags & fd_info::listener ) { + // std::cerr << "%\n"; if ( ev[i].events & EPOLLRDHUP ) { epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ); // walk through descr and detach every .p ? descr.erase( ifd ); + // std::cerr << "Remove listener EPOLLRDHUP\n"; } else if ( ev[i].events & EPOLLIN ) { sockaddr addr; socklen_t sz = sizeof( sockaddr_in ); - int fd = accept( ev[i].data.fd, &addr, &sz ); - if ( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { - throw std::runtime_error( "can't establish nonblock mode" ); - } - sockstream_t* s; + for ( ; ; ) { + int fd = accept( ev[i].data.fd, &addr, &sz ); + if ( fd < 0 ) { + if ( (errno == EINTR) || (errno == ECONNABORTED) /* || (errno == ERESTARTSYS) */ ) { + continue; + } + if ( !(errno == EAGAIN || errno == EWOULDBLOCK) ) { + // std::cerr << "Accept, listener " << ev[i].data.fd << ", errno " << errno << std::endl; + // throw system_error ? + } + break; + } + // std::cerr << "listener accept " << fd << std::endl; + if ( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { + throw std::runtime_error( "can't establish nonblock mode" ); + } + sockstream_t* s; - try { - s = new sockstream_t(); - if ( s->rdbuf()->_open_sockmgr( fd, addr ) ) { - epoll_event ev_add; - ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; - ev_add.data.fd = fd; - fd_info new_info = { fd_info::owner, s, info.p }; - descr[fd] = new_info; + try { + s = new sockstream_t(); + if ( s->rdbuf()->_open_sockmgr( fd, addr ) ) { + epoll_event ev_add; + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = fd; + fd_info new_info = { fd_info::owner, s, info.p }; + descr[fd] = new_info; - if ( epoll_ctl( efd, EPOLL_CTL_ADD, fd, &ev_add ) < 0 ) { - std::cerr << "Accept, add " << fd << ", errno " << errno << std::endl; - descr.erase( fd ); - // throw system_error + if ( epoll_ctl( efd, EPOLL_CTL_ADD, fd, &ev_add ) < 0 ) { + // std::cerr << "Accept, add " << fd << ", errno " << errno << std::endl; + descr.erase( fd ); + // throw system_error + } + (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); + } else { + // std::cerr << "Accept, delete " << fd << std::endl; + delete s; } - (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); - } else { - std::cerr << "Accept, delete " << fd << std::endl; + } + catch ( const std::bad_alloc& ) { + // nothing + } + catch ( ... ) { + descr.erase( fd ); delete s; } } - catch ( const std::bad_alloc& ) { - // nothing - } - catch ( ... ) { - descr.erase( fd ); - delete s; - } + } else { + // std::cerr << "listener: " << std::hex << ev[i].events << std::dec << std::endl; } } else { + // std::cerr << "not listener\n"; if ( ev[i].events & EPOLLIN ) { if ( (info.flags & fd_info::owner) == 0 ) { // marginal case: me not owner (registerd via push(), @@ -620,6 +960,7 @@ b->setg( b->eback(), b->gptr(), b->egptr() + offset ); b->ucnd.notify_one(); if ( info.p != 0 ) { + // std::cerr << "data here" << std::endl; (*info.p)( *info.s.s, typename socks_processor_t::adopt_data_t() ); } } else { @@ -675,12 +1016,53 @@ } } } + } + catch ( std::exception& e ) { + std::cerr << e.what() << std::endl; + } } } //detail } // namesapce std +#if defined(__USE_STLPORT_HASH) || defined(__USE_STLPORT_TR1) || defined(__USE_STD_TR1) +# define __HASH_NAMESPACE std +#endif +#if defined(__USE_STD_HASH) +# define __HASH_NAMESPACE __gnu_cxx +#endif + +namespace __HASH_NAMESPACE { + +#ifdef __USE_STD_TR1 +namespace tr1 { +#endif + +template <class charT, class traits, class _Alloc> +struct hash<std::basic_sockstream2<charT, traits, _Alloc>* > +{ + size_t operator()(const std::basic_sockstream2<charT, traits, _Alloc>* __x) const + { return reinterpret_cast<size_t>(__x); } +}; + +#ifdef __USE_STD_TR1 +} +#endif + +#if defined(__GNUC__) && (__GNUC__ < 4) +template<> +struct hash<void *> +{ + size_t operator()(const void *__x) const + { return reinterpret_cast<size_t>(__x); } +}; +#endif // __GNUC__ < 4 + +} // namespace __HASH_NAMESPACE + +#undef __HASH_NAMESPACE + #ifdef __USE_STLPORT_HASH # undef __USE_STLPORT_HASH #endif Modified: branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc =================================================================== --- branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc 2008-03-26 10:57:21 UTC (rev 1834) +++ branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc 2008-03-26 11:10:43 UTC (rev 1835) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/06 23:31:13 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 11:48:40 ptr> /* * @@ -14,6 +14,8 @@ #include <sockios/sockstream2> #include <mt/mutex> +#include <sys/wait.h> +#include <mt/shm.h> using namespace std; using namespace std::tr2; @@ -28,33 +30,6 @@ /* ************************************************************ */ -class worker -{ - public: - worker( sockstream& ) - { lock_guard<mutex> lk(lock); ++cnt; ++visits; } - - ~worker() - { lock_guard<mutex> lk(lock); --cnt; } - - void connect( sockstream& ) - { } - - void close() - { } - - static int get_visits() - { lock_guard<mutex> lk(lock); return visits; } - - static mutex lock; - static int cnt; - static int visits; -}; - -mutex worker::lock; -int worker::cnt = 0; -int worker::visits = 0; - class simple_mgr : public sock_basic_processor { @@ -145,7 +120,7 @@ return EXAM_RESULT; } -int EXAM_IMPL(sockios2_test::ctor_dtor) +int EXAM_IMPL(sockios2_test::connect_disconnect) { { simple_mgr srv( 2008 ); @@ -211,82 +186,261 @@ } } -#if 0 - // Check, that number of ctors of Cnt is the same as number of called dtors - // i.e. all created Cnt was released. + return EXAM_RESULT; +} + +class worker +{ + public: + worker( sockstream2& ) + { lock_guard<mutex> lk(lock); ++cnt; ++visits; cnd.notify_one(); } + + ~worker() + { lock_guard<mutex> lk(lock); --cnt; } + + void connect( sockstream2& s ) + { lock_guard<mutex> lk(lock); getline( s, line ); ++rd; line_cnd.notify_one(); } + +// void close() +// { } + + static int get_visits() + { lock_guard<mutex> lk(lock); return visits; } + + static mutex lock; + static int cnt; + static /* volatile */ int visits; + static condition_variable cnd; + static string line; + static condition_variable line_cnd; + static int rd; + // static barrier b; +}; + +mutex worker::lock; +int worker::cnt = 0; +/* volatile */ int worker::visits = 0; +condition_variable worker::cnd; +string worker::line; +condition_variable worker::line_cnd; +int worker::rd = 0; + +// barrier worker::b; + +// void stopper( connect_processor<worker>* prss ) +// { +// b.wait(); +// prss->close(); +// } + +bool visits_counter1() +{ + return worker::visits == 1; +} + +bool visits_counter2() +{ + return worker::visits == 2; +} + +bool rd_counter1() +{ + return worker::rd == 1; +} + +int EXAM_IMPL(sockios2_test::processor_core) +{ { - sockmgr_stream_MP<Cnt> srv( port ); + connect_processor<worker> prss( 2008 ); + EXAM_CHECK( prss.good() ); + EXAM_CHECK( prss.is_open() ); + { - sockstream s1( "localhost", port ); + sockstream2 s( "localhost", 2008 ); - EXAM_CHECK( s1.good() ); - EXAM_CHECK( s1.is_open() ); + EXAM_CHECK( s.good() ); + EXAM_CHECK( s.is_open() ); - s1 << "1234" << endl; +// for ( int i = 0; i < 64; ++i ) { // give chance to process it +// std::tr2::this_thread::yield(); +// } + unique_lock<mutex> lk( worker::lock ); + + worker::cnd.timed_wait( lk, milliseconds( 100 ), visits_counter1 ); + + EXAM_CHECK( worker::visits == 1 ); + worker::visits = 0; + } + } + { + lock_guard<mutex> lk( worker::lock ); + EXAM_CHECK( worker::cnt == 0 ); + } + + { + connect_processor<worker> prss( 2008 ); + + EXAM_CHECK( prss.good() ); + EXAM_CHECK( prss.is_open() ); + + { + sockstream2 s1( "localhost", 2008 ); + EXAM_CHECK( s1.good() ); EXAM_CHECK( s1.is_open() ); - while ( Cnt::get_visits() == 0 ) { - xmt::Thread::yield(); - } - Cnt::lock.lock(); - EXAM_CHECK( Cnt::cnt == 1 ); - Cnt::lock.unlock(); - } - srv.close(); - srv.wait(); + sockstream2 s2( "localhost", 2008 ); - Cnt::lock.lock(); - EXAM_CHECK( Cnt::cnt == 0 ); - Cnt::visits = 0; - Cnt::lock.unlock(); + EXAM_CHECK( s2.good() ); + EXAM_CHECK( s2.is_open() ); + +// for ( int i = 0; i < 1024; ++i ) { // give chance to process it +// std::tr2::this_thread::yield(); +// } + unique_lock<mutex> lk( worker::lock ); + + worker::cnd.timed_wait( lk, milliseconds( 100 ), visits_counter2 ); + + EXAM_CHECK( worker::visits == 2 ); + worker::visits = 0; + } } + { + lock_guard<mutex> lk( worker::lock ); + EXAM_CHECK( worker::cnt == 0 ); + } - Cnt::lock.lock(); - EXAM_CHECK( Cnt::cnt == 0 ); - Cnt::lock.unlock(); + // check before sockstream2 was closed { - sockmgr_stream_MP<Cnt> srv( port ); + connect_processor<worker> prss( 2008 ); + EXAM_CHECK( prss.good() ); + EXAM_CHECK( prss.is_open() ); + { - sockstream s1( "localhost", port ); - sockstream s2( "localhost", port ); + sockstream2 s1( "localhost", 2008 ); EXAM_CHECK( s1.good() ); EXAM_CHECK( s1.is_open() ); - EXAM_CHECK( s2.good() ); - EXAM_CHECK( s2.is_open() ); - s1 << "1234" << endl; - s2 << "1234" << endl; + s1 << "Hello, world!" << endl; + unique_lock<mutex> lk( worker::lock ); + worker::cnd.timed_wait( lk, milliseconds( 100 ), rd_counter1 ); + + // cerr << worker::line << endl; + EXAM_CHECK( worker::line == "Hello, world!" ); + worker::line = ""; + worker::rd = 0; + } + } + + + EXAM_CHECK( worker::line == "" ); + + // check after sockstream2 was closed, i.e. ensure, that all data available read before close + { + connect_processor<worker> prss( 2008 ); + + EXAM_CHECK( prss.good() ); + EXAM_CHECK( prss.is_open() ); + + { + sockstream2 s1( "localhost", 2008 ); + EXAM_CHECK( s1.good() ); EXAM_CHECK( s1.is_open() ); - EXAM_CHECK( s2.good() ); - EXAM_CHECK( s2.is_open() ); - while ( Cnt::get_visits() < 2 ) { - xmt::Thread::yield(); - } - Cnt::lock.lock(); - EXAM_CHECK( Cnt::cnt == 2 ); - Cnt::lock.unlock(); + + s1 << "Hello, world!" << endl; } - srv.close(); - srv.wait(); + unique_lock<mutex> lk( worker::lock ); + worker::cnd.timed_wait( lk, milliseconds( 100 ), rd_counter1 ); - Cnt::lock.lock(); - EXAM_CHECK( Cnt::cnt == 0 ); - Cnt::lock.unlock(); + // cerr << worker::line << endl; + EXAM_CHECK( worker::line == "Hello, world!" ); + worker::line = ""; + worker::rd = 0; } - Cnt::lock.lock(); - EXAM_CHECK( Cnt::cnt == 0 ); - Cnt::lock.unlock(); -#endif + EXAM_CHECK( worker::line == "" ); return EXAM_RESULT; } + +int EXAM_IMPL(sockios2_test::fork) +{ + const char fname[] = "/tmp/sockios2_test.shm"; + + /* You must work very carefully with sockets, theads and fork: it unsafe in principle + and no way to make it safe. Never try to pass _opened_ connection via fork. + Here I create sockstream, but without connection (it check that io processing + loop in underlying sockmgr finish and restart smoothly in child process). + */ + sockstream2 s; + + // worker::lock.lock(); + worker::visits = 0; + // worker::lock.unlock(); + + try { + xmt::shm_alloc<0> seg; + seg.allocate( fname, 4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + + xmt::allocator_shm<barrier_ip,0> shm; + barrier_ip& b = *new ( shm.allocate( 1 ) ) barrier_ip(); + + try { + + EXAM_CHECK( worker::visits == 0 ); + + this_thread::fork(); + { + connect_processor<worker> prss( 2008 ); + + EXAM_CHECK_ASYNC( worker::visits == 0 ); + + b.wait(); // -- align here + + EXAM_CHECK_ASYNC( prss.good() ); + EXAM_CHECK_ASYNC( prss.is_open() ); + + unique_lock<mutex> lk( worker::lock ); + worker::cnd.timed_wait( lk, milliseconds( 100 ), visits_counter1 ); + + EXAM_CHECK_ASYNC( worker::visits == 1 ); + } + + exit( 0 ); + } + catch ( std::tr2::fork_in_parent& child ) { + b.wait(); // -- align here + + s.open( "localhost", 2008 ); + + EXAM_CHECK( s.good() ); + EXAM_CHECK( s.is_open() ); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + + EXAM_CHECK( worker::visits == 0 ); + } + shm.deallocate( &b ); + seg.deallocate(); + unlink( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} Modified: branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.h =================================================================== --- branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.h 2008-03-26 10:57:21 UTC (rev 1834) +++ branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.h 2008-03-26 11:10:43 UTC (rev 1835) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/07/18 08:52:26 ptr> +// -*- C++ -*- Time-stamp: <08/03/25 06:22:29 ptr> /* * @@ -22,7 +22,9 @@ ~sockios2_test(); int EXAM_DECL(srv_core); - int EXAM_DECL(ctor_dtor); + int EXAM_DECL(connect_disconnect); + int EXAM_DECL(processor_core); + int EXAM_DECL(fork); }; #endif // __sockios2_test_h Modified: branches/complement-sockios/explore/lib/sockios/ut/sockios_test_suite.cc =================================================================== --- branches/complement-sockios/explore/lib/sockios/ut/sockios_test_suite.cc 2008-03-26 10:57:21 UTC (rev 1834) +++ branches/complement-sockios/explore/lib/sockios/ut/sockios_test_suite.cc 2008-03-26 11:10:43 UTC (rev 1835) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/07/19 00:19:19 ptr> +// -*- C++ -*- Time-stamp: <08/03/25 07:48:17 ptr> /* * @@ -80,8 +80,10 @@ sockios2_test test2; - t.add( &sockios2_test::ctor_dtor, test2, "sockios2_test::ctor_dtor", - t.add( &sockios2_test::srv_core, test2, "sockios2_test::srv_core" ) ); + t.add( &sockios2_test::fork, test2, "sockios2_test::fork", + t.add( &sockios2_test::processor_core, test2, "sockios2_test::processor_core", + t.add( &sockios2_test::connect_disconnect, test2, "sockios2_test::connect_disconnect", + t.add( &sockios2_test::srv_core, test2, "sockios2_test::srv_core" ) ) ) ); return t.girdle(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-03-26 10:57:23
|
Revision: 1834 http://complement.svn.sourceforge.net/complement/?rev=1834&view=rev Author: complement Date: 2008-03-26 03:57:21 -0700 (Wed, 26 Mar 2008) Log Message: ----------- mutex: add rw_mutex_ip typedef; condition_variable: fix wrong typedef for barrier_ip; thread, thread.cc: __at_fork_* handlers moved into Init; added fork call; on fork down thread's ids to bad id, except thread that call fork; set __at_fork_* handlers only once; lock all threads mutexes before fork and release all ones after---safe fork; shm.h: based on JTC1/SC22/WG21 threads interfaces, but still in xmt namespace for compatibility; ut/mt_test.cc, ut/mt_test.h, ut/shm_test.h, ut/shm_test.cc: move shared memory test suite into separate file; ut/mt_test_wg21.h, ut/mt_test_wg21.cc: test for fork; libxmt: version 2.0.1. Modified Paths: -------------- branches/complement-sockios/explore/include/mt/condition_variable branches/complement-sockios/explore/include/mt/mutex branches/complement-sockios/explore/include/mt/shm.h branches/complement-sockios/explore/include/mt/thread branches/complement-sockios/explore/lib/mt/ChangeLog branches/complement-sockios/explore/lib/mt/Makefile.inc branches/complement-sockios/explore/lib/mt/thread.cc branches/complement-sockios/explore/lib/mt/ut/Makefile.inc branches/complement-sockios/explore/lib/mt/ut/mt_test.cc branches/complement-sockios/explore/lib/mt/ut/mt_test.h branches/complement-sockios/explore/lib/mt/ut/mt_test_suite.cc branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.cc branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.h Added Paths: ----------- branches/complement-sockios/explore/lib/mt/ut/shm_test.cc branches/complement-sockios/explore/lib/mt/ut/shm_test.h Modified: branches/complement-sockios/explore/include/mt/condition_variable =================================================================== --- branches/complement-sockios/explore/include/mt/condition_variable 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/include/mt/condition_variable 2008-03-26 10:57:21 UTC (rev 1834) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/06 13:23:11 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:18:13 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -768,7 +768,7 @@ }; typedef __barrier<false> barrier; -typedef __barrier<false> barrier_ip; +typedef __barrier<true> barrier_ip; } // namespace tr2 Modified: branches/complement-sockios/explore/include/mt/mutex =================================================================== --- branches/complement-sockios/explore/include/mt/mutex 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/include/mt/mutex 2008-03-26 10:57:21 UTC (rev 1834) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/24 23:48:23 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:20:36 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -831,6 +831,7 @@ typedef __mutex<true,true> recursive_mutex_ip; #ifdef __FIT_RWLOCK typedef __rw_mutex<false> rw_mutex; +typedef __rw_mutex<true> rw_mutex_ip; #endif // __FIT_RWLOCK #ifdef __FIT_PTHREAD_SPINLOCK typedef __spinlock<false,false> spinlock; Modified: branches/complement-sockios/explore/include/mt/shm.h =================================================================== --- branches/complement-sockios/explore/include/mt/shm.h 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/include/mt/shm.h 2008-03-26 10:57:21 UTC (rev 1834) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/08/03 09:47:53 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:37:01 ptr> /* - * Copyright (c) 2006, 2007 + * Copyright (c) 2006-2008 * Petr Ovtchenkov * * Licensed under the Academic Free License version 3.0 @@ -25,6 +25,9 @@ #include <mt/xmt.h> +#include <mt/mutex> +#include <mt/condition_variable> + namespace xmt { struct shm_base @@ -94,12 +97,22 @@ __SPEC_FULL(is_ipc_sharable,float,true); __SPEC_FULL(is_ipc_sharable,double,true); __SPEC_FULL(is_ipc_sharable,long double,true); + __SPEC_FULL(is_ipc_sharable,xmt::__condition<true>,true); __SPEC_FULL(is_ipc_sharable,xmt::__semaphore<true>,true); __SPEC_FULL(is_ipc_sharable,xmt::__barrier<true>,true); __SPEC_FULL(is_ipc_sharable,xmt::shared_mutex,true); __SPEC_FULL(is_ipc_sharable,xmt::shared_recursive_mutex,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::condition_variable_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::condition_variable_any_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::semaphore_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::barrier_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::mutex_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::recursive_mutex_ip,true); +__SPEC_FULL(is_ipc_sharable,std::tr2::rw_mutex_ip,true); + + #undef __SPEC_FULL #undef __SPEC_ @@ -307,7 +320,7 @@ template <class T> void named( const T& obj, int name ) { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); if ( _last == 255 ) { throw std::range_error( "too many named objects" ); } @@ -332,7 +345,7 @@ template <class T> T& named( int name ) { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { ++_nm_table[i].count; @@ -345,7 +358,7 @@ template <class T> const T& named( int name ) const { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { ++_nm_table[i].count; @@ -358,7 +371,7 @@ template <class T> void release( int name ) { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { if ( --_nm_table[i].count == 0 ) { @@ -375,7 +388,7 @@ int count( int name ) const throw() { - xmt::basic_lock<__mutex<false,true> > lk( _lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( _lock ); for ( int i = 0; _nm_table[i].name != -1; ++i ) { if ( _nm_table[i].name == name ) { return _nm_table[i].count; @@ -395,7 +408,7 @@ shm_name_mgr& operator =( const shm_name_mgr& ) { return *this; } - xmt::__mutex<false,true> _lock; + std::tr2::mutex_ip _lock; struct _name_rec { int name; @@ -424,7 +437,7 @@ { uint64_t _magic; size_type _first; - xmt::__mutex<false,true> _lock; + std::tr2::mutex_ip _lock; size_type _nm; }; @@ -466,8 +479,9 @@ pointer p = _seg.address(); if ( p != reinterpret_cast<pointer>(-1) && (force || _seg.count() <= 1) ) { + using namespace std::tr2; _master *m = reinterpret_cast<_master *>( _seg.address() ); - (&m->_lock)->~__mutex<false,true>(); + (&m->_lock)->~mutex_ip(); if ( m->_nm != 0 ) { reinterpret_cast<shm_name_mgr<_Inst> *>(reinterpret_cast<char *>(p) + m->_nm)->~shm_name_mgr<_Inst>(); } @@ -484,7 +498,7 @@ if ( p != reinterpret_cast<pointer>(-1) ) { _master *m = reinterpret_cast<_master *>( p ); if ( m->_nm == 0 ) { - xmt::basic_lock<xmt::__mutex<false,true> > lk( m->_lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m->_lock ); void *nm = _traverse( &m->_first, sizeof(shm_name_mgr<_Inst>) ); m->_nm = reinterpret_cast<char *>(nm) - reinterpret_cast<char *>(p); return *new ( nm ) shm_name_mgr<_Inst>(); @@ -500,7 +514,7 @@ { _master *m = reinterpret_cast<_master *>( _seg.address() ); if ( m != reinterpret_cast<_master *>(-1) ) { - xmt::basic_lock<xmt::__mutex<false,true> > lk( m->_lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m->_lock ); return _traverse( &m->_first, n ); } @@ -516,8 +530,8 @@ static void init( _master& m ) { m._magic = MAGIC; - new ( &m._lock ) xmt::__mutex<false,true>(); - xmt::basic_lock<xmt::__mutex<false,true> > lk( m._lock ); + new ( &m._lock ) std::tr2::mutex_ip(); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m._lock ); m._first = sizeof( _master ); m._nm = 0; _fheader& h = *new ( reinterpret_cast<char *>(&m) + sizeof(_master) ) _fheader(); @@ -539,7 +553,7 @@ n = std::max( n + (__align - n % __align) % __align, sizeof(_fheader) ); _master *m = reinterpret_cast<_master *>( _seg.address() ); if ( m != reinterpret_cast<_master *>(-1) && (reinterpret_cast<char *>(p) - reinterpret_cast<char *>(_seg.address())) < (_seg.max_size() + sizeof(_master) + sizeof(_aheader) ) ) { - xmt::basic_lock<xmt::__mutex<false,true> > lk( m->_lock ); + std::tr2::lock_guard<std::tr2::mutex_ip> lk( m->_lock ); _aheader *a = reinterpret_cast<_aheader *>( reinterpret_cast<char *>(p) - sizeof(_aheader) ); size_type off = reinterpret_cast<char *>(p) - reinterpret_cast<char *>(_seg.address()); if ( m->_first == 0 ) { Modified: branches/complement-sockios/explore/include/mt/thread =================================================================== --- branches/complement-sockios/explore/include/mt/thread 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/include/mt/thread 2008-03-26 10:57:21 UTC (rev 1834) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 16:11:00 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 01:58:08 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -78,6 +78,8 @@ }; #endif // !_WIN32 +__FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); + class thread_base { public: @@ -135,6 +137,7 @@ friend class thread_base; friend id get_id(void); + // friend __FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); }; enum { @@ -161,6 +164,9 @@ Init(); ~Init(); private: + static void __at_fork_prepare(); + static void __at_fork_parent(); + static void __at_fork_child(); static int& _count; }; @@ -203,6 +209,7 @@ std::string _stack_on_create; #endif friend class Init; + friend __FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); }; template <unsigned F, size_t S> @@ -605,11 +612,18 @@ // trick to declare thread_base::id get_id() as friend in thread_base::id thread_base::id get_id(); +pid_t getpid(); +pid_t getppid(); + namespace this_thread { - // std::thread_base::id get_id(); - using tr2::get_id; +using tr2::fork; +__FIT_DECLSPEC void become_daemon() throw( fork_in_parent, std::runtime_error ); + +// std::thread_base::id get_id(); +using tr2::get_id; + inline void yield() { #ifdef __FIT_PTHREADS Modified: branches/complement-sockios/explore/lib/mt/ChangeLog =================================================================== --- branches/complement-sockios/explore/lib/mt/ChangeLog 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/lib/mt/ChangeLog 2008-03-26 10:57:21 UTC (rev 1834) @@ -1,3 +1,29 @@ +2008-03-26 Petr Ovtchenkov <pt...@is...> + + * mutex: add rw_mutex_ip typedef; + + * condition_variable: fix wrong typedef for barrier_ip; + + * thread, thread.cc: __at_fork_* handlers moved into Init; + added fork call; on fork down thread's ids to bad id, + except thread that call fork; set __at_fork_* handlers + only once; lock all threads mutexes before fork and + release all ones after---safe fork; + + * shm.h: based on JTC1/SC22/WG21 threads interfaces, but + still in xmt namespace for compatibility; + + * note: implementation of threads interfaces are close + to JTC1/SC22/WG21 C++ 0x working draft, see + http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2521.pdf + + * ut/mt_test.cc, ut/mt_test.h, ut/shm_test.h, ut/shm_test.cc: + move shared memory test suite into separate file; + + * ut/mt_test_wg21.h, ut/mt_test_wg21.cc: test for fork; + + * libxmt: version 2.0.1. + 2008-03-06 Petr Ovtchenkov <pt...@is...> * condition_variable: const casts for pthread_cond_* calls; Modified: branches/complement-sockios/explore/lib/mt/Makefile.inc =================================================================== --- branches/complement-sockios/explore/lib/mt/Makefile.inc 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/lib/mt/Makefile.inc 2008-03-26 10:57:21 UTC (rev 1834) @@ -3,7 +3,7 @@ LIBNAME = xmt MAJOR = 2 MINOR = 0 -PATCH = 0 +PATCH = 1 SRC_CC = xmt.cc thr_mgr.cc time.cc uid.cc shm.cc callstack.cc system_error.cc thread.cc \ date_time.cc SRC_C = fl.c Modified: branches/complement-sockios/explore/lib/mt/thread.cc =================================================================== --- branches/complement-sockios/explore/lib/mt/thread.cc 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/lib/mt/thread.cc 2008-03-26 10:57:21 UTC (rev 1834) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 16:08:25 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 02:02:03 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -41,17 +41,77 @@ #include <stdio.h> #include <syscall.h> +#ifdef STLPORT +// # include <unordered_map> +# include <unordered_set> +// # include <hash_map> +// # include <hash_set> +// # define __USE_STLPORT_HASH +# define __USE_STLPORT_TR1 +#else +# if defined(__GNUC__) && (__GNUC__ < 4) +// # include <ext/hash_map> +# include <ext/hash_set> +# define __USE_STD_HASH +# else +// # include <tr1/unordered_map> +# include <tr1/unordered_set> +# define __USE_STD_TR1 +# endif +#endif + + #ifdef WIN32 # pragma warning( disable : 4290) // using namespace std; #endif +#if defined(__USE_STLPORT_HASH) || defined(__USE_STLPORT_TR1) || defined(__USE_STD_TR1) +# define __HASH_NAMESPACE std +#endif +#if defined(__USE_STD_HASH) +# define __HASH_NAMESPACE __gnu_cxx +#endif + +namespace __HASH_NAMESPACE { + +#ifdef __USE_STD_TR1 +namespace tr1 { +#endif + +template <> +struct hash<std::tr2::thread_base*> +{ + size_t operator()(const std::tr2::thread_base* __x) const + { return reinterpret_cast<size_t>(__x); } +}; + +#ifdef __USE_STD_TR1 +} +#endif + +} // namespace __HASH_NAMESPACE + + namespace std { namespace tr2 { namespace detail { +#ifdef __USE_STLPORT_HASH +typedef std::hash_set<thread_base*> thread_pool_t; +#endif +#ifdef __USE_STD_HASH +typedef __gnu_cxx::hash_set<thread_base*> thread_pool_t; +#endif +#if defined(__USE_STLPORT_TR1) || defined(__USE_STD_TR1) +typedef std::tr1::unordered_set<thread_base*> thread_pool_t; +#endif + +static mutex thrpool_lock; +static thread_pool_t thread_pool; + int Init_count = 0; // problem: ::getpid() really return cached value, so pid returned may be @@ -141,45 +201,6 @@ return user_words + __idx + 1; } - -void __at_fork_prepare() -{ -#ifdef __FIT_PTHREADS - if ( Init_count > 0 ) { - _uw_save = pthread_getspecific( _mt_key ); - } -#endif -} - -void __at_fork_parent() -{ -} - -void __at_fork_child() -{ -#ifdef __FIT_PTHREADS - if ( Init_count > 0 ) { - // otherwise we do it in Thread::Init::Init() below -# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) - // I am misunderstand this point, Solaris 7 require this (to be restored) - - // pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ); - - // while Linux (and other) inherit this setting from parent process? - // At least Linux glibc 2.2.5 try to made lock in recursive - // call of pthread_atfork -# else -// should be fixed... -# endif // !(__FreeBSD__ || __OpenBSD__) - pthread_key_create( &_mt_key, 0 ); // take new key - pthread_setspecific( _mt_key, _uw_save ); // store preserved user words array - _uw_save = 0; - // Note, that only calling thread inherited when we use POSIX: - Init_count = 1; // i.e. only ONE (calling) thread... - } -#endif -} - } // namespace detail } // namespace tr2 } // namespace std @@ -196,6 +217,7 @@ char *Init_buf[32]; int& thread_base::Init::_count( detail::Init_count ); // trick to avoid friend declarations +bool _at_fork_set = false; const std::string msg1( "Can't create thread" ); const std::string msg2( "Can't fork" ); @@ -213,8 +235,11 @@ if ( _count++ == 0 ) { #ifdef __FIT_PTHREADS # if !(defined(__FreeBSD__) || defined(__OpenBSD__)) - if ( pthread_atfork( detail::__at_fork_prepare, detail::__at_fork_parent, detail::__at_fork_child ) ) { - throw std::runtime_error( "Problems with pthread_atfork" ); + if ( !_at_fork_set ) { // call only once + if ( pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ) ) { + throw std::runtime_error( "Problems with pthread_atfork" ); + } + _at_fork_set = true; } # endif // !(__FreeBSD__ || __OpenBSD__) pthread_key_create( &detail::_mt_key, 0 ); @@ -253,6 +278,73 @@ # endif // !(__FreeBSD__ || __OpenBSD__) #endif // __FIT_UITHREADS || _PTHREADS +void thread_base::Init::__at_fork_prepare() +{ +#ifdef __FIT_PTHREADS + detail::_F_lock.lock(); + detail::thrpool_lock.lock(); + + if ( detail::Init_count > 0 ) { + detail::_uw_save = pthread_getspecific( detail::_mt_key ); + } + + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id != _bad_thread_id ) { + const_cast<thread_base*>(*i)->_id_lock.lock(); + } + } + +#endif +} + +void thread_base::Init::__at_fork_parent() +{ +#ifdef __FIT_PTHREADS + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id != _bad_thread_id ) { + const_cast<thread_base*>(*i)->_id_lock.unlock(); + } + } + + detail::thrpool_lock.unlock(); + detail::_F_lock.unlock(); +#endif +} + +void thread_base::Init::__at_fork_child() +{ +#ifdef __FIT_PTHREADS + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id != _bad_thread_id ) { + const_cast<thread_base*>(*i)->_id_lock.unlock(); + } + } + + detail::thrpool_lock.unlock(); + + if ( detail::Init_count > 0 ) { + // otherwise we do it in Thread::Init::Init() below +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + // I am misunderstand this point, Solaris 7 require this (to be restored) + + // pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ); + + // while Linux (and other) inherit this setting from parent process? + // At least Linux glibc 2.2.5 try to made lock in recursive + // call of pthread_atfork +# else +// should be fixed... +# endif // !(__FreeBSD__ || __OpenBSD__) + pthread_key_create( &detail::_mt_key, 0 ); // take new key + pthread_setspecific( detail::_mt_key, detail::_uw_save ); // store preserved user words array + detail::_uw_save = 0; + // Note, that only calling thread inherited when we use POSIX: + detail::Init_count = 1; // i.e. only ONE (calling) thread... + } + detail::_F_lock.unlock(); +#endif +} + thread_base::id::id() : _id( _bad_thread_id ) { } @@ -262,6 +354,9 @@ _id( _bad_thread_id ) { new( Init_buf ) Init(); + + lock_guard<mutex> lk( detail::thrpool_lock ); + detail::thread_pool.insert( this ); } __FIT_DECLSPEC @@ -269,6 +364,9 @@ { if ( joinable() ) { thread_base::join(); + } else { + lock_guard<mutex> lk( detail::thrpool_lock ); + detail::thread_pool.erase( this ); } ((Init *)Init_buf)->~Init(); @@ -294,6 +392,12 @@ #endif // __FIT_WIN32THREADS #ifdef __FIT_PTHREADS pthread_join( _id, 0 ); + + { + lock_guard<mutex> lk(detail::thrpool_lock); + detail::thread_pool.erase( this ); + } + _id = _bad_thread_id; // lock not required here, only one thread #endif // PTHREADS } @@ -306,14 +410,44 @@ if ( pthread_detach( _id ) ) { // throw system_error; } + { + lock_guard<mutex> lk(detail::thrpool_lock); + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ++i ) { + if ( (*i)->_id == _id ) { + detail::thread_pool.erase( i ); + break; + } + } + } _id = _bad_thread_id; #endif } +pid_t getpid() +{ + return detail::_pid; +} + +pid_t getppid() +{ + return detail::_ppid; +} + +thread_base::id get_id() +{ +#ifdef __FIT_PTHREADS + return thread_base::id( pthread_self() ); +#endif +#ifdef __FIT_WIN32THREADS + return thread_base::id( GetCurrentThread() ); +#endif +} + +__FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ) { #ifdef __unix - // MT_REENTRANT( detail::_F_lock, _1 ); + thread_base::id fthr = this_thread::get_id(); fork_in_parent f( ::fork() ); if ( f.pid() > 0 ) { throw f; @@ -323,15 +457,29 @@ } detail::_ppid = detail::_pid; detail::_pid = syscall( SYS_getpid ); + + // lock not required: it in child and only one thread yet + for ( detail::thread_pool_t::const_iterator i = detail::thread_pool.begin(); i != detail::thread_pool.end(); ) { + if ( (*i)->get_id() != fthr ) { + const_cast<thread_base*>(*i)->_id = _bad_thread_id; + detail::thread_pool.erase( i++ ); + } else { + ++i; + } + } + #endif } +namespace this_thread +{ + __FIT_DECLSPEC void become_daemon() throw( fork_in_parent, std::runtime_error ) { #ifdef __unix try { - std::tr2::fork(); + std::tr2::this_thread::fork(); ::chdir( "/var/tmp" ); // for CWD: if not done, process remain with same WD // and don't allow unmount volume, for example @@ -353,29 +501,6 @@ #endif } -pid_t getpid() -{ - return detail::_pid; -} - -pid_t getppid() -{ - return detail::_ppid; -} - -thread_base::id get_id() -{ -#ifdef __FIT_PTHREADS - return thread_base::id( pthread_self() ); -#endif -#ifdef __FIT_WIN32THREADS - return thread_base::id( GetCurrentThread() ); -#endif -} - -namespace this_thread -{ - #if 0 std::thread_base::id get_id() { Modified: branches/complement-sockios/explore/lib/mt/ut/Makefile.inc =================================================================== --- branches/complement-sockios/explore/lib/mt/ut/Makefile.inc 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/lib/mt/ut/Makefile.inc 2008-03-26 10:57:21 UTC (rev 1834) @@ -1,7 +1,7 @@ -# -*- makefile -*- Time-stamp: <08/02/15 22:36:40 ptr> +# -*- makefile -*- Time-stamp: <08/03/26 10:12:36 ptr> PRGNAME = mt_ut SRC_CC = unit_test.cc timespec.cc \ signal-1.cc signal-3.cc \ - mt_test.cc mt_test_suite.cc \ + mt_test.cc shm_test.cc mt_test_suite.cc \ mt_test_wg21.cc Modified: branches/complement-sockios/explore/lib/mt/ut/mt_test.cc =================================================================== --- branches/complement-sockios/explore/lib/mt/ut/mt_test.cc 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/lib/mt/ut/mt_test.cc 2008-03-26 10:57:21 UTC (rev 1834) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/09/14 22:10:35 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:09:40 ptr> /* * Copyright (c) 2006, 2007 @@ -516,454 +516,7 @@ return EXAM_RESULT; } -/* ****************************************************** */ - -int EXAM_IMPL(shm_test::shm_segment) -{ - const char fname[] = "/tmp/mt_test.shm"; - try { - xmt::detail::__shm_alloc<0> seg( 5000, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - - EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); - seg.deallocate(); - EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); - - EXAM_REQUIRE( !fs::exists( fname ) ); - - seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); - seg.deallocate(); - EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); - EXAM_CHECK( fs::exists( fname ) ); // well, now I don't remove ref file, because shm segment may be created with another way - - // not exclusive, should pass - seg.allocate( fname, 1024, xmt::shm_base::create, 0660 ); - EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); - try { - // This instance has segment in usage, should throw - seg.allocate( fname, 1024, 0, 0660 ); - EXAM_CHECK( false ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_CHECK( true ); // Ok - } - - /* - - I will treat another instanse (<1>) as interface to another - segment, so this sample not work. - - try { - // But this is another instanse, it's ok: - xmt::detail::__shm_alloc<1> seg1( fname, 1024, 0, 0660 ); - BOOST_CHECK( seg1.address() != reinterpret_cast<void *>(-1) ); - // Don't call seg1.deallocate() here, it destroy - } - catch ( xmt::shm_bad_alloc& err ) { - BOOST_CHECK( false ); // Fail - } - */ - - seg.deallocate(); - EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); - - // ---- - try { - // exclusive, should throw - seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - EXAM_CHECK( false ); // Fail, should throw - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_CHECK( true ); // Ok - } - EXAM_CHECK( fs::exists( fname ) ); - // ---- - - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** */ - -int EXAM_IMPL(shm_test::shm_alloc) -{ - const char fname[] = "/tmp/mt_test.shm"; - try { - xmt::shm_alloc<0> seg; - - seg.allocate( fname, 7000, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - - { - xmt::allocator_shm<char,0> shmall; - size_t sz = shmall.max_size(); - // two blocks - char *ch1 = shmall.allocate( 3500 ); - EXAM_CHECK( ch1 != 0 ); - char *ch2 = shmall.allocate( 3500 ); - EXAM_CHECK( ch2 != 0 ); - try { - // try to allocate third block, not enough room - char *ch3 = shmall.allocate( 8 * 1024 - 7000 ); - EXAM_CHECK( false ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_CHECK( true ); - } - // free first blocks - shmall.deallocate( ch1, 3500 ); - ch1 = shmall.allocate( 3500 ); - // allocate [first] block again - EXAM_CHECK( ch1 != 0 ); - // free second block - shmall.deallocate( ch2, 3500 ); - // allocate [second] block again - ch2 = shmall.allocate( 3500 ); - EXAM_CHECK( ch2 != 0 ); - // free both blocks - shmall.deallocate( ch1, 3500 ); - shmall.deallocate( ch2, 3500 ); - // allocate big block, enough for initial memory chunk - ch1 = shmall.allocate( 7000 ); - EXAM_CHECK( ch1 != 0 ); - // free it - shmall.deallocate( ch1, 7000 ); - // allocate block of maximum size - ch1 = shmall.allocate( sz ); - EXAM_CHECK( ch1 != 0 ); - // free it - shmall.deallocate( ch1, sz ); - // allocate block, enough for initial memory chunk - ch1 = shmall.allocate( 7000 ); - EXAM_CHECK( ch1 != 0 ); - // free it - shmall.deallocate( ch1, 7000 ); - ch1 = shmall.allocate( 3000 ); - EXAM_CHECK( ch1 != 0 ); - ch2 = shmall.allocate( 400 ); - EXAM_CHECK( ch2 != 0 ); - char *ch3 = shmall.allocate( 3500 ); - EXAM_CHECK( ch3 != 0 ); - shmall.deallocate( ch1, 3000 ); - shmall.deallocate( ch2, 400 ); - shmall.deallocate( ch3, 3500 ); - ch1 = shmall.allocate( sz ); - EXAM_CHECK( ch1 != 0 ); - shmall.deallocate( ch1, sz ); - } - seg.deallocate(); - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - - /* ****************************************************** - * This test is similar mt_test::fork() above, but instead plain shm_* - * functions it use allocator based on shared memory segment - */ -int EXAM_IMPL(shm_test::fork_shm) -{ - const char fname[] = "/tmp/mt_test.shm"; - try { - xmt::shm_alloc<0> seg; - - seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - xmt::allocator_shm<char,0> shm; - - xmt::__condition<true>& fcnd = *new( shm.allocate( sizeof(xmt::__condition<true>) ) ) xmt::__condition<true>(); - fcnd.set( false ); - try { - xmt::fork(); - - try { - - // Child code - fcnd.try_wait(); - - } - catch ( ... ) { - } - - exit( 0 ); - } - catch ( xmt::fork_in_parent& child ) { - try { - EXAM_CHECK( child.pid() > 0 ); - - fcnd.set( true ); - - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - catch ( ... ) { - } - } - catch ( ... ) { - } - - (&fcnd)->~__condition<true>(); - shm.deallocate( reinterpret_cast<char *>(&fcnd), sizeof(xmt::__condition<true>) ); - seg.deallocate(); - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** - * Test: how to take named object in shared memory segment - */ -int EXAM_IMPL(shm_test::shm_named_obj) -{ - const char fname[] = "/tmp/mt_test.shm"; - enum { - test_Condition_Object = 1 - }; - try { - xmt::shm_alloc<0> seg; - - seg.allocate( fname, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - xmt::shm_name_mgr<0>& nm = seg.name_mgr(); - - xmt::allocator_shm<xmt::__condition<true>,0> shm; - - xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); - nm.named( fcnd, test_Condition_Object ); - fcnd.set( false ); - - try { - xmt::fork(); - - int eflag = 0; - - try { - - // Child code - xmt::shm_alloc<0> seg_ch; - - if ( seg_ch.max_size() == 0 ) { // just illustration, if seg and seg_ch - // (really xmt::shm_alloc<0>) - // in totally different address spaces - // in our case xmt::shm_name_mgr<0> instance derived from parent - // process - seg.allocate( fname, 4*4096, 0, 0660 ); - } - - xmt::shm_name_mgr<0>& nm_ch = seg_ch.name_mgr(); - xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( test_Condition_Object ); - fcnd_ch.set( true ); - } - catch ( const xmt::shm_bad_alloc& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - catch ( ... ) { - EXAM_ERROR_ASYNC_F( "Fail in child", eflag ); - } - - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - try { - EXAM_CHECK( child.pid() > 0 ); - - fcnd.try_wait(); - - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - catch ( ... ) { - EXAM_ERROR( "Fail in parent" ); - } - } - catch ( ... ) { - EXAM_ERROR( "Fail in fork" ); - } - - (&fcnd)->~__condition<true>(); - shm.deallocate( &fcnd, 1 ); - seg.deallocate(); - fs::remove( fname ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** - */ -const char shm_test::fname1[] = "/tmp/mt_test.shm.1"; - -shm_test::shm_test() -{ - try { - seg1.allocate( fname1, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR_ASYNC( err.what() ); - } -} - -/* ****************************************************** - */ -shm_test::~shm_test() -{ - seg1.deallocate(); - fs::remove( fname1 ); -} - -/* ****************************************************** - */ - -int EXAM_IMPL(shm_test::shm_named_obj_more) -{ - enum { - ObjName = 1 - }; - - try { - xmt::shm_name_mgr<1>& nm = seg1.name_mgr(); - - xmt::allocator_shm<xmt::__condition<true>,1> shm; - - xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); - nm.named( fcnd, ObjName ); - fcnd.set( false ); - - try { - xmt::fork(); - - int eflag = 0; - - try { - xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); - xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; - xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); - fcnd_ch.set( true ); - nm_ch.release<xmt::__condition<true> >( ObjName ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - fcnd.try_wait(); - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here - - xmt::__condition<true>& fcnd1 = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); - nm.named( fcnd1, ObjName ); // ObjName should be free here - fcnd1.set( false ); - - try { - xmt::fork(); - - int eflag = 0; - - try { - xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); - xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; - xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); - fcnd_ch.set( true ); - nm_ch.release<xmt::__condition<true> >( ObjName ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - fcnd1.try_wait(); - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here - - xmt::allocator_shm<xmt::__barrier<true>,1> shm_b; - xmt::__barrier<true>& b = *new ( shm_b.allocate( 1 ) ) xmt::__barrier<true>(); - - nm.named( b, ObjName ); // ObjName should be free here - - try { - xmt::fork(); - - int eflag = 0; - try { - xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); - xmt::allocator_shm<xmt::__barrier<true>,1> shm_ch; - xmt::__barrier<true>& b_ch = nm_ch.named<xmt::__barrier<true> >( ObjName ); - b_ch.wait(); - nm_ch.release<xmt::__barrier<true> >( ObjName ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR_ASYNC_F( err.what(), eflag ); - } - - exit( eflag ); - } - catch ( xmt::fork_in_parent& child ) { - b.wait(); - int stat = -1; - EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); - if ( WIFEXITED(stat) ) { - EXAM_CHECK( WEXITSTATUS(stat) == 0 ); - } else { - EXAM_ERROR( "child interrupted" ); - } - } - nm.release<xmt::__barrier<true> >( ObjName ); // barrier should be destroyed here - } - catch ( xmt::shm_bad_alloc& err ) { - EXAM_ERROR( err.what() ); - } - catch ( const std::invalid_argument& err ) { - EXAM_ERROR( err.what() ); - } - - return EXAM_RESULT; -} - -/* ****************************************************** * Thread pool (aka ThreadMgr) test. * * Start 200 threads under ThreadMgr; check that all threads Modified: branches/complement-sockios/explore/lib/mt/ut/mt_test.h =================================================================== --- branches/complement-sockios/explore/lib/mt/ut/mt_test.h 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/lib/mt/ut/mt_test.h 2008-03-26 10:57:21 UTC (rev 1834) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/05 00:02:19 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:08:36 ptr> /* - * Copyright (c) 2006, 2007 + * Copyright (c) 2006-2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -37,22 +37,4 @@ // static int x; }; -class shm_test -{ - public: - shm_test(); - ~shm_test(); - - int EXAM_DECL(shm_segment); - int EXAM_DECL(shm_alloc); - int EXAM_DECL(fork_shm); - int EXAM_DECL(shm_named_obj); - - int EXAM_DECL(shm_named_obj_more); - - private: - xmt::shm_alloc<1> seg1; - static const char fname1[]; -}; - #endif // __MT_TEST_H Modified: branches/complement-sockios/explore/lib/mt/ut/mt_test_suite.cc =================================================================== --- branches/complement-sockios/explore/lib/mt/ut/mt_test_suite.cc 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/lib/mt/ut/mt_test_suite.cc 2008-03-26 10:57:21 UTC (rev 1834) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 12:17:54 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 10:12:21 ptr> /* * Copyright (c) 2006-2008 @@ -10,6 +10,7 @@ #include "mt_test_suite.h" #include "mt_test.h" +#include "shm_test.h" #include "mt_test_wg21.h" #include <config/feature.h> @@ -41,7 +42,6 @@ exam::test_suite::test_case_type tc[3]; // t.add( &mt_test::callstack, test, "callstack" ); - tc[0] = t.add( &mt_test::barrier, test, "mt_test::barrier" ); tc[1] = t.add( &mt_test::join_test, test, "mt_test::join_test" ); tc[2] = t.add( &mt_test::yield, test, "mt_test::yield", @@ -74,6 +74,7 @@ t.add( &mt_test_wg21::mutex_test, test_wg21, "mt_test_wg21::mutex_test" ); t.add( &mt_test_wg21::barrier, test_wg21, "mt_test_wg21::barrier" ); t.add( &mt_test_wg21::semaphore, test_wg21, "mt_test_wg21::semaphore" ); + t.add( &mt_test_wg21::fork, test_wg21, "mt_test_wg21::fork" ); return t.girdle(); }; Modified: branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.cc =================================================================== --- branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.cc 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.cc 2008-03-26 10:57:21 UTC (rev 1834) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 13:01:59 ptr> +// -*- C++ -*- Time-stamp: <08/03/26 01:53:46 ptr> /* * Copyright (c) 2006-2008 @@ -19,6 +19,10 @@ #include <iostream> +#include <sys/wait.h> +#include <sys/ipc.h> +#include <sys/shm.h> + int EXAM_IMPL(mt_test_wg21::date_time) { // using namespace std::tr2; @@ -202,3 +206,111 @@ return EXAM_RESULT; } + +int EXAM_IMPL(mt_test_wg21::fork) +{ + // trivial fork + + int v = 3; + try { + std::tr2::this_thread::fork(); + + try { + + // Child code + EXAM_CHECK_ASYNC( v == 3 ); + + v = 5; + } + catch ( ... ) { + } + + exit( 0 ); + } + catch ( std::tr2::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + EXAM_CHECK( v == 3 ); + } + catch ( ... ) { + } + } + catch ( ... ) { + } + + + // less trivial fork: check interprocess communication via shared memory + + shmid_ds ds; + int id = shmget( 5000, 1024, IPC_CREAT | IPC_EXCL | 0600 ); + EXAM_REQUIRE( id != -1 ); + // if ( id == -1 ) { + // cerr << "Error on shmget" << endl; + // } + EXAM_REQUIRE( shmctl( id, IPC_STAT, &ds ) != -1 ); + // if ( shmctl( id, IPC_STAT, &ds ) == -1 ) { + // cerr << "Error on shmctl" << endl; + // } + void *buf = shmat( id, 0, 0 ); + EXAM_REQUIRE( buf != reinterpret_cast<void *>(-1) ); + // if ( buf == reinterpret_cast<void *>(-1) ) { + // cerr << "Error on shmat" << endl; + // } + + int& x = *new( buf ) int(4); + + EXAM_CHECK( x == 4 ); + + try { + std::tr2::this_thread::fork(); + + try { + + // Child code + EXAM_CHECK_ASYNC( v == 3 ); + + v = 5; + + EXAM_CHECK_ASYNC( x == 4 ); + + x = 6; + } + catch ( ... ) { + } + + exit( 0 ); + } + catch ( std::tr2::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + EXAM_CHECK( v == 3 ); + EXAM_CHECK( x == 6 ); + } + catch ( ... ) { + } + } + catch ( ... ) { + } + + shmdt( buf ); + shmctl( id, IPC_RMID, &ds ); + + return EXAM_RESULT; +} + Modified: branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.h =================================================================== --- branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.h 2008-03-11 15:03:22 UTC (rev 1833) +++ branches/complement-sockios/explore/lib/mt/ut/mt_test_wg21.h 2008-03-26 10:57:21 UTC (rev 1834) @@ -24,6 +24,7 @@ int EXAM_DECL(mutex_test); int EXAM_DECL(barrier); int EXAM_DECL(semaphore); + int EXAM_DECL(fork); private: // static xmt::Thread::ret_t thread_entry_call( void * ); Copied: branches/complement-sockios/explore/lib/mt/ut/shm_test.cc (from rev 1832, branches/complement-sockios/explore/lib/mt/ut/mt_test.cc) =================================================================== --- branches/complement-sockios/explore/lib/mt/ut/shm_test.cc (rev 0) +++ branches/complement-sockios/explore/lib/mt/ut/shm_test.cc 2008-03-26 10:57:21 UTC (rev 1834) @@ -0,0 +1,474 @@ +// -*- C++ -*- Time-stamp: <08/03/26 10:11:58 ptr> + +/* + * Copyright (c) 2006, 2007 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License Version 3.0 + * + */ + +#include "shm_test.h" + +#include <mt/xmt.h> +#include <mt/shm.h> + + +#include <sys/shm.h> +#include <sys/wait.h> + +#include <signal.h> + +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> + +#include <iostream> + +using namespace std; +namespace fs = boost::filesystem; + +int EXAM_IMPL(shm_test::shm_segment) +{ + const char fname[] = "/tmp/mt_test.shm"; + try { + xmt::detail::__shm_alloc<0> seg( 5000, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + + EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); + seg.deallocate(); + EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); + + EXAM_REQUIRE( !fs::exists( fname ) ); + + seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); + seg.deallocate(); + EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); + EXAM_CHECK( fs::exists( fname ) ); // well, now I don't remove ref file, because shm segment may be created with another way + + // not exclusive, should pass + seg.allocate( fname, 1024, xmt::shm_base::create, 0660 ); + EXAM_CHECK( seg.address() != reinterpret_cast<void *>(-1) ); + try { + // This instance has segment in usage, should throw + seg.allocate( fname, 1024, 0, 0660 ); + EXAM_CHECK( false ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_CHECK( true ); // Ok + } + + /* + + I will treat another instanse (<1>) as interface to another + segment, so this sample not work. + + try { + // But this is another instanse, it's ok: + xmt::detail::__shm_alloc<1> seg1( fname, 1024, 0, 0660 ); + BOOST_CHECK( seg1.address() != reinterpret_cast<void *>(-1) ); + // Don't call seg1.deallocate() here, it destroy + } + catch ( xmt::shm_bad_alloc& err ) { + BOOST_CHECK( false ); // Fail + } + */ + + seg.deallocate(); + EXAM_CHECK( seg.address() == reinterpret_cast<void *>(-1) ); + + // ---- + try { + // exclusive, should throw + seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + EXAM_CHECK( false ); // Fail, should throw + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_CHECK( true ); // Ok + } + EXAM_CHECK( fs::exists( fname ) ); + // ---- + + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + +/* ****************************************************** */ + +int EXAM_IMPL(shm_test::shm_alloc) +{ + const char fname[] = "/tmp/mt_test.shm"; + try { + xmt::shm_alloc<0> seg; + + seg.allocate( fname, 7000, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + + { + xmt::allocator_shm<char,0> shmall; + size_t sz = shmall.max_size(); + // two blocks + char *ch1 = shmall.allocate( 3500 ); + EXAM_CHECK( ch1 != 0 ); + char *ch2 = shmall.allocate( 3500 ); + EXAM_CHECK( ch2 != 0 ); + try { + // try to allocate third block, not enough room + char *ch3 = shmall.allocate( 8 * 1024 - 7000 ); + EXAM_CHECK( false ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_CHECK( true ); + } + // free first blocks + shmall.deallocate( ch1, 3500 ); + ch1 = shmall.allocate( 3500 ); + // allocate [first] block again + EXAM_CHECK( ch1 != 0 ); + // free second block + shmall.deallocate( ch2, 3500 ); + // allocate [second] block again + ch2 = shmall.allocate( 3500 ); + EXAM_CHECK( ch2 != 0 ); + // free both blocks + shmall.deallocate( ch1, 3500 ); + shmall.deallocate( ch2, 3500 ); + // allocate big block, enough for initial memory chunk + ch1 = shmall.allocate( 7000 ); + EXAM_CHECK( ch1 != 0 ); + // free it + shmall.deallocate( ch1, 7000 ); + // allocate block of maximum size + ch1 = shmall.allocate( sz ); + EXAM_CHECK( ch1 != 0 ); + // free it + shmall.deallocate( ch1, sz ); + // allocate block, enough for initial memory chunk + ch1 = shmall.allocate( 7000 ); + EXAM_CHECK( ch1 != 0 ); + // free it + shmall.deallocate( ch1, 7000 ); + ch1 = shmall.allocate( 3000 ); + EXAM_CHECK( ch1 != 0 ); + ch2 = shmall.allocate( 400 ); + EXAM_CHECK( ch2 != 0 ); + char *ch3 = shmall.allocate( 3500 ); + EXAM_CHECK( ch3 != 0 ); + shmall.deallocate( ch1, 3000 ); + shmall.deallocate( ch2, 400 ); + shmall.deallocate( ch3, 3500 ); + ch1 = shmall.allocate( sz ); + EXAM_CHECK( ch1 != 0 ); + shmall.deallocate( ch1, sz ); + } + seg.deallocate(); + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + + +/* ****************************************************** + * This test is similar mt_test::fork() above, but instead plain shm_* + * functions it use allocator based on shared memory segment + */ +int EXAM_IMPL(shm_test::fork_shm) +{ + const char fname[] = "/tmp/mt_test.shm"; + try { + xmt::shm_alloc<0> seg; + + seg.allocate( fname, 1024, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + xmt::allocator_shm<char,0> shm; + + xmt::__condition<true>& fcnd = *new( shm.allocate( sizeof(xmt::__condition<true>) ) ) xmt::__condition<true>(); + fcnd.set( false ); + try { + xmt::fork(); + + try { + + // Child code + fcnd.try_wait(); + + } + catch ( ... ) { + } + + exit( 0 ); + } + catch ( xmt::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + fcnd.set( true ); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + catch ( ... ) { + } + } + catch ( ... ) { + } + + (&fcnd)->~__condition<true>(); + shm.deallocate( reinterpret_cast<char *>(&fcnd), sizeof(xmt::__condition<true>) ); + seg.deallocate(); + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + +/* ****************************************************** + * Test: how to take named object in shared memory segment + */ +int EXAM_IMPL(shm_test::shm_named_obj) +{ + const char fname[] = "/tmp/mt_test.shm"; + enum { + test_Condition_Object = 1 + }; + try { + xmt::shm_alloc<0> seg; + + seg.allocate( fname, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + xmt::shm_name_mgr<0>& nm = seg.name_mgr(); + + xmt::allocator_shm<xmt::__condition<true>,0> shm; + + xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); + nm.named( fcnd, test_Condition_Object ); + fcnd.set( false ); + + try { + xmt::fork(); + + int eflag = 0; + + try { + + // Child code + xmt::shm_alloc<0> seg_ch; + + if ( seg_ch.max_size() == 0 ) { // just illustration, if seg and seg_ch + // (really xmt::shm_alloc<0>) + // in totally different address spaces + // in our case xmt::shm_name_mgr<0> instance derived from parent + // process + seg.allocate( fname, 4*4096, 0, 0660 ); + } + + xmt::shm_name_mgr<0>& nm_ch = seg_ch.name_mgr(); + xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( test_Condition_Object ); + fcnd_ch.set( true ); + } + catch ( const xmt::shm_bad_alloc& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + catch ( ... ) { + EXAM_ERROR_ASYNC_F( "Fail in child", eflag ); + } + + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + try { + EXAM_CHECK( child.pid() > 0 ); + + fcnd.try_wait(); + + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + catch ( ... ) { + EXAM_ERROR( "Fail in parent" ); + } + } + catch ( ... ) { + EXAM_ERROR( "Fail in fork" ); + } + + (&fcnd)->~__condition<true>(); + shm.deallocate( &fcnd, 1 ); + seg.deallocate(); + fs::remove( fname ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + +/* ****************************************************** + */ +const char shm_test::fname1[] = "/tmp/mt_test.shm.1"; + +shm_test::shm_test() +{ + try { + seg1.allocate( fname1, 4*4096, xmt::shm_base::create | xmt::shm_base::exclusive, 0660 ); + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR_ASYNC( err.what() ); + } +} + +/* ****************************************************** + */ +shm_test::~shm_test() +{ + seg1.deallocate(); + fs::remove( fname1 ); +} + +/* ****************************************************** + */ + +int EXAM_IMPL(shm_test::shm_named_obj_more) +{ + enum { + ObjName = 1 + }; + + try { + xmt::shm_name_mgr<1>& nm = seg1.name_mgr(); + + xmt::allocator_shm<xmt::__condition<true>,1> shm; + + xmt::__condition<true>& fcnd = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); + nm.named( fcnd, ObjName ); + fcnd.set( false ); + + try { + xmt::fork(); + + int eflag = 0; + + try { + xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); + xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; + xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); + fcnd_ch.set( true ); + nm_ch.release<xmt::__condition<true> >( ObjName ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + fcnd.try_wait(); + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here + + xmt::__condition<true>& fcnd1 = *new ( shm.allocate( 1 ) ) xmt::__condition<true>(); + nm.named( fcnd1, ObjName ); // ObjName should be free here + fcnd1.set( false ); + + try { + xmt::fork(); + + int eflag = 0; + + try { + xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); + xmt::allocator_shm<xmt::__condition<true>,1> shm_ch; + xmt::__condition<true>& fcnd_ch = nm_ch.named<xmt::__condition<true> >( ObjName ); + fcnd_ch.set( true ); + nm_ch.release<xmt::__condition<true> >( ObjName ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + fcnd1.try_wait(); + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + nm.release<xmt::__condition<true> >( ObjName ); // fcnd should be destroyed here + + xmt::allocator_shm<xmt::__barrier<true>,1> shm_b; + xmt::__barrier<true>& b = *new ( shm_b.allocate( 1 ) ) xmt::__barrier<true>(); + + nm.named( b, ObjName ); // ObjName should be free here + + try { + xmt::fork(); + + int eflag = 0; + try { + xmt::shm_name_mgr<1>& nm_ch = seg1.name_mgr(); + xmt::allocator_shm<xmt::__barrier<true>,1> shm_ch; + xmt::__barrier<true>& b_ch = nm_ch.named<xmt::__barrier<true> >( ObjName ); + b_ch.wait(); + nm_ch.release<xmt::__barrier<true> >( ObjName ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR_ASYNC_F( err.what(), eflag ); + } + + exit( eflag ); + } + catch ( xmt::fork_in_parent& child ) { + b.wait(); + int stat = -1; + EXAM_CHECK( waitpid( child.pid(), &stat, 0 ) == child.pid() ); + if ( WIFEXITED(stat) ) { + EXAM_CHECK( WEXITSTATUS(stat) == 0 ); + } else { + EXAM_ERROR( "child interrupted" ); + } + } + nm.release<xmt::__barrier<true> >( ObjName ); // barrier should be destroyed here + } + catch ( xmt::shm_bad_alloc& err ) { + EXAM_ERROR( err.what() ); + } + catch ( const std::invalid_argument& err ) { + EXAM_ERROR( err.what() ); + } + + return EXAM_RESULT; +} + Copied: branches/complement-sockios/explore/lib/mt/ut/shm_test.h (from rev 1832, branches/complement-sockios/explore/lib/mt/ut/mt_test.h) =================================================================== --- branches/complement-sockios/explore/lib/mt/ut/shm_test.h (rev 0) +++ branches/complement-sockios/explore/lib/mt/ut/shm_test.h 2008-03-26 10:57:21 UTC (rev 1834) @@ -0,0 +1,37 @@ +// -*- C++ -*- Time-stamp: <08/03/26 10:10:18 ptr> + +/* + * Copyright (c) 2006, 2007 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License Version 3.0 + * + */ + +#ifndef __SHM_TEST_H +#define __SHM_TEST_H + +#define FIT_EXAM + +#include <exam/suite.h> +#include <mt/shm.h> + +class shm_test +{ + public: + shm_test(); + ~shm_test(); + + int EXAM_DECL(shm_segment); + int EXAM_DECL(shm_alloc); + int EXAM_DECL(fork_shm); + int EXAM_DECL(shm_named_obj); + + int EXAM_DECL(shm_named_obj_more); + + private: + xmt::shm_alloc<1> seg1; + static const char fname1[]; +}; + +#endif // __SHM_TEST_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-03-11 15:03:58
|
Revision: 1833 http://complement.svn.sourceforge.net/complement/?rev=1833&view=rev Author: complement Date: 2008-03-11 08:03:22 -0700 (Tue, 11 Mar 2008) Log Message: ----------- core implementation of new sockstream, that based on epoll and has uniform sockets management Modified Paths: -------------- branches/complement-sockios/explore/lib/sockios/Makefile.inc branches/complement-sockios/explore/lib/sockios/ut/Makefile.inc branches/complement-sockios/explore/lib/sockios/ut/sockios_test_suite.cc Added Paths: ----------- branches/complement-sockios/explore/include/sockios/sockstream2 branches/complement-sockios/explore/include/sockios/sockstream2.cc branches/complement-sockios/explore/include/sockios/sp.h branches/complement-sockios/explore/lib/sockios/_sp.cc branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.cc branches/complement-sockios/explore/lib/sockios/ut/sockios2_test.h Copied: branches/complement-sockios/explore/include/sockios/sockstream2 (from rev 1828, branches/complement-sockios/explore/include/sockios/sockstream) =================================================================== --- branches/complement-sockios/explore/include/sockios/sockstream2 (rev 0) +++ branches/complement-sockios/explore/include/sockios/sockstream2 2008-03-11 15:03:22 UTC (rev 1833) @@ -0,0 +1,766 @@ +// -*- C++ -*- Time-stamp: <08/03/07 01:16:27 ptr> + +/* + * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + */ + +#ifndef __SOCKIOS_SOCKSTREAM2 +#define __SOCKIOS_SOCKSTREAM2 + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#if !defined(__sun) && !defined(_WIN32) // i.e. __linux and __hpux +#include <sys/poll.h> // pollfd +#endif + +#include <mt/mutex> +#include <mt/condition_variable> +#include <mt/date_time> + +#include <netdb.h> +#include <netinet/in.h> + +#include <iosfwd> +#include <ios> +#include <streambuf> +#include <iostream> +#include <string> +#include <stdexcept> + +#ifdef WIN32 +# include <winsock2.h> +#else // WIN32 +# include <unistd.h> +# include <sys/types.h> +# if defined(__hpux) && !defined(_INCLUDE_XOPEN_SOURCE_EXTENDED) +# define _INCLUDE_XOPEN_SOURCE_EXTENDED +# endif +# include <sys/socket.h> +# if !defined(__UCLIBC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) +# include <stropts.h> +# endif +# ifdef __sun +# include <sys/conf.h> +# endif +# include <netinet/in.h> +# include <arpa/inet.h> +# include <netdb.h> +# ifdef __hpux +// # ifndef socklen_t // HP-UX 10.01 +// typedef int socklen_t; +// # endif +# endif +# include <cerrno> +#endif // !WIN32 + +#include <sockios/netinfo.h> + +#ifdef STLPORT +_STLP_BEGIN_NAMESPACE +#else +namespace std { +#endif + +class sock_base2 +{ + public: + typedef unsigned long shutdownflg; +#ifdef __unix + typedef int socket_type; +#endif +#ifdef WIN32 + typedef SOCKET socket_type; +#endif + + enum stype { + sock_stream = SOCK_STREAM, // stream socket + sock_dgram = SOCK_DGRAM, // datagram socket + sock_raw = SOCK_RAW, // raw-protocol interface + sock_rdm = SOCK_RDM, // reliably-delivered message + sock_seqpacket = SOCK_SEQPACKET // sequenced packet stream + }; + + enum protocol { + local, // local to host (pipes, portals) + inet // internetwork: UDP, TCP, etc. + }; + + // Option flags per-socket. + enum so_t { + so_debug = SO_DEBUG, // turn on debugging info recording +#ifndef __linux + so_acceptconn = SO_ACCEPTCONN, // socket has had listen() +#endif + so_reuseaddr = SO_REUSEADDR, // allow local address reuse + so_keepalive = SO_KEEPALIVE, // keep connections alive + so_dontroute = SO_DONTROUTE, // just use interface addresses + so_broadcast = SO_BROADCAST, // permit sending of broadcast msgs +#ifndef __linux + so_useloopback = SO_USELOOPBACK, // bypass hardware when possible +#endif + so_linger = SO_LINGER, // linger on close if data present + so_oobinline = SO_OOBINLINE, // leave received OOB data in line + // Additional options, not kept in so_options. + so_sndbuf = SO_SNDBUF, // send buffer size + so_rcvbuf = SO_RCVBUF, // receive buffer size + so_sndlowat = SO_SNDLOWAT, // send low-water mark + so_rcvlowat = SO_RCVLOWAT, // receive low-water mark + so_sndtimeo = SO_SNDTIMEO, // send timeout + so_rcvtimeo = SO_RCVTIMEO, // receive timeout + so_error = SO_ERROR, // get error status and clear + so_type = SO_TYPE // get socket type +#ifdef __sun // indeed HP-UX 11.00 also has it, but 10.01 not + , + so_prototype = SO_PROTOTYPE // get/set protocol type +#endif + }; + + // Level number for (get/set)sockopt() to apply to socket itself. +// enum _level { +// sol_socket = SOL_SOCKET +// }; + + enum shutdownflags { + stop_in = 0x1, + stop_out = 0x2 + }; + +#ifdef WIN32 + class Init + { + // sometimes I need Init outside sock_base... + // private: + public: + __FIT_DECLSPEC Init(); + __FIT_DECLSPEC ~Init(); + + friend class sock_base; + }; + + protected: + __FIT_DECLSPEC sock_base(); + __FIT_DECLSPEC ~sock_base(); +#endif +}; + +class socket_timeout : + public std::exception +{ + public: + socket_timeout() + { } + + virtual char const *what() throw() + { return "socket timeout"; } +}; + +class socket_read_timeout : + public socket_timeout +{ + public: + socket_read_timeout() + { } + + virtual char const *what() throw() + { return "socket read timeout"; } +}; + +class socket_write_timeout : + public socket_timeout +{ + public: + socket_write_timeout() + { } + + virtual char const *what() throw() + { return "socket write timeout"; } +}; + +namespace detail { +template <class charT, class traits, class _Alloc> class sockmgr; +} // namespace detail + +template<class charT, class traits, class _Alloc> +class basic_socket +{ + protected: + basic_socket() : + _fd( -1 ), + _use_rdtimeout( false ), + _use_wrtimeout( false ), + _notify_close( false ) + { new( Init_buf ) Init(); } + + ~basic_socket() + { ((Init *)Init_buf)->~Init(); } + + bool is_open_unsafe() const + { return _fd != -1; } + sock_base2::socket_type fd_unsafe() const + { return _fd; } + + class Init + { + public: + Init() + { _guard( 1 ); } + ~Init() + { _guard( 0 ); } + + private: + static void _guard( int direction ); + static void __at_fork_prepare(); + static void __at_fork_child(); + static void __at_fork_parent(); + static int _count; + }; + + static char Init_buf[]; + + public: +#ifdef WIN32 + typedef u_short family_type; +#else +# ifdef sa_family_t + typedef sa_family_t family_type; +# else // HP-UX 10.01 + typedef unsigned short family_type; +# endif +#endif + + template <class Duration> + void rdtimeout( const Duration& ); + void rdtimeout() // infinite + { _use_rdtimeout = false; } + + template <class Duration> + void wrtimeout( const Duration& ); + void wrtimeout() // infinite + { _use_wrtimeout = false; } + + sock_base2::socket_type fd() const { return _fd;} + bool is_open() const + { return _fd != -1; } + + family_type family() const + { return /* is_open() ? */ _address.any.sa_family /* : 0 */; } + + int port() const + { return /* is_open() && */ _address.any.sa_family == AF_INET ? _address.inet.sin_port : 0; } + + unsigned long inet_addr() const + { return /* is_open() && */ _address.any.sa_family == AF_INET ? _address.inet.sin_addr.s_addr : 0; } + + const sockaddr_in& inet_sockaddr() const throw( std::domain_error ) + { + if ( _address.any.sa_family != AF_INET ) { + throw domain_error( "socket not belongs to inet type" ); + } + return /* is_open() && */ _address.inet; + } + + protected: + sock_base2::socket_type _fd; + + union sockaddr_t { + sockaddr_in inet; + sockaddr any; + } _address; + + std::tr2::milliseconds _rdtimeout; + std::tr2::milliseconds _wrtimeout; + bool _use_rdtimeout; + bool _use_wrtimeout; + bool _notify_close; + + static detail::sockmgr<charT,traits,_Alloc>* mgr; + friend class Init; +}; + +template<class charT, class traits, class _Alloc> +int basic_socket<charT,traits,_Alloc>::Init::_count = 0; + +template<class charT, class traits, class _Alloc> +void basic_socket<charT,traits,_Alloc>::Init::_guard( int direction ) +{ + static std::tr2::mutex _init_lock; + + if ( direction ) { + std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); + if ( _count++ == 0 ) { + basic_socket<charT,traits,_Alloc>::mgr = new detail::sockmgr<charT,traits,_Alloc>(); +// #ifdef __FIT__PTHREADS +// pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ); +// #endif +// _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); + } + } else { + std::tr2::lock_guard<std::tr2::mutex> lk( _init_lock ); + if ( --_count == 0 ) { + delete basic_socket<charT,traits,_Alloc>::mgr; + } + } +} + +template<class charT, class traits, class _Alloc> +void basic_socket<charT,traits,_Alloc>::Init::__at_fork_prepare() +{ } + +template<class charT, class traits, class _Alloc> +void basic_socket<charT,traits,_Alloc>::Init::__at_fork_child() +{ + if ( _count != 0 ) { + // stop mgr + delete basic_socket<charT,traits,_Alloc>::mgr; + basic_socket<charT,traits,_Alloc>::mgr = new detail::sockmgr<charT,traits,_Alloc>(); + } + // _sock_processor_base::_idx = std::tr2::this_thread::xalloc(); +} + +template<class charT, class traits, class _Alloc> +void basic_socket<charT,traits,_Alloc>::Init::__at_fork_parent() +{ } + +template<class charT, class traits, class _Alloc> +char basic_socket<charT,traits,_Alloc>::Init_buf[128]; + +template <class charT, class traits, class _Alloc> +detail::sockmgr<charT,traits,_Alloc>* basic_socket<charT,traits,_Alloc>::mgr; + +#ifdef STLPORT +_STLP_END_NAMESPACE +#else +} // namespace std +#endif + +#include <sockios/sp.h> + +#ifdef STLPORT +_STLP_BEGIN_NAMESPACE +#else +namespace std { +#endif + +template<class charT, class traits, class _Alloc> +class basic_sockbuf2 : + public basic_streambuf<charT, traits>, + public basic_socket<charT,traits,_Alloc> +{ + private: + typedef basic_socket<charT,traits,_Alloc> basic_socket_t; + + public: + typedef basic_ios<charT, traits> ios_type; + typedef basic_sockbuf2<charT, traits, _Alloc> sockbuf_type; + typedef typename traits::state_type state_t; + + public: + /* Inherited from basic_streambuf : */ + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + typedef traits traits_type; + /* */ + + basic_sockbuf2() : + rdready( *this ), +#if !defined(STLPORT) && defined(__GNUC__) +#if ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4))) // hmm, 3.3.6 + _mode( ios_base::openmode(__ios_flags::_S_in | __ios_flags::_S_out) ), +#else // 4.1.1 + _mode( _S_in | _S_out ), +#endif // __GNUC__ +#else // STLPORT + _mode( 0 ), +#endif // STLPORT + _bbuf(0), + _ebuf(0), + _allocated( true ) + { } + + basic_sockbuf2( const char *hostname, int port, + sock_base2::stype type = sock_base2::sock_stream, + sock_base2::protocol prot = sock_base2::inet ) : + rdready( *this ), +#if !defined(STLPORT) && defined(__GNUC__) +#if ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4))) + _mode( ios_base::openmode(__ios_flags::_S_in | __ios_flags::_S_out) ), +#else // 4.1.1 + _mode( _S_in | _S_out ), +#endif // __GNUC__ +#else // STLPORT + _mode( 0 ), +#endif // STLPORT + _bbuf(0), + _ebuf(0), + _allocated( true ) + { open( hostname, port, type, prot ); } + + basic_sockbuf2( const in_addr& addr, int port, + sock_base2::stype type = sock_base2::sock_stream, + sock_base2::protocol prot = sock_base2::inet ) : + rdready( *this ), +#if !defined(STLPORT) && defined(__GNUC__) +#if ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4))) + _mode( ios_base::openmode(__ios_flags::_S_in | __ios_flags::_S_out) ), +#else // 4.1.1 + _mode( _S_in | _S_out ), +#endif // __GNUC__ +#else // STLPORT + _mode( 0 ), +#endif // STLPORT + _bbuf(0), + _ebuf(0), + _allocated( true ) + { open( addr, type, prot ); } + + virtual ~basic_sockbuf2() + { + close(); + _M_deallocate_block(); + } + + sockbuf_type *open( const char *hostname, int port, + sock_base2::stype type = sock_base2::sock_stream, + sock_base2::protocol prot = sock_base2::inet ); + + sockbuf_type *open( const in_addr& addr, int port, + sock_base2::stype type = sock_base2::sock_stream, + sock_base2::protocol prot = sock_base2::inet ); + + sockbuf_type *open( sock_base2::socket_type s, + sock_base2::stype t = sock_base2::sock_stream ); + + sockbuf_type *open( sock_base2::socket_type s, const sockaddr& addr, + sock_base2::stype t = sock_base2::sock_stream ); + + sockbuf_type *attach( sock_base2::socket_type s, + sock_base2::stype t = sock_base2::sock_stream ); + + sockbuf_type *attach( sock_base2::socket_type s, const sockaddr& addr, + sock_base2::stype t = sock_base2::sock_stream ); + + sockbuf_type *close(); + void shutdown( sock_base2::shutdownflg dir ); + + sock_base2::stype stype() const + { return _type; } + + protected: + virtual streamsize showmanyc() + { return this->egptr() - this->gptr(); } + + virtual int_type underflow(); + virtual int_type overflow( int_type c = traits::eof() ); + virtual int_type pbackfail( int_type c = traits::eof() ) + { + if ( !basic_socket_t::is_open() ) + return traits::eof(); + + if ( this->gptr() <= this->eback() ) { + return traits::eof(); + } + + this->gbump(-1); + if ( !traits::eq_int_type(c,traits::eof()) ) { + *this->gptr() = traits::to_char_type(c); + return c; + } + + return traits::not_eof(c); + } + + // Buffer managment and positioning: + virtual basic_streambuf<charT, traits> *setbuf(char_type *s, streamsize n ) + { + if ( s != 0 && n != 0 ) { + _M_deallocate_block(); + _allocated = false; + _bbuf = s; + _ebuf = s + n; + } + return this; + } + + virtual int sync(); + virtual streamsize xsputn(const char_type *s, streamsize n); + + private: // Helper functions + charT* _bbuf; + charT* _ebuf; + bool _allocated; // true, if _bbuf should be deallocated + + // Precondition: 0 < __n <= max_size(). + charT* _M_allocate( size_t __n ) { return _M_data_allocator.allocate(__n); } + void _M_deallocate( charT* __p, size_t __n ) + { if (__p) _M_data_allocator.deallocate(__p, __n); } + + void _M_allocate_block(size_t __n) + { + if ( _allocated ) { + if ( __n <= max_size() ) { + _bbuf = _M_allocate(__n); + _ebuf = _bbuf + __n; + // _STLP_ASSERT( __n > 0 ? _bbuf != 0 : _bbuf == 0 ); + } else + this->_M_throw_length_error(); + } + } + + void _M_deallocate_block() + { if ( _allocated ) _M_deallocate(_bbuf, _ebuf - _bbuf); } + + size_t max_size() const { return (size_t(-1) / sizeof(charT)) - 1; } + +#ifdef STLPORT + void _M_throw_length_error() const + { _STLP_THROW(length_error("basic_sockbuf2")); } +#else + void _M_throw_length_error() const + { throw length_error("basic_sockbuf2"); } +#endif + +#ifdef STLPORT + typedef typename _Alloc_traits<charT, _Alloc>::allocator_type allocator_type; +#else + typedef _Alloc allocator_type; +#endif + /* typedef __allocator<charT, _Alloc> _Alloc_type; */ + + /* _Alloc_type */ allocator_type _M_data_allocator; + + class rdready_t + { + public: + rdready_t( sockbuf_type& self ) : + b( self ) + { } + bool operator ()() const + { return b.showmanyc() != 0; } + private: + sockbuf_type& b; + } rdready; + + sockbuf_type *_open_sockmgr( sock_base2::socket_type s, const sockaddr& addr, + sock_base2::stype t = sock_base2::sock_stream ); + + private: + typedef basic_sockbuf2<charT,traits,_Alloc> _Self_type; + int (basic_sockbuf2<charT,traits,_Alloc>::*_xwrite)( const void *, size_t ); + int (basic_sockbuf2<charT,traits,_Alloc>::*_xread)( void *, size_t ); + int write( const void *buf, size_t n ) +#ifndef WIN32 + { return ::write( basic_socket_t::_fd, buf, n ); } +#else + { return ::send( basic_socket_t::_fd, (const char *)buf, n, 0 ); } +#endif + int send( const void *buf, size_t n ) +#ifdef WIN32 + { return ::send( basic_socket_t::_fd, (const char *)buf, n, 0 ); } +#else + { return ::send( basic_socket_t::_fd, buf, n, 0 ); } +#endif + int sendto( const void *buf, size_t n ) +#ifdef WIN32 + { return ::sendto( basic_socket_t::_fd, (const char *)buf, n, 0, &basic_socket_t::_address.any, sizeof( sockaddr_in ) ); } +#else + { return ::sendto( basic_socket_t::_fd, buf, n, 0, &basic_socket_t::_address.any, sizeof( sockaddr_in ) ); } +#endif + + int read( void *buf, size_t n ) +#ifdef WIN32 + { return ::recv( basic_socket_t::_fd, (char *)buf, n, 0 ); } +#else + { return ::read( basic_socket_t::_fd, buf, n ); } +#endif + int recv( void *buf, size_t n ) +#ifdef WIN32 + { return ::recv( basic_socket_t::_fd, (char *)buf, n, 0 ); } +#else + { return ::recv( basic_socket_t::_fd, buf, n, 0 ); } +#endif + int recvfrom( void *buf, size_t n ); + void __hostname(); + + ios_base::openmode _mode; + sock_base2::stype _type; + + std::tr2::mutex ulck; + std::tr2::condition_variable ucnd; + + friend class detail::sockmgr<charT,traits,_Alloc>; +}; + +template <class charT, class traits, class _Alloc> +class basic_sockstream2 : + public sock_base2, + public basic_iostream<charT,traits> +{ + public: + /* Inherited from basic_iostream + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + */ + basic_sockstream2() : + sock_base2(), + basic_iostream<charT,traits>( 0 ) + { basic_ios<charT,traits>::init(&_sb); } + basic_sockstream2( const char *hostname, int port, + sock_base2::stype type = sock_base2::sock_stream, + sock_base2::protocol pro = sock_base2::inet ) : + sock_base2(), + basic_iostream<charT,traits>( 0 ) + { + basic_ios<charT,traits>::init(&_sb); + basic_iostream<charT,traits>::clear(); + if ( _sb.open( hostname, port, type, pro ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + basic_sockstream2( const in_addr& addr, int port, + sock_base2::stype type = sock_base2::sock_stream, + sock_base2::protocol pro = sock_base2::inet ) : + sock_base2(), + basic_iostream<charT,traits>( 0 ) + { + basic_ios<charT,traits>::init(&_sb); + basic_iostream<charT,traits>::clear(); + if ( _sb.open( addr, port, type, pro ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + basic_sockstream2( sock_base2::socket_type s, const sockaddr& addr, + sock_base2::stype type = sock_base2::sock_stream ) : + sock_base2(), + basic_iostream<charT,traits>( 0 ) + { + basic_ios<charT,traits>::init(&_sb); + basic_iostream<charT,traits>::clear(); + if ( _sb.open( s, addr, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + basic_sockstream2( sock_base2::socket_type s, + sock_base2::stype type = sock_base2::sock_stream ) : + sock_base2(), + basic_iostream<charT,traits>( 0 ) + { + basic_ios<charT,traits>::init(&_sb); + basic_iostream<charT,traits>::clear(); + if ( _sb.open( s, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + basic_sockbuf2<charT,traits,_Alloc>* rdbuf() const + { return const_cast<basic_sockbuf2<charT,traits,_Alloc>*>(&_sb); } + + bool is_open() const + { return _sb.is_open(); } + + void open( const char *hostname, int port, + sock_base2::stype type = sock_base2::sock_stream, + sock_base2::protocol pro = sock_base2::inet ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.open( hostname, port, type, pro ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + void open( const in_addr& addr, int port, + sock_base2::stype type = sock_base2::sock_stream, + sock_base2::protocol pro = sock_base2::inet ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.open( addr, port, type, pro ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + // only for sock_stream : inet now! + void open( sock_base2::socket_type s, const sockaddr& addr, + sock_base2::stype type = sock_base2::sock_stream ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.open( s, addr, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + void open( sock_base2::socket_type s, + sock_base2::stype type = sock_base2::sock_stream ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.open( s, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + void attach( sock_base2::socket_type s, const sockaddr& addr, + sock_base2::stype type = sock_base2::sock_stream ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.attach( s, addr, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + void attach( sock_base2::socket_type s, + sock_base2::stype type = sock_base2::sock_stream ) + { + basic_iostream<charT,traits>::clear(); + if ( _sb.attach( s, type ) == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit | ios_base::badbit ); + } + } + + void close() + { + if ( _sb.is_open() ) { + if ( _sb.close() == 0 ) { + basic_ios<charT,traits>::setstate( ios_base::failbit ); + } else { + basic_iostream<charT,traits>::clear(); + } + } + } + + void setoptions( sock_base2::so_t optname, bool on_off = true, + int __v = 0 ); + + private: + basic_sockbuf2<charT,traits,_Alloc> _sb; +}; + +typedef basic_sockbuf2<char,char_traits<char>,allocator<char> > sockbuf2; +// typedef basic_sockbuf2<wchar_t,char_traits<wchar_t>,allocator<wchar_t> > wsockbuf; +typedef basic_sockstream2<char,char_traits<char>,allocator<char> > sockstream2; +// typedef basic_sockstream<wchar_t,char_traits<wchar_t>,allocator<wchar_t> > wsockstream; + +#ifdef STLPORT +_STLP_END_NAMESPACE +#else +} // namespace std +#endif + +#ifndef __STL_LINK_TIME_INSTANTIATION +#include <sockios/sockstream2.cc> +#endif + +#endif // __SOCKIOS_SOCKSTREAM2 Copied: branches/complement-sockios/explore/include/sockios/sockstream2.cc (from rev 1828, branches/complement-sockios/explore/include/sockios/sockstream.cc) =================================================================== --- branches/complement-sockios/explore/include/sockios/sockstream2.cc (rev 0) +++ branches/complement-sockios/explore/include/sockios/sockstream2.cc 2008-03-11 15:03:22 UTC (rev 1833) @@ -0,0 +1,541 @@ +// -*- C++ -*- Time-stamp: <08/03/07 01:16:27 ptr> + +/* + * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + */ + +#include <sockios/netinfo.h> + +#if defined(__unix) && !defined(__UCLIBC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) +# include <stropts.h> // for ioctl() call +#endif + +#include <fcntl.h> + +#ifdef STLPORT +_STLP_BEGIN_NAMESPACE +#else +namespace std { +#endif + +template<class charT, class traits, class _Alloc> +basic_sockbuf2<charT, traits, _Alloc> * +basic_sockbuf2<charT, traits, _Alloc>::open( const char *name, int port, + sock_base2::stype type, + sock_base2::protocol prot ) +{ return basic_sockbuf2<charT, traits, _Alloc>::open( std::findhost( name ), port, type, prot ); } + +template<class charT, class traits, class _Alloc> +basic_sockbuf2<charT, traits, _Alloc> * +basic_sockbuf2<charT, traits, _Alloc>::open( const in_addr& addr, int port, + sock_base2::stype type, + sock_base2::protocol prot ) +{ + if ( basic_socket_t::is_open() ) { + return 0; + } + try { + _mode = ios_base::in | ios_base::out; + _type = type; +#ifdef WIN32 + WSASetLastError( 0 ); +#endif + if ( prot == sock_base2::inet ) { + basic_socket_t::_fd = socket( PF_INET, type, 0 ); + if ( basic_socket_t::_fd == -1 ) { + throw std::runtime_error( "can't open socket" ); + } + basic_socket_t::_address.inet.sin_family = AF_INET; + // htons is a define at least in Linux 2.2.5-15, and it's expantion fail + // for gcc 2.95.3 +#if defined(linux) && defined(htons) && defined(__bswap_16) + basic_socket_t::_address.inet.sin_port = ((((port) >> 8) & 0xff) | (((port) & 0xff) << 8)); +#else + basic_socket_t::_address.inet.sin_port = htons( port ); +#endif // linux && htons + basic_socket_t::_address.inet.sin_addr = addr; + + // Generally, stream sockets may successfully connect() only once + if ( connect( basic_socket_t::_fd, &basic_socket_t::_address.any, sizeof( basic_socket_t::_address ) ) == -1 ) { + throw std::domain_error( "connect fail" ); + } + if ( type == sock_base2::sock_stream ) { + _xwrite = &_Self_type::write; + _xread = &_Self_type::read; + } else if ( type == sock_base2::sock_dgram ) { + _xwrite = &_Self_type::send; + _xread = &_Self_type::recv; + } + } else if ( prot == sock_base2::local ) { + basic_socket_t::_fd = socket( PF_UNIX, type, 0 ); + if ( basic_socket_t::_fd == -1 ) { + throw std::runtime_error( "can't open socket" ); + } + } else { // other protocols not implemented yet + throw std::invalid_argument( "protocol not implemented" ); + } + + if ( _bbuf == 0 ) { + struct ifconf ifc; + struct ifreq ifr; + ifc.ifc_len = sizeof(ifreq); + ifc.ifc_req = 𝔦 + int mtu = ((ioctl(basic_socket_t::_fd, SIOCGIFMTU, &ifc) < 0 ? 1500 : ifr.ifr_mtu) - 20 - (type == sock_base2::sock_stream ? 20 : 8 )) / sizeof(charT); + int qlen = ioctl(basic_socket_t::_fd, SIOCGIFTXQLEN, &ifc) < 0 ? 2 : ifr.ifr_qlen; + _M_allocate_block( type == sock_base2::sock_stream ? mtu * qlen * 2 : mtu * 2 ); + } + + if ( _bbuf == 0 ) { + throw std::length_error( "can't allocate block" ); + } + + if ( fcntl( basic_socket_t::_fd, F_SETFL, fcntl( basic_socket_t::_fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { + throw std::runtime_error( "can't establish nonblock mode" ); + } + setp( _bbuf, _bbuf + ((_ebuf - _bbuf)>>1) ); + setg( this->epptr(), this->epptr(), this->epptr() ); + basic_socket_t::_notify_close = true; + basic_socket_t::mgr->push( *this ); + } + catch ( std::domain_error& ) { +#ifdef WIN32 + // _errno = WSAGetLastError(); + ::closesocket( basic_socket_t::_fd ); +#else + ::close( basic_socket_t::_fd ); +#endif + basic_socket_t::_fd = -1; + return 0; + } + catch ( std::length_error& ) { +#ifdef WIN32 + ::closesocket( basic_socket_t::_fd ); +#else + ::close( basic_socket_t::_fd ); +#endif + basic_socket_t::_fd = -1; + return 0; + } + catch ( std::runtime_error& ) { +#ifdef WIN32 + // _errno = WSAGetLastError(); +#else +#endif + return 0; + } + catch ( std::invalid_argument& ) { + return 0; + } + + return this; +} + +template<class charT, class traits, class _Alloc> +basic_sockbuf2<charT, traits, _Alloc> * +basic_sockbuf2<charT, traits, _Alloc>::open( sock_base2::socket_type s, sock_base2::stype t ) +{ + if ( basic_socket_t::is_open() || s == -1 ) { + return 0; + } + + sockaddr sa; + socklen_t sl = sizeof(sa); + getsockname( s, &sa, &sl ); + + return basic_sockbuf<charT, traits, _Alloc>::open( s, sa, t ); +} + +template<class charT, class traits, class _Alloc> +basic_sockbuf2<charT, traits, _Alloc> * +basic_sockbuf2<charT, traits, _Alloc>::open( sock_base2::socket_type s, + const sockaddr& addr, + sock_base2::stype t ) +{ + basic_sockbuf2<charT, traits, _Alloc>* ret = _open_sockmgr( s, addr, t ); + if ( ret != 0 ) { + basic_socket_t::_notify_close = true; + basic_socket_t::mgr->push( *this ); + } + return ret; +} + +template<class charT, class traits, class _Alloc> +basic_sockbuf2<charT, traits, _Alloc> * +basic_sockbuf2<charT, traits, _Alloc>::_open_sockmgr( sock_base2::socket_type s, + const sockaddr& addr, + sock_base2::stype t ) +{ + if ( basic_socket_t::is_open() || s == -1 ) { + return 0; + } + basic_socket_t::_fd = s; + memcpy( (void *)&basic_socket_t::_address.any, (const void *)&addr, sizeof(sockaddr) ); + _mode = ios_base::in | ios_base::out; + _type = t; +#ifdef WIN32 + WSASetLastError( 0 ); +#endif + if ( t == sock_base2::sock_stream ) { + _xwrite = &_Self_type::write; + _xread = &_Self_type::read; + } else if ( t == sock_base2::sock_dgram ) { + _xwrite = &_Self_type::sendto; + _xread = &_Self_type::recvfrom; + } else { + basic_socket_t::_fd = -1; + return 0; // unsupported type + } + + if ( _bbuf == 0 ) { + struct ifconf ifc; + struct ifreq ifr; + ifc.ifc_len = sizeof(ifreq); + ifc.ifc_req = 𝔦 + int mtu = ((ioctl(basic_socket_t::_fd, SIOCGIFMTU, &ifc) < 0 ? 1500 : ifr.ifr_mtu) - 20 - (t == sock_base2::sock_stream ? 20 : 8 )) / sizeof(charT); + int qlen = ioctl(basic_socket_t::_fd, SIOCGIFTXQLEN, &ifc) < 0 ? 2 : ifr.ifr_qlen; + _M_allocate_block( t == sock_base2::sock_stream ? mtu * qlen * 2 : mtu * 2); + } + + if ( _bbuf == 0 ) { +#ifdef WIN32 + ::closesocket( basic_socket_t::_fd ); +#else + ::close( basic_socket_t::_fd ); +#endif + basic_socket_t::_fd = -1; + return 0; + } + + if ( fcntl( basic_socket_t::_fd, F_SETFL, fcntl( basic_socket_t::_fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { + throw std::runtime_error( "can't establish nonblock mode" ); + } + setp( _bbuf, _bbuf + ((_ebuf - _bbuf)>>1) ); + setg( this->epptr(), this->epptr(), this->epptr() ); + + return this; +} + +template<class charT, class traits, class _Alloc> +basic_sockbuf2<charT, traits, _Alloc> * +basic_sockbuf2<charT, traits, _Alloc>::attach( sock_base2::socket_type s, + sock_base2::stype t ) +{ + if ( basic_socket_t::is_open() || s == -1 ) { + return 0; + } + + sockaddr sa; + socklen_t sl = sizeof(sa); + getsockname( s, &sa, &sl ); + + return basic_sockbuf<charT, traits, _Alloc>::attach( s, sa, t ); +} + +template<class charT, class traits, class _Alloc> +basic_sockbuf2<charT, traits, _Alloc> * +basic_sockbuf2<charT, traits, _Alloc>::attach( sock_base2::socket_type s, + const sockaddr& addr, + sock_base2::stype t ) +{ + if ( basic_socket_t::is_open() || s == -1 ) { + return 0; + } + + // _doclose = false; + return basic_sockbuf2<charT, traits, _Alloc>::open( dup(s), addr, t ); +} + +template<class charT, class traits, class _Alloc> +basic_sockbuf2<charT, traits, _Alloc> * +basic_sockbuf2<charT, traits, _Alloc>::close() +{ + if ( !basic_socket_t::is_open() ) + return 0; + + // if ( _doclose ) { +#ifdef WIN32 + ::closesocket( basic_socket_t::_fd ); +#else + ::close( basic_socket_t::_fd ); +#endif + // } + + // _STLP_ASSERT( _bbuf != 0 ); + // put area before get area + setp( _bbuf, _bbuf + ((_ebuf - _bbuf)>>1) ); + setg( this->epptr(), this->epptr(), this->epptr() ); + + if ( basic_socket_t::_notify_close ) { + basic_socket_t::mgr->exit_notify( this, basic_socket_t::_fd ); + basic_socket_t::_notify_close = false; + } + + basic_socket_t::_fd = -1; + + return this; +} + +template<class charT, class traits, class _Alloc> +void basic_sockbuf2<charT, traits, _Alloc>::shutdown( sock_base2::shutdownflg dir ) +{ + if ( basic_socket_t::is_open() ) { + if ( (dir & (sock_base2::stop_in | sock_base2::stop_out)) == + (sock_base2::stop_in | sock_base2::stop_out) ) { + ::shutdown( basic_socket_t::_fd, 2 ); + } else if ( dir & sock_base2::stop_in ) { + ::shutdown( basic_socket_t::_fd, 0 ); + } else if ( dir & sock_base2::stop_out ) { + ::shutdown( basic_socket_t::_fd, 1 ); + } + } +} + +template<class charT, class traits, class _Alloc> +__FIT_TYPENAME basic_sockbuf2<charT, traits, _Alloc>::int_type +basic_sockbuf2<charT, traits, _Alloc>::underflow() +{ + if( !basic_socket_t::is_open() ) + return traits::eof(); + + std::tr2::unique_lock<std::tr2::mutex> lk( ulck ); + + if ( this->gptr() < this->egptr() ) + return traits::to_int_type(*this->gptr()); + + if ( this->egptr() == this->gptr() ) { // fullfilled: _ebuf == gptr() + setg( this->eback(), this->eback(), this->eback() ); + } + + // setg( this->eback(), this->eback(), this->eback() + offset ); + // wait on condition + if ( basic_socket_t::_use_rdtimeout ) { + ucnd.timed_wait( lk, basic_socket_t::_rdtimeout, rdready ); + } else { + ucnd.wait( lk, rdready ); + } + + return traits::to_int_type(*this->gptr()); +} + +template<class charT, class traits, class _Alloc> +__FIT_TYPENAME basic_sockbuf2<charT, traits, _Alloc>::int_type +basic_sockbuf2<charT, traits, _Alloc>::overflow( int_type c ) +{ + if ( !basic_socket_t::is_open() ) + return traits::eof(); + + if ( !traits::eq_int_type( c, traits::eof() ) && this->pptr() < this->epptr() ) { + sputc( traits::to_char_type(c) ); + return c; + } + + long count = this->pptr() - this->pbase(); + + if ( count ) { + count *= sizeof(charT); + long offset = (this->*_xwrite)( this->pbase(), count ); + if ( offset < 0 ) { + if ( errno == EAGAIN ) { + pollfd wpfd; + wpfd.fd = basic_socket_t::_fd; + wpfd.events = POLLOUT | POLLHUP | POLLWRNORM; + wpfd.revents = 0; + while ( poll( &wpfd, 1, basic_socket_t::_use_wrtimeout ? basic_socket_t::_wrtimeout.count() : -1 ) <= 0 ) { // wait infinite + if ( errno == EINTR ) { // may be interrupted, check and ignore + errno = 0; + continue; + } + return traits::eof(); + } + if ( (wpfd.revents & POLLERR) != 0 ) { + return traits::eof(); + } + offset = (this->*_xwrite)( this->pbase(), count ); + if ( offset < 0 ) { + return traits::eof(); + } + } else { + return traits::eof(); + } + } + if ( offset < count ) { + // MUST BE: (offset % sizeof(char_traits)) == 0 ! + offset /= sizeof(charT); + count /= sizeof(charT); + traits::move( this->pbase(), this->pbase() + offset, count - offset ); + // std::copy_backword( this->pbase() + offset, this->pbase() + count, this->pbase() ); + setp( this->pbase(), this->epptr() ); // require: set pptr + this->pbump( count - offset ); + if( !traits::eq_int_type(c,traits::eof()) ) { + sputc( traits::to_char_type(c) ); + } + + return traits::not_eof(c); + } + } + + setp( this->pbase(), this->epptr() ); // require: set pptr + if( !traits::eq_int_type(c,traits::eof()) ) { + sputc( traits::to_char_type(c) ); + } + + return traits::not_eof(c); +} + +template<class charT, class traits, class _Alloc> +int basic_sockbuf2<charT, traits, _Alloc>::sync() +{ + if ( !basic_socket_t::is_open() ) { + return -1; + } + + long count = this->pptr() - this->pbase(); + if ( count ) { + // _STLP_ASSERT( this->pbase() != 0 ); + count *= sizeof(charT); + long start = 0; + while ( count > 0 ) { + long offset = (this->*_xwrite)( this->pbase() + start, count ); + if ( offset < 0 ) { + if ( errno == EAGAIN ) { + pollfd wpfd; + wpfd.fd = basic_socket_t::_fd; + wpfd.events = POLLOUT | POLLHUP | POLLWRNORM; + wpfd.revents = 0; + while ( poll( &wpfd, 1, basic_socket_t::_use_wrtimeout ? basic_socket_t::_wrtimeout.count() : -1 ) <= 0 ) { // wait infinite + if ( errno == EINTR ) { // may be interrupted, check and ignore + errno = 0; + continue; + } + return -1; + } + if ( (wpfd.revents & POLLERR) != 0 ) { + return -1; + } + offset = (this->*_xwrite)( this->pbase() + start, count ); + if ( offset < 0 ) { + return -1; + } + } else { + return -1; + } + } + count -= offset; + start += offset; + } + setp( this->pbase(), this->epptr() ); // require: set pptr + } + + return 0; +} + +template<class charT, class traits, class _Alloc> +streamsize basic_sockbuf2<charT, traits, _Alloc>:: +xsputn( const char_type *s, streamsize n ) +{ + if ( !basic_socket_t::is_open() || s == 0 || n == 0 ) { + return 0; + } + + if ( this->epptr() - this->pptr() > n ) { + traits::copy( this->pptr(), s, n ); + this->pbump( n ); + } else { + streamsize __n_put = this->epptr() - this->pptr(); + traits::copy( this->pptr(), s, __n_put ); + this->pbump( __n_put ); + + if ( traits::eq_int_type(overflow(),traits::eof()) ) + return 0; + + setp( (char_type *)(s + __n_put), (char_type *)(s + n) ); + this->pbump( n - __n_put ); + + if ( traits::eq_int_type(overflow(),traits::eof()) ) { + setp( _bbuf, _bbuf + ((_ebuf - _bbuf) >> 1) ); + return 0; + } + setp( _bbuf, _bbuf + ((_ebuf - _bbuf) >> 1) ); + } + return n; +} + +template<class charT, class traits, class _Alloc> +int basic_sockbuf2<charT, traits, _Alloc>::recvfrom( void *buf, size_t n ) +{ +#if defined(_WIN32) || (defined(__hpux) && !defined(_INCLUDE_POSIX1C_SOURCE)) + int sz = sizeof( sockaddr_in ); +#else + socklen_t sz = sizeof( sockaddr_in ); +#endif + + typename basic_socket_t::sockaddr_t addr; + +#ifdef __FIT_POLL + pollfd pfd; + pfd.fd = basic_socket_t::_fd; + pfd.events = POLLIN; +#endif // __FIT_POLL + do { +#ifdef __FIT_POLL + pfd.revents = 0; + if ( poll( &pfd, 1, /* _timeout */ -1 ) > 0 ) { // wait infinite + // get address of caller only + char buff[32]; + ::recvfrom( basic_socket_t::_fd, buff, 32, MSG_PEEK, &addr.any, &sz ); + } else { + return 0; // poll wait infinite, so it can't return 0 (timeout), so it return -1. + } +#endif // __FIT_POLL + if ( memcmp( &basic_socket_t::_address.inet, &addr.inet, sizeof(sockaddr_in) ) == 0 ) { +#ifdef WIN32 + return ::recvfrom( basic_socket_t::_fd, (char *)buf, n, 0, &basic_socket_t::_address.any, &sz ); +#else + return ::recvfrom( basic_socket_t::_fd, buf, n, 0, &basic_socket_t::_address.any, &sz ); +#endif + } + xmt::Thread::yield(); + } while ( true ); + + return 0; // never +} + +template<class charT, class traits, class _Alloc> +void basic_sockstream2<charT, traits, _Alloc>::setoptions( sock_base2::so_t optname, bool on_off, int __v ) +{ +#ifdef __unix + if ( _sb.is_open() ) { + if ( optname != sock_base2::so_linger ) { + int turn = on_off ? 1 : 0; + if ( setsockopt( _sb.fd(), SOL_SOCKET, (int)optname, (const void *)&turn, + (socklen_t)sizeof(int) ) != 0 ) { + this->setstate( ios_base::failbit ); + } + } else { + linger l; + l.l_onoff = on_off ? 1 : 0; + l.l_linger = __v; + if ( setsockopt( _sb.fd(), SOL_SOCKET, (int)optname, (const void *)&l, + (socklen_t)sizeof(linger) ) != 0 ) { + this->setstate( ios_base::failbit ); + } + } + } else { + this->setstate( ios_base::failbit ); + } +#endif // __unix +} + +#ifdef STLPORT +_STLP_END_NAMESPACE +#else +} // namespace std +#endif + Added: branches/complement-sockios/explore/include/sockios/sp.h =================================================================== --- branches/complement-sockios/explore/include/sockios/sp.h (rev 0) +++ branches/complement-sockios/explore/include/sockios/sp.h 2008-03-11 15:03:22 UTC (rev 1833) @@ -0,0 +1,697 @@ +// -*- C++ -*- Time-stamp: <08/03/07 01:40:59 ptr> + +/* + * Copyright (c) 2008 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License Version 3.0 + * + */ + +#ifndef __SOCKIOS_SP_H +#define __SOCKIOS_SP_H + +#include <sys/epoll.h> + +#ifndef EPOLLRDHUP +# define EPOLLRDHUP 0x2000 +#endif + +#include <fcntl.h> + +#include <cerrno> +#include <mt/thread> +#include <mt/mutex> + +#ifdef STLPORT +# include <unordered_map> +# include <unordered_set> +// # include <hash_map> +// # include <hash_set> +// # define __USE_STLPORT_HASH +# define __USE_STLPORT_TR1 +#else +# if defined(__GNUC__) && (__GNUC__ < 4) +# include <ext/hash_map> +# include <ext/hash_set> +# define __USE_STD_HASH +# else +# include <tr1/unordered_map> +# include <tr1/unordered_set> +# define __USE_STD_TR1 +# endif +#endif + +#include <sockios/sockstream> + +namespace std { + +template <class charT, class traits, class _Alloc> class basic_sockbuf2; +template <class charT, class traits, class _Alloc> class basic_sockstream2; +template <class charT, class traits, class _Alloc> class sock_processor_base; + +namespace detail { + +template<class charT, class traits, class _Alloc> +class _sock_processor_base : + public sock_base2, + public basic_socket<charT,traits,_Alloc> +{ + private: + typedef basic_socket<charT,traits,_Alloc> basic_socket_t; + + protected: + _sock_processor_base() : + _mode( ios_base::in | ios_base::out ), + _state( ios_base::goodbit ) + { } + + virtual ~_sock_processor_base() + { + _sock_processor_base::close(); + } + + public: + void open( const in_addr& addr, int port, sock_base2::stype type, sock_base2::protocol prot ); + void open( unsigned long addr, int port, sock_base2::stype type, sock_base2::protocol prot ); + void open( int port, sock_base2::stype type, sock_base2::protocol prot ); + + virtual void close(); + + protected: + void setoptions_unsafe( sock_base2::so_t optname, bool on_off = true, int __v = 0 ); + + public: + bool is_open() const + { std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); return basic_socket_t::is_open_unsafe(); } + bool good() const + { return _state == ios_base::goodbit; } + + sock_base2::socket_type fd() const + { std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); sock_base2::socket_type tmp = basic_socket_t::fd_unsafe(); return tmp; } + + void shutdown( sock_base2::shutdownflg dir ); + void setoptions( sock_base2::so_t optname, bool on_off = true, int __v = 0 ) + { + std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); + setoptions_unsafe( optname, on_off, __v ); + } + + private: + _sock_processor_base( const _sock_processor_base& ); + _sock_processor_base& operator =( const _sock_processor_base& ); + + private: + unsigned long _mode; // open mode + unsigned long _state; // state flags + + protected: + std::tr2::mutex _fd_lck; + // xmt::condition _loop_cnd; +}; + +template<class charT, class traits, class _Alloc> +void _sock_processor_base<charT,traits,_Alloc>::open( const in_addr& addr, int port, sock_base2::stype type, sock_base2::protocol prot ) +{ + std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); + if ( basic_socket_t::is_open_unsafe() ) { + return; + } + _mode = ios_base::in | ios_base::out; + _state = ios_base::goodbit; +#ifdef WIN32 + ::WSASetLastError( 0 ); +#endif + if ( prot == sock_base2::inet ) { + basic_socket_t::_fd = socket( PF_INET, type, 0 ); + if ( basic_socket_t::_fd == -1 ) { + _state |= ios_base::failbit | ios_base::badbit; + return; + } + // _open = true; + basic_socket_t::_address.inet.sin_family = AF_INET; + basic_socket_t::_address.inet.sin_port = htons( port ); + basic_socket_t::_address.inet.sin_addr.s_addr = addr.s_addr; + + if ( type == sock_base2::sock_stream || type == sock_base2::sock_seqpacket ) { + // let's try reuse local address + setoptions_unsafe( sock_base2::so_reuseaddr, true ); + } + + if ( ::bind( basic_socket_t::_fd, &basic_socket_t::_address.any, sizeof(basic_socket_t::_address) ) == -1 ) { + _state |= ios_base::failbit; +#ifdef WIN32 + ::closesocket( basic_socket_t::_fd ); +#else + ::close( basic_socket_t::_fd ); +#endif + basic_socket_t::_fd = -1; + return; + } + + if ( type == sock_base2::sock_stream || type == sock_base2::sock_seqpacket ) { + // I am shure, this is socket of type SOCK_STREAM | SOCK_SEQPACKET, + // so don't check return code from listen + ::listen( basic_socket_t::_fd, SOMAXCONN ); + basic_socket_t::mgr->push( dynamic_cast<sock_processor_base<charT,traits,_Alloc>&>(*this) ); + } + } else if ( prot == sock_base2::local ) { + return; + } else { + return; + } + _state = ios_base::goodbit; + + return; +} + +template<class charT, class traits, class _Alloc> +void _sock_processor_base<charT,traits,_Alloc>::open( unsigned long addr, int port, sock_base2::stype type, sock_base2::protocol prot ) +{ + in_addr _addr; + _addr.s_addr = htonl( addr ); + _sock_processor_base::open( _addr, port, type, prot ); +} + +template<class charT, class traits, class _Alloc> +void _sock_processor_base<charT,traits,_Alloc>::open( int port, sock_base2::stype type, sock_base2::protocol prot ) +{ + _sock_processor_base::open(INADDR_ANY, port, type, prot); +} + +template<class charT, class traits, class _Alloc> +void _sock_processor_base<charT,traits,_Alloc>::close() +{ + std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); + if ( !basic_socket_t::is_open_unsafe() ) { + return; + } +#ifdef WIN32 + ::closesocket( basic_socket_t::_fd ); +#else + ::shutdown( basic_socket_t::_fd, 2 ); + ::close( basic_socket_t::_fd ); +#endif + basic_socket_t::_fd = -1; +} + +template<class charT, class traits, class _Alloc> +void _sock_processor_base<charT,traits,_Alloc>::shutdown( sock_base2::shutdownflg dir ) +{ + std::tr2::lock_guard<std::tr2::mutex> lk(_fd_lck); + if ( basic_socket_t::is_open_unsafe() ) { + if ( (dir & (sock_base2::stop_in | sock_base2::stop_out)) == + (sock_base2::stop_in | sock_base2::stop_out) ) { + ::shutdown( basic_socket_t::_fd, 2 ); + } else if ( dir & sock_base2::stop_in ) { + ::shutdown( basic_socket_t::_fd, 0 ); + } else if ( dir & sock_base2::stop_out ) { + ::shutdown( basic_socket_t::_fd, 1 ); + } + } +} + +template<class charT, class traits, class _Alloc> +void _sock_processor_base<charT,traits,_Alloc>::setoptions_unsafe( sock_base2::so_t optname, bool on_off, int __v ) +{ +#ifdef __unix + if ( basic_socket_t::is_open_unsafe() ) { + if ( optname != sock_base2::so_linger ) { + int turn = on_off ? 1 : 0; + if ( setsockopt( basic_socket_t::_fd, SOL_SOCKET, (int)optname, (const void *)&turn, + (socklen_t)sizeof(int) ) != 0 ) { + _state |= ios_base::failbit; + } + } else { + linger l; + l.l_onoff = on_off ? 1 : 0; + l.l_linger = __v; + if ( setsockopt( basic_socket_t::_fd, SOL_SOCKET, (int)optname, (const void *)&l, + (socklen_t)sizeof(linger) ) != 0 ) { + _state |= ios_base::failbit; + } + + } + } else { + _state |= ios_base::failbit; + } +#endif // __unix +} + +} // namespace detail + +template <class charT, class traits, class _Alloc> +class sock_processor_base : + public detail::_sock_processor_base<charT,traits,_Alloc> +{ + private: + typedef detail::_sock_processor_base<charT,traits,_Alloc> sp_base_t; + + public: + typedef basic_sockstream2<charT,traits,_Alloc> sockstream_t; + + struct adopt_new_t { }; + struct adopt_close_t { }; + struct adopt_data_t { }; + + sock_processor_base() + { } + + explicit sock_processor_base( int port, sock_base2::stype t = sock_base2::sock_stream ) + { + sp_base_t::open( port, t, sock_base2::inet ); + } + + + virtual void operator ()( sockstream_t& s, const adopt_new_t& ) = 0; + virtual void operator ()( sockstream_t& s, const adopt_close_t& ) = 0; + virtual void operator ()( sockstream_t& s, const adopt_data_t& ) = 0; +}; + +typedef sock_processor_base<char,char_traits<char>,allocator<char> > sock_basic_processor; + +namespace detail { + +template<class charT, class traits, class _Alloc> +class sockmgr +{ + private: + typedef basic_sockstream2<charT,traits,_Alloc> sockstream_t; + typedef basic_sockbuf2<charT,traits,_Alloc> sockbuf_t; + typedef sock_processor_base<charT,traits,_Alloc> socks_processor_t; + + enum { + listener, + // tcp_stream, + tcp_buffer, + rqstop, + rqstart + }; + + struct fd_info + { + enum { + listener = 0x1, + level_triggered = 0x2, + owner = 0x4, + buffer = 0x8 + }; + + unsigned flags; + union { + sockstream_t* s; + sockbuf_t* b; + } s; + socks_processor_t *p; + }; + + struct ctl { + int cmd; + union { + int fd; + void *ptr; + } data; + }; + + static void _loop( sockmgr *me ) + { me->io_worker(); } + + public: + sockmgr( int hint = 1024, int ret = 512 ) : + n_ret( ret ) + { + efd = epoll_create( hint ); + if ( efd < 0 ) { + // throw system_error( errno ) + } + pipe( pipefd ); // check err + // cfd = pipefd[1]; + + epoll_event ev_add; + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP; + ev_add.data.fd = pipefd[0]; + epoll_ctl( efd, EPOLL_CTL_ADD, pipefd[0], &ev_add ); + + _worker = new std::tr2::thread( _loop, this ); + + // ctl _ctl; + // _ctl.cmd = rqstart; + + // write( pipefd[1], &_ctl, sizeof(ctl) ); + } + + ~sockmgr() + { + if ( _worker->joinable() ) { + ctl _ctl; + _ctl.cmd = rqstop; + + write( pipefd[1], &_ctl, sizeof(ctl) ); + + _worker->join(); + } + close( pipefd[1] ); + close( pipefd[0] ); + close( efd ); + delete _worker; + } + + void push( socks_processor_t& p ) + { + ctl _ctl; + _ctl.cmd = listener; + _ctl.data.ptr = static_cast<void *>(&p); + + write( pipefd[1], &_ctl, sizeof(ctl) ); + } + +#if 0 + void push( sockstream_t& s ) + { + ctl _ctl; + _ctl.cmd = tcp_stream; + _ctl.data.ptr = static_cast<void *>(&s); + + write( pipefd[1], &_ctl, sizeof(ctl) ); + } +#endif + + void push( sockbuf_t& s ) + { + ctl _ctl; + _ctl.cmd = tcp_buffer; + _ctl.data.ptr = static_cast<void *>(&s); + + errno = 0; + int r = write( pipefd[1], &_ctl, sizeof(ctl) ); + } + + void exit_notify( sockbuf_t* b, int fd ) + { + fd_info info = { 0, reinterpret_cast<sockstream_t*>(b), 0 }; + std::tr2::lock_guard<std::tr2::mutex> lk( cll ); + closed_queue[fd] = info; + } + + private: + sockmgr( const sockmgr& ) + { } + sockmgr& operator =( const sockmgr& ) + { return *this; } + + void io_worker(); + + int efd; + int pipefd[2]; + std::tr2::thread *_worker; + const int n_ret; + +#ifdef __USE_STLPORT_HASH + typedef std::hash_map<int,fd_info> fd_container_type; +#endif +#ifdef __USE_STD_HASH + typedef __gnu_cxx::hash_map<int, fd_info> fd_container_type; +#endif +#if defined(__USE_STLPORT_TR1) || defined(__USE_STD_TR1) + typedef std::tr1::unordered_map<int, fd_info> fd_container_type; +#endif + + fd_container_type descr; + fd_container_type closed_queue; + std::tr2::mutex cll; +}; + +template<class charT, class traits, class _Alloc> +void sockmgr<charT,traits,_Alloc>::io_worker() +{ + epoll_event ev[n_ret]; + +/* + ctl _xctl; + int r = read( pipefd[0], &_xctl, sizeof(ctl) ); + + if ( _xctl.cmd == rqstart ) { + std::cerr << "io_worker fine" << std::endl; + } else { + std::cerr << "io_worker not fine, " << r << ", " << errno << std::endl; + } +*/ + + for ( ; ; ) { + int n = epoll_wait( efd, &ev[0], n_ret, -1 ); + if ( n < 0 ) { + if ( errno == EINTR ) { + continue; + } + // throw system_error + } + for ( int i = 0; i < n; ++i ) { + if ( ev[i].data.fd == pipefd[0] ) { + epoll_event ev_add; + ctl _ctl; + int r = read( pipefd[0], &_ctl, sizeof(ctl) ); + if ( r < 0 ) { + // throw system_error + } else if ( r == 0 ) { + return; + } + + switch ( _ctl.cmd ) { + case listener: + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = static_cast<socks_processor_t*>(_ctl.data.ptr)->fd(); + if ( ev_add.data.fd >= 0 ) { + fd_info new_info = { fd_info::listener, 0, static_cast<socks_processor_t*>(_ctl.data.ptr) }; + descr[ev_add.data.fd] = new_info; + if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { + descr.erase( ev_add.data.fd ); + // throw system_error + } + } + break; +#if 0 + case tcp_stream: + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = static_cast<sockstream_t*>(_ctl.data.ptr)->rdbuf()->fd(); + if ( ev_add.data.fd >= 0 ) { + fd_info new_info = { 0, static_cast<sockstream_t*>(_ctl.data.ptr), 0 }; + descr[ev_add.data.fd] = new_info; + if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { + descr.erase( ev_add.data.fd ); + // throw system_error + } + } + break; +#endif + case tcp_buffer: + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = static_cast<sockbuf_t*>(_ctl.data.ptr)->fd(); + if ( ev_add.data.fd >= 0 ) { + fd_info new_info = { fd_info::buffer, static_cast<sockstream_t* /* sockbuf_t* */ >(_ctl.data.ptr), 0 }; + descr[ev_add.data.fd] = new_info; + if ( epoll_ctl( efd, EPOLL_CTL_ADD, ev_add.data.fd, &ev_add ) < 0 ) { + descr.erase( ev_add.data.fd ); + // throw system_error + } + } + break; + case rqstop: + return; + break; + } + + continue; + } + + typename fd_container_type::iterator ifd = descr.find( ev[i].data.fd ); + if ( ifd == descr.end() ) { + throw std::logic_error( "file descriptor in epoll, but not in descr[]" ); + } + + fd_info& info = ifd->second; + if ( info.flags & fd_info::listener ) { + if ( ev[i].events & EPOLLRDHUP ) { + epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ); + // walk through descr and detach every .p ? + descr.erase( ifd ); + } else if ( ev[i].events & EPOLLIN ) { + sockaddr addr; + socklen_t sz = sizeof( sockaddr_in ); + + int fd = accept( ev[i].data.fd, &addr, &sz ); + if ( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) != 0 ) { + throw std::runtime_error( "can't establish nonblock mode" ); + } + sockstream_t* s; + + try { + s = new sockstream_t(); + if ( s->rdbuf()->_open_sockmgr( fd, addr ) ) { + epoll_event ev_add; + ev_add.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT; + ev_add.data.fd = fd; + fd_info new_info = { fd_info::owner, s, info.p }; + descr[fd] = new_info; + + if ( epoll_ctl( efd, EPOLL_CTL_ADD, fd, &ev_add ) < 0 ) { + std::cerr << "Accept, add " << fd << ", errno " << errno << std::endl; + descr.erase( fd ); + // throw system_error + } + (*info.p)( *s, typename socks_processor_t::adopt_new_t() ); + } else { + std::cerr << "Accept, delete " << fd << std::endl; + delete s; + } + } + catch ( const std::bad_alloc& ) { + // nothing + } + catch ( ... ) { + descr.erase( fd ); + delete s; + } + } + } else { + if ( ev[i].events & EPOLLIN ) { + if ( (info.flags & fd_info::owner) == 0 ) { + // marginal case: me not owner (registerd via push(), + // when I owner, I know destroy point), + // already closed, but I not see closed event yet; + // object may be deleted already, so I can't + // call b->egptr() etc. here + std::tr2::lock_guard<std::tr2::mutex> lck( cll ); + typename fd_container_type::iterator closed_ifd = closed_queue.find( ev[i].data.fd ); + if ( closed_ifd != closed_queue.end() ) { + closed_queue.erase( closed_ifd ); + if ( epoll_ctl( efd, EPOLL_CTL_DEL, ifd->first, 0 ) < 0 ) { + // throw system_error + } + descr.erase( ifd ); + continue; + } + } + sockbuf_t* b = (info.flags & fd_info::buffer != 0) ? info.s.b : info.s.s->rdbuf(); + errno = 0; + for ( ; ; ) { + if ( b->_ebuf == b->egptr() ) { + // process extract data from buffer too slow for us! + if ( (info.flags & fd_info::level_triggered) == 0 ) { + epoll_event xev; + xev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP; + xev.data.fd = ev[i].data.fd; + in... [truncated message content] |
From: <com...@us...> - 2008-03-06 19:53:47
|
Revision: 1832 http://complement.svn.sourceforge.net/complement/?rev=1832&view=rev Author: complement Date: 2008-03-06 11:53:42 -0800 (Thu, 06 Mar 2008) Log Message: ----------- merge -r1828:HEAD branches/complement-sockios/explore Modified Paths: -------------- trunk/complement/explore/include/mt/condition_variable trunk/complement/explore/lib/mt/ChangeLog Modified: trunk/complement/explore/include/mt/condition_variable =================================================================== --- trunk/complement/explore/include/mt/condition_variable 2008-03-06 19:45:40 UTC (rev 1831) +++ trunk/complement/explore/include/mt/condition_variable 2008-03-06 19:53:42 UTC (rev 1832) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/03/02 14:44:37 ptr> +// -*- C++ -*- Time-stamp: <08/03/06 13:23:11 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -24,7 +24,11 @@ #include <mt/date_time> #include <mt/mutex> +#ifdef __FIT_PTHREADS +# include <semaphore.h> +#endif + namespace std { namespace tr2 { @@ -97,7 +101,7 @@ lock.lock(); #endif #ifdef __FIT_PTHREADS - int ret = pthread_cond_wait( &_cond, &lock.m->_M_lock ); + int ret = pthread_cond_wait( &_cond, const_cast<pthread_mutex_t *>(&lock.m->_M_lock) ); if ( ret ) { lock.lock(); // throw system_error @@ -119,7 +123,7 @@ ::timespec t; t.tv_sec = abs_time.seconds_since_epoch(); t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); - int ret = pthread_cond_timedwait( &_cond, &lock.m->_M_lock, &t ); + int ret = pthread_cond_timedwait( &_cond, const_cast<pthread_mutex_t *>(&lock.m->_M_lock), &t ); if ( ret != 0 ) { if ( ret == ETIMEDOUT ) { return false; Modified: trunk/complement/explore/lib/mt/ChangeLog =================================================================== --- trunk/complement/explore/lib/mt/ChangeLog 2008-03-06 19:45:40 UTC (rev 1831) +++ trunk/complement/explore/lib/mt/ChangeLog 2008-03-06 19:53:42 UTC (rev 1832) @@ -1,3 +1,8 @@ +2008-03-06 Petr Ovtchenkov <pt...@is...> + + * condition_variable: const casts for pthread_cond_* calls; + add semaphore.h. + 2008-02-26 Petr Ovtchenkov <pt...@is...> * thread, mutex, condition_variable, date_time: implementation This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-03-06 19:50:08
|
Revision: 1829 http://complement.svn.sourceforge.net/complement/?rev=1829&view=rev Author: complement Date: 2008-03-06 11:42:31 -0800 (Thu, 06 Mar 2008) Log Message: ----------- const casts for pthread_cond_* calls; add semaphore.h Modified Paths: -------------- branches/complement-sockios/explore/include/mt/condition_variable branches/complement-sockios/explore/lib/mt/ChangeLog Modified: branches/complement-sockios/explore/include/mt/condition_variable =================================================================== --- branches/complement-sockios/explore/include/mt/condition_variable 2008-02-28 18:15:40 UTC (rev 1828) +++ branches/complement-sockios/explore/include/mt/condition_variable 2008-03-06 19:42:31 UTC (rev 1829) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 13:09:15 ptr> +// -*- C++ -*- Time-stamp: <08/03/06 13:23:11 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -24,7 +24,11 @@ #include <mt/date_time> #include <mt/mutex> +#ifdef __FIT_PTHREADS +# include <semaphore.h> +#endif + namespace std { namespace tr2 { @@ -97,7 +101,7 @@ lock.lock(); #endif #ifdef __FIT_PTHREADS - int ret = pthread_cond_wait( &_cond, &lock.m->_M_lock ); + int ret = pthread_cond_wait( &_cond, const_cast<pthread_mutex_t *>(&lock.m->_M_lock) ); if ( ret ) { lock.lock(); // throw system_error @@ -119,7 +123,7 @@ ::timespec t; t.tv_sec = abs_time.seconds_since_epoch(); t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); - int ret = pthread_cond_timedwait( &_cond, &lock.m->_M_lock, &t ); + int ret = pthread_cond_timedwait( &_cond, const_cast<pthread_mutex_t *>(&lock.m->_M_lock), &t ); if ( ret != 0 ) { if ( ret == ETIMEDOUT ) { return false; Modified: branches/complement-sockios/explore/lib/mt/ChangeLog =================================================================== --- branches/complement-sockios/explore/lib/mt/ChangeLog 2008-02-28 18:15:40 UTC (rev 1828) +++ branches/complement-sockios/explore/lib/mt/ChangeLog 2008-03-06 19:42:31 UTC (rev 1829) @@ -1,3 +1,8 @@ +2008-03-06 Petr Ovtchenkov <pt...@is...> + + * condition_variable: const casts for pthread_cond_* calls; + add semaphore.h. + 2008-02-26 Petr Ovtchenkov <pt...@is...> * thread, mutex, condition_variable, date_time: implementation This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-03-06 19:48:58
|
Revision: 1830 http://complement.svn.sourceforge.net/complement/?rev=1830&view=rev Author: complement Date: 2008-03-06 11:45:17 -0800 (Thu, 06 Mar 2008) Log Message: ----------- ref to C++ 0x working draft Modified Paths: -------------- trunk/complement/explore/lib/mt/date_time.cc trunk/complement/explore/lib/mt/thread.cc Modified: trunk/complement/explore/lib/mt/date_time.cc =================================================================== --- trunk/complement/explore/lib/mt/date_time.cc 2008-03-06 19:42:31 UTC (rev 1829) +++ trunk/complement/explore/lib/mt/date_time.cc 2008-03-06 19:45:17 UTC (rev 1830) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/24 18:58:05 ptr> +// -*- C++ -*- Time-stamp: <08/03/02 14:45:29 ptr> /* * Copyright (c) 2002, 2006-2008 @@ -8,8 +8,8 @@ * * Derived from original <mt/time.h> of 'complement' project * [http://complement.sourceforge.net] - * to make it close to JTC1/SC22/WG21 working draft - * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + * to make it close to JTC1/SC22/WG21 C++ 0x working draft + * [http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2521.pdf] */ #include <mt/date_time> Modified: trunk/complement/explore/lib/mt/thread.cc =================================================================== --- trunk/complement/explore/lib/mt/thread.cc 2008-03-06 19:42:31 UTC (rev 1829) +++ trunk/complement/explore/lib/mt/thread.cc 2008-03-06 19:45:17 UTC (rev 1830) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 16:08:25 ptr> +// -*- C++ -*- Time-stamp: <08/03/02 14:54:25 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -11,8 +11,8 @@ * * Derived from original <mt/xmt.h> of 'complement' project * [http://complement.sourceforge.net] - * to make it close to JTC1/SC22/WG21 working draft - * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + * to make it close to JTC1/SC22/WG21 C++ 0x working draft + * [http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2521.pdf] */ #include <config/feature.h> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-03-06 19:48:56
|
Revision: 1831 http://complement.svn.sourceforge.net/complement/?rev=1831&view=rev Author: complement Date: 2008-03-06 11:45:40 -0800 (Thu, 06 Mar 2008) Log Message: ----------- ref to C++ 0x working draft Modified Paths: -------------- trunk/complement/explore/include/mt/condition_variable trunk/complement/explore/include/mt/mutex trunk/complement/explore/include/mt/thread Modified: trunk/complement/explore/include/mt/condition_variable =================================================================== --- trunk/complement/explore/include/mt/condition_variable 2008-03-06 19:45:17 UTC (rev 1830) +++ trunk/complement/explore/include/mt/condition_variable 2008-03-06 19:45:40 UTC (rev 1831) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 13:09:15 ptr> +// -*- C++ -*- Time-stamp: <08/03/02 14:44:37 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -11,8 +11,8 @@ * * Derived from original <mt/xmt.h> of 'complement' project * [http://complement.sourceforge.net] - * to make it close to JTC1/SC22/WG21 working draft - * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + * to make it close to JTC1/SC22/WG21 C++ 0x working draft + * [http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2521.pdf] */ #ifndef __MT_CONDITION_VARIABLE Modified: trunk/complement/explore/include/mt/mutex =================================================================== --- trunk/complement/explore/include/mt/mutex 2008-03-06 19:45:17 UTC (rev 1830) +++ trunk/complement/explore/include/mt/mutex 2008-03-06 19:45:40 UTC (rev 1831) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/24 23:48:23 ptr> +// -*- C++ -*- Time-stamp: <08/03/02 14:43:55 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -11,8 +11,8 @@ * * Derived from original <mt/xmt.h> of 'complement' project * [http://complement.sourceforge.net] - * to make it close to JTC1/SC22/WG21 working draft - * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + * to make it close to JTC1/SC22/WG21 C++ 0x working draft + * [http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2521.pdf] */ #ifndef __MUTEX_H Modified: trunk/complement/explore/include/mt/thread =================================================================== --- trunk/complement/explore/include/mt/thread 2008-03-06 19:45:17 UTC (rev 1830) +++ trunk/complement/explore/include/mt/thread 2008-03-06 19:45:40 UTC (rev 1831) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/02/25 16:11:00 ptr> +// -*- C++ -*- Time-stamp: <08/03/02 14:44:16 ptr> /* * Copyright (c) 1997-1999, 2002-2008 @@ -11,8 +11,8 @@ * * Derived from original <mt/xmt.h> of 'complement' project * [http://complement.sourceforge.net] - * to make it close to JTC1/SC22/WG21 working draft - * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + * to make it close to JTC1/SC22/WG21 C++ 0x working draft + * [http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2521.pdf] */ #ifndef __THREAD_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |