Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r63430 - in trunk: boost/iostreams/device libs/iostreams/build libs/iostreams/doc/classes libs/iostreams/src libs/iostreams/test libs/iostreams/test/detail
From: daniel_james_at_[hidden]
Date: 2010-06-29 10:15:15


Author: danieljames
Date: 2010-06-29 10:15:13 EDT (Tue, 29 Jun 2010)
New Revision: 63430
URL: http://svn.boost.org/trac/boost/changeset/63430

Log:
Try to improve file_descriptor's ownership policies. Refs #3517

* Deprecate the old 'close_on_exit' constructors.
* Introduce new constructors from file handle, taking either
  `never_close_handle` or `close_handle`.
* Close current file handle when opening a new file handle,
  if it would have been closed in the destructor.
Added:
   trunk/libs/iostreams/test/deprecated_file_descriptor_test.cpp (contents, props changed)
   trunk/libs/iostreams/test/detail/file_handle.hpp (contents, props changed)
Text files modified:
   trunk/boost/iostreams/device/file_descriptor.hpp | 54 +++++++++++++
   trunk/libs/iostreams/build/Jamfile.v2 | 1
   trunk/libs/iostreams/doc/classes/file_descriptor.html | 152 +++++++++++++++++++++++++++++++++----
   trunk/libs/iostreams/src/file_descriptor.cpp | 160 +++++++++++++++++++++++++++++++--------
   trunk/libs/iostreams/test/Jamfile.v2 | 24 ++++++
   trunk/libs/iostreams/test/file_descriptor_test.cpp | 121 ++++++++++++++++++++++++++++++
   6 files changed, 460 insertions(+), 52 deletions(-)

Modified: trunk/boost/iostreams/device/file_descriptor.hpp
==============================================================================
--- trunk/boost/iostreams/device/file_descriptor.hpp (original)
+++ trunk/boost/iostreams/device/file_descriptor.hpp 2010-06-29 10:15:13 EDT (Tue, 29 Jun 2010)
@@ -37,6 +37,12 @@
 class file_descriptor_sink;
 namespace detail { struct file_descriptor_impl; }
 
+enum file_descriptor_flags
+{
+ never_close_handle = 0,
+ close_handle = 3
+};
+
 class BOOST_IOSTREAMS_DECL file_descriptor {
 public:
     friend class file_descriptor_source;
@@ -52,10 +58,18 @@
     file_descriptor();
 
     // Constructors taking file desciptors
+ file_descriptor(handle_type fd, file_descriptor_flags);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ file_descriptor(int fd, file_descriptor_flags);
+#endif
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
+ // Constructors taking file desciptors
     explicit file_descriptor(handle_type fd, bool close_on_exit = false);
 #ifdef BOOST_IOSTREAMS_WINDOWS
     explicit file_descriptor(int fd, bool close_on_exit = false);
 #endif
+#endif
 
     // Constructor taking a std:: string
     explicit file_descriptor( const std::string& path,
@@ -81,10 +95,18 @@
     file_descriptor(const file_descriptor& other);
 
     // open overloads taking file descriptors
+ void open(handle_type fd, file_descriptor_flags);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ void open(int fd, file_descriptor_flags);
+#endif
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
+ // open overloads taking file descriptors
     void open(handle_type fd, bool close_on_exit = false);
 #ifdef BOOST_IOSTREAMS_WINDOWS
     void open(int fd, bool close_on_exit = false);
 #endif
+#endif
 
     // open overload taking a std::string
     void open( const std::string& path,
@@ -144,10 +166,18 @@
     file_descriptor_source() { }
 
     // Constructors taking file desciptors
+ explicit file_descriptor_source(handle_type fd, file_descriptor_flags);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ explicit file_descriptor_source(int fd, file_descriptor_flags);
+#endif
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
+ // Constructors taking file desciptors
     explicit file_descriptor_source(handle_type fd, bool close_on_exit = false);
 #ifdef BOOST_IOSTREAMS_WINDOWS
     explicit file_descriptor_source(int fd, bool close_on_exit = false);
 #endif
+#endif
 
     // Constructor taking a std:: string
     explicit file_descriptor_source( const std::string& path,
@@ -166,11 +196,19 @@
     // Copy constructor
     file_descriptor_source(const file_descriptor_source& other);
 
+ // Constructors taking file desciptors
+ void open(handle_type fd, file_descriptor_flags);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ void open(int fd, file_descriptor_flags);
+#endif
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
     // open overloads taking file descriptors
     void open(handle_type fd, bool close_on_exit = false);
 #ifdef BOOST_IOSTREAMS_WINDOWS
     void open(int fd, bool close_on_exit = false);
 #endif
+#endif
 
     // open overload taking a std::string
     void open(const std::string& path, BOOST_IOS::openmode mode = BOOST_IOS::in);
@@ -210,10 +248,18 @@
     file_descriptor_sink() { }
 
     // Constructors taking file desciptors
+ file_descriptor_sink(handle_type fd, file_descriptor_flags);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ file_descriptor_sink(int fd, file_descriptor_flags);
+#endif
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
+ // Constructors taking file desciptors
     explicit file_descriptor_sink(handle_type fd, bool close_on_exit = false);
 #ifdef BOOST_IOSTREAMS_WINDOWS
     explicit file_descriptor_sink(int fd, bool close_on_exit = false);
 #endif
+#endif
 
     // Constructor taking a std:: string
     explicit file_descriptor_sink( const std::string& path,
@@ -233,10 +279,18 @@
     file_descriptor_sink(const file_descriptor_sink& other);
 
     // open overloads taking file descriptors
+ void open(handle_type fd, file_descriptor_flags);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ void open(int fd, file_descriptor_flags);
+#endif
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
+ // open overloads taking file descriptors
     void open(handle_type fd, bool close_on_exit = false);
 #ifdef BOOST_IOSTREAMS_WINDOWS
     void open(int fd, bool close_on_exit = false);
 #endif
+#endif
 
     // open overload taking a std::string
     void open( const std::string& path,

Modified: trunk/libs/iostreams/build/Jamfile.v2
==============================================================================
--- trunk/libs/iostreams/build/Jamfile.v2 (original)
+++ trunk/libs/iostreams/build/Jamfile.v2 2010-06-29 10:15:13 EDT (Tue, 29 Jun 2010)
@@ -155,6 +155,7 @@
 lib boost_iostreams
     : $(sources)
     : <link>shared:<define>BOOST_IOSTREAMS_DYN_LINK=1
+ <define>BOOST_IOSTREAMS_USE_DEPRECATED
     :
     : <link>shared:<define>BOOST_IOSTREAMS_DYN_LINK=1
     ;

Modified: trunk/libs/iostreams/doc/classes/file_descriptor.html
==============================================================================
--- trunk/libs/iostreams/doc/classes/file_descriptor.html (original)
+++ trunk/libs/iostreams/doc/classes/file_descriptor.html 2010-06-29 10:15:13 EDT (Tue, 29 Jun 2010)
@@ -97,6 +97,11 @@
 
 <PRE CLASS="broken_ie"><SPAN CLASS="keyword">namespace</SPAN> boost { <SPAN CLASS="keyword">namespace</SPAN> iostreams {
 
+<SPAN CLASS="keyword">enum</SPAN> file_descriptor_flags {
+ never_close_handle,
+ close_handle
+};
+
 <SPAN CLASS="keyword">class</SPAN> file_descriptor_source {
 <SPAN CLASS="keyword">public</SPAN>:
     <SPAN CLASS='keyword'>typedef</SPAN> <SPAN CLASS='keyword'>char</SPAN> char_type;
@@ -107,18 +112,30 @@
     <A CLASS="documented" HREF="#file_descriptor_source_ctor">file_descriptor_source</A>( <SPAN CLASS="keyword">const</SPAN> Path& pathname,
                             std::ios_base::open_mode mode =
                                 std::ios_base::in );
- <A CLASS="documented" HREF="#file_descriptor_source_ctor">file_descriptor_source</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+ <A CLASS="documented" HREF="#file_descriptor_source_ctor">file_descriptor_source</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
 
     <SPAN CLASS='comment'>// Windows-only</SPAN>
+ <A CLASS="documented" HREF="#file_descriptor_source_ctor">file_descriptor_source</A>( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ <A CLASS="documented" HREF="#file_descriptor_source_ctor">file_descriptor_source</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
     <A CLASS="documented" HREF="#file_descriptor_source_ctor">file_descriptor_source</A>( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
 
     <SPAN CLASS="keyword">template</SPAN>&lt;<SPAN CLASS="keyword">typename</SPAN> Path&gt;
     <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_source_open">open</A>( <SPAN CLASS="keyword">const</SPAN> Path& pathname,
                      std::ios_base::open_mode mode =
                          std::ios_base::in );
- <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_source_open">open</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+ <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_source_open">open</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
 
     <SPAN CLASS='comment'>// Windows-only</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_source_open">open</A>( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_source_open">open</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
     <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_source_open">open</A>( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
 
     <SPAN CLASS="keyword">bool</SPAN> <A CLASS="documented" HREF="#file_descriptor_source_is_open">is_open</A>() <SPAN CLASS="keyword">const</SPAN>;
@@ -136,11 +153,16 @@
     file_descriptor_source( <SPAN CLASS="keyword">const</SPAN> Path& pathname,
                             std::ios_base::open_mode mode =
                                 std::ios_base::in );
- file_descriptor_source( <SPAN CLASS="keyword">int </SPAN>fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+ file_descriptor_source( <SPAN CLASS="keyword">int </SPAN>fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
 
     <SPAN CLASS='comment'>// Windows-only</SPAN>
- file_descriptor_source( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );</PRE>
+ file_descriptor_source( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
 
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ file_descriptor_source( <SPAN CLASS="keyword">int </SPAN>fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
+ file_descriptor_source( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );</PRE>
 <P>
     The first member constructs an empty <CODE>file_descriptor_source</CODE>.
 </P>
@@ -150,11 +172,19 @@
 </P>
 
 <P>
- The third member constructs a <CODE>file_descriptor_source</CODE> to access the file with the given operating system or runtime-library file descriptor. If the second argument is <CODE>true</CODE>, the file descriptor is closed when the <CODE>file_descriptor_source</CODE> being constructed &#8212; or one of its copies &#8212; is closed.
+ The third member constructs a <CODE>file_descriptor_source</CODE> to access the file with the given operating system or runtime-library file descriptor.
+ If the second argument is <CODE>close_handle</CODE>, the file descriptor is closed when the <CODE>file_descriptor_source</CODE> being constructed &#8212; or one of its copies &#8212; is closed or destructed.
 </P>
 
 <P>
- The fourth member is the same as the third, except that it accepts a Windows file handle instead of a file descriptor. If the second argument is <CODE>true</CODE>, the file descriptor is closed when the <CODE>file_descriptor_source</CODE> being constructed &#8212; or one of its copies &#8212; is closed.
+ The fourth member is the same as the third, except that it accepts a Windows file handle instead of a file descriptor.
+ If the second argument is <CODE>close_handle</CODE>, the file descriptor is closed when the <CODE>file_descriptor_source</CODE> being constructed &#8212; or one of its copies &#8212; is closed or destructed.
+</P>
+
+<P>
+ The deprecated members are there to provide backwards compatability with old versions.
+ To use them you need to define <CODE>BOOST_IOSTREAMS_USE_DEPRECATED</CODE>.
+ The descriptor is always closed by <CODE>close</CODE> but only closed in destructors if <CODE>close_on_exit</CODE> is <CODE>true</CODE>.
 </P>
 
 <A NAME="file_descriptor_source_open"></A>
@@ -164,13 +194,21 @@
     <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">const</SPAN> Path& pathname,
                      std::ios_base::open_mode mode =
                          std::ios_base::in );
- <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+ <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
 
     <SPAN CLASS='comment'>// Windows-only</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> open( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
     <SPAN CLASS="keyword">void</SPAN> open( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );</PRE>
 
 <P>
     The parameters of <CODE>open</CODE> the same as those of the corresponding constructors.
+ If the file descriptor already holds a file, it'll be closed
+ (unless opened or constructed with <CODE>never_close_handle</CODE>).
 </P>
 
 <A NAME="file_descriptor_source_is_open"></A>
@@ -198,6 +236,11 @@
 
 <PRE CLASS="broken_ie"><SPAN CLASS="keyword">namespace</SPAN> boost { <SPAN CLASS="keyword">namespace</SPAN> iostreams {
 
+<SPAN CLASS="keyword">enum</SPAN> file_descriptor_flags {
+ never_close_handle,
+ close_handle
+};
+
 <SPAN CLASS="keyword">class</SPAN> file_descriptor_sink {
 <SPAN CLASS="keyword">public</SPAN>:
     <SPAN CLASS='keyword'>typedef</SPAN> <SPAN CLASS='keyword'>char</SPAN> char_type;
@@ -213,13 +256,25 @@
     <SPAN CLASS='comment'>// Windows-only</SPAN>
     <A CLASS="documented" HREF="#file_descriptor_sink_ctor">file_descriptor_sink</A>( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
 
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ <A CLASS="documented" HREF="#file_descriptor_sink_ctor">file_descriptor_sink</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
+ <A CLASS="documented" HREF="#file_descriptor_sink_ctor">file_descriptor_sink</A>( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
     <SPAN CLASS="keyword">template</SPAN>&lt;<SPAN CLASS="keyword">typename</SPAN> Path&gt;
     <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_sink_open">open</A>( <SPAN CLASS="keyword">const</SPAN> Path& pathname,
                      std::ios_base::open_mode mode =
                          std::ios_base::out );
- <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_sink_open">open</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+ <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_sink_open">open</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
 
     <SPAN CLASS='comment'>// Windows-only</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_sink_open">open</A>( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_sink_open">open</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
     <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_sink_open">open</A>( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
 
     <SPAN CLASS="keyword">bool</SPAN> <A CLASS="documented" HREF="#file_descriptor_sink_is_open">is_open</A>() <SPAN CLASS="keyword">const</SPAN>;
@@ -240,7 +295,13 @@
     file_descriptor_sink( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
 
     <SPAN CLASS='comment'>// Windows-only</SPAN>
- file_descriptor_sink( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );</PRE>
+ file_descriptor_sink( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ file_descriptor_sink( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
+ file_descriptor_sink( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );</PRE>
 
 <P>
     The first member constructs an empty <CODE>file_descriptor_sink</CODE>.
@@ -251,11 +312,19 @@
 </P>
 
 <P>
- The third member constructs a <CODE>file_descriptor_sink</CODE> to access the file with the given operating system or runtime-library file descriptor. If the second argument is <CODE>true</CODE>, the file descriptor is closed when the new <CODE>file_descriptor_sink</CODE> &#8212; or one of its copies &#8212; is closed.
+ The third member constructs a <CODE>file_descriptor_sink</CODE> to access the file with the given operating system or runtime-library file descriptor.
+ If the second argument is <CODE>close_handle</CODE>, the file descriptor is closed when the <CODE>file_descriptor_sink</CODE> being constructed &#8212; or one of its copies &#8212; is closed or destructed.
+</P>
+
+<P>
+ The fourth member is the same as the third, except that it accepts a Windows file handle instead of a file descriptor.
+ If the second argument is <CODE>close_handle</CODE>, the file descriptor is closed when the <CODE>file_descriptor_sink</CODE> being constructed &#8212; or one of its copies &#8212; is closed or destructed.
 </P>
 
 <P>
- The fourth member is the same as the third, except that it accepts a Windows file handle instead of a file descriptor. If the second argument is <CODE>true</CODE>, the file descriptor is closed when the new <CODE>file_descriptor_sink</CODE> &#8212; or one of its copies &#8212; is closed.
+ The deprecated members are there to provide backwards compatability with old versions.
+ To use them you need to define <CODE>BOOST_IOSTREAMS_USE_DEPRECATED</CODE>.
+ The descriptor is always closed by <CODE>close</CODE> but only closed in destructors if <CODE>close_on_exit</CODE> is <CODE>true</CODE>.
 </P>
 
 <A NAME="file_descriptor_sink_open"></A>
@@ -265,13 +334,21 @@
     <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">const</SPAN> Path& pathname,
                      std::ios_base::open_mode mode =
                          std::ios_base::out );
- <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+ <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
 
     <SPAN CLASS='comment'>// Windows-only</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> open( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
     <SPAN CLASS="keyword">void</SPAN> open( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );</PRE>
 
 <P>
     The parameters of <CODE>open</CODE> the same as those of the corresponding constructors.
+ If the file descriptor already holds a file, it'll be closed
+ (unless opened or constructed with <CODE>never_close_handle</CODE>).
 </P>
 
 <A NAME="file_descriptor_sink_is_open"></A>
@@ -299,6 +376,11 @@
 
 <PRE CLASS="broken_ie"><SPAN CLASS="keyword">namespace</SPAN> boost { <SPAN CLASS="keyword">namespace</SPAN> iostreams {
 
+<SPAN CLASS="keyword">enum</SPAN> file_descriptor_flags {
+ never_close_handle,
+ close_handle
+};
+
 <SPAN CLASS="keyword">class</SPAN> file_descriptor {
 <SPAN CLASS="keyword">public</SPAN>:
     <SPAN CLASS='keyword'>typedef</SPAN> <SPAN CLASS='keyword'>char</SPAN> char_type;
@@ -309,18 +391,30 @@
     <A CLASS="documented" HREF="#file_descriptor_constructor">file_descriptor</A>( <SPAN CLASS="keyword">const</SPAN> Path& pathname,
                      std::ios_base::open_mode mode =
                          std::ios_base::in | std::ios_base::out );
- <A CLASS="documented" HREF="#file_descriptor_constructor">file_descriptor</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+ <A CLASS="documented" HREF="#file_descriptor_constructor">file_descriptor</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
 
     <SPAN CLASS='comment'>// Windows-only</SPAN>
+ <A CLASS="documented" HREF="#file_descriptor_constructor">file_descriptor</A>( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ <A CLASS="documented" HREF="#file_descriptor_constructor">file_descriptor</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
     <A CLASS="documented" HREF="#file_descriptor_constructor">file_descriptor</A>( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
 
     <SPAN CLASS="keyword">template</SPAN>&lt;<SPAN CLASS="keyword">typename</SPAN> Path&gt;
     <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_open">open</A>( <SPAN CLASS="keyword">const</SPAN> Path& pathname,
                      std::ios_base::open_mode mode =
                          std::ios_base::in | std::ios_base::out );
- <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_open">open</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+ <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_open">open</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
 
     <SPAN CLASS='comment'>// Windows-only</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_open">open</A>( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_open">open</A>( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
     <SPAN CLASS="keyword">void</SPAN> <A CLASS="documented" HREF="#file_descriptor_open">open</A>( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
 
     <SPAN CLASS="keyword">bool</SPAN> <A CLASS="documented" HREF="#file_descriptor_is_open">is_open</A>() <SPAN CLASS="keyword">const</SPAN>;
@@ -338,9 +432,15 @@
     file_descriptor( <SPAN CLASS="keyword">const</SPAN> Path& pathname,
                      std::ios_base::open_mode mode =
                          std::ios_base::in | std::ios_base::out );
- file_descriptor( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+ file_descriptor( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
 
     <SPAN CLASS='comment'>// Windows-only</SPAN>
+ file_descriptor( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ file_descriptor( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
     file_descriptor( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );</PRE>
 
 <P>
@@ -352,11 +452,19 @@
 </P>
 
 <P>
- The third member constructs a <CODE>file_descriptor</CODE> to access the file with the given operating system or runtime-library file descriptor. If the second argument is <CODE>true</CODE>, the file descriptor is closed when the new <CODE>file_descriptor</CODE> &#8212; or one of its copies &#8212; is closed.
+ The third member constructs a <CODE>file_descriptor</CODE> to access the file with the given operating system or runtime-library file descriptor.
+ If the second argument is <CODE>close_handle</CODE>, the file descriptor is closed when the <CODE>file_descriptor</CODE> being constructed &#8212; or one of its copies &#8212; is closed or destructed.
 </P>
 
 <P>
- The fourth member is the same as the third, except that it accepts a Windows file handle instead of a file descriptor. If the second argument is <CODE>true</CODE>, the file descriptor is closed when the new <CODE>file_descriptor</CODE> &#8212; or one of its copies &#8212; is closed.
+ The fourth member is the same as the third, except that it accepts a Windows file handle instead of a file descriptor.
+ If the second argument is <CODE>close_handle</CODE>, the file descriptor is closed when the new <CODE>file_descriptor</CODE> &#8212; or one of its copies &#8212; is closed or destructed.
+</P>
+
+<P>
+ The deprecated members are there to provide backwards compatability with old versions.
+ To use them you need to define <CODE>BOOST_IOSTREAMS_USE_DEPRECATED</CODE>.
+ The descriptor is always closed by <CODE>close</CODE> but only closed in destructors if <CODE>close_on_exit</CODE> is <CODE>true</CODE>.
 </P>
 
 <A NAME="file_descriptor_open"></A>
@@ -366,13 +474,21 @@
     <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">const</SPAN> Path& pathname,
                      std::ios_base::open_mode mode =
                          std::ios_base::in | std::ios_base::out );
- <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+ <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
 
     <SPAN CLASS='comment'>// Windows-only</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> open( HANDLE hFile, <SPAN CLASS="keyword">file_descriptor_flags</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated</SPAN>
+ <SPAN CLASS="keyword">void</SPAN> open( <SPAN CLASS="keyword">int</SPAN> fd, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );
+
+ <SPAN CLASS='comment'>// Deprecated, Windows-only</SPAN>
     <SPAN CLASS="keyword">void</SPAN> open( HANDLE hFile, <SPAN CLASS="keyword">bool</SPAN> close_on_exit = <SPAN CLASS="keyword">false</SPAN> );</PRE>
 
 <P>
     The parameters of <CODE>open</CODE> the same as those of the corresponding constructors.
+ If the file descriptor already holds a file, it'll be closed
+ (unless opened or constructed with <CODE>never_close_handle</CODE>).
 </P>
 
 <A NAME="file_descriptor_is_open"></A>

Modified: trunk/libs/iostreams/src/file_descriptor.cpp
==============================================================================
--- trunk/libs/iostreams/src/file_descriptor.cpp (original)
+++ trunk/libs/iostreams/src/file_descriptor.cpp 2010-06-29 10:15:13 EDT (Tue, 29 Jun 2010)
@@ -48,22 +48,28 @@
 
 // Contains the platform dependant implementation
 struct file_descriptor_impl {
+ // Note: These need to match file_desciptor_flags
+ enum flags {
+ never_close = 0,
+ close_on_exit = 1,
+ close_on_close = 2,
+ close_always = 3
+ };
+
     file_descriptor_impl();
     ~file_descriptor_impl();
- void open(file_handle fd, bool close_on_exit);
+ void open(file_handle fd, flags);
 #ifdef BOOST_IOSTREAMS_WINDOWS
- void open(int fd, bool close_on_exit);
+ void open(int fd, flags);
 #endif
     void open(const detail::path&, BOOST_IOS::openmode);
     bool is_open() const;
     void close();
+ void close_impl(bool close_flag, bool throw_);
     std::streamsize read(char* s, std::streamsize n);
     std::streamsize write(const char* s, std::streamsize n);
     std::streampos seek(stream_offset off, BOOST_IOS::seekdir way);
     static file_handle invalid_handle();
- enum flags {
- close_on_exit = 1
- };
     file_handle handle_;
     int flags_;
 };
@@ -76,30 +82,38 @@
 
 file_descriptor_impl::~file_descriptor_impl()
 {
- if (flags_ & close_on_exit) {
- try {
- close();
- } catch (...) { }
- }
+ close_impl(flags_ & close_on_exit, false);
 }
 
-void file_descriptor_impl::open(file_handle fd, bool close_on_exit)
+void file_descriptor_impl::open(file_handle fd, flags f)
 {
+ // Using 'close' to close the existing handle so that it will throw an
+ // exception if it fails.
+ //
+ // Only closing after assigning the new handle, so that the class will
+ // take ownership of the handle regardless of whether close throws.
+
+ file_descriptor_impl tmp;
+ tmp.handle_ = handle_;
+ tmp.flags_ = flags_ & close_on_exit ? close_on_close : never_close;
+
     handle_ = fd;
- flags_ = close_on_exit ?
- file_descriptor_impl::close_on_exit :
- 0;
+ flags_ = f;
+
+ tmp.close();
 }
 
 #ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
 
-void file_descriptor_impl::open(int fd, bool close_on_exit)
-{ open(reinterpret_cast<file_handle>(_get_osfhandle(fd)), close_on_exit); }
+void file_descriptor_impl::open(int fd, flags f)
+{ open(reinterpret_cast<file_handle>(_get_osfhandle(fd)), f); }
 
 #endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
 
 void file_descriptor_impl::open(const detail::path& p, BOOST_IOS::openmode mode)
 {
+ close_impl(flags_ & close_on_exit, true);
+
 #ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
     DWORD dwDesiredAccess;
     DWORD dwCreationDisposition;
@@ -157,7 +171,7 @@
                        NULL ); // hTemplateFile
     if (handle != INVALID_HANDLE_VALUE) {
         handle_ = handle;
- flags_ |= close_on_exit;
+ flags_ = close_always;
     } else {
         flags_ = 0;
         throw_system_failure("failed opening file");
@@ -214,7 +228,7 @@
         boost::throw_exception(system_failure("failed opening file"));
     } else {
         handle_ = fd;
- flags_ = close_on_exit;
+ flags_ = close_always;
     }
 #endif // #ifndef BOOST_IOSTREAMS_WINDOWS //----------------------------------//
 }
@@ -224,15 +238,21 @@
 
 void file_descriptor_impl::close()
 {
+ close_impl(flags_ & close_on_close, true);
+}
+
+void file_descriptor_impl::close_impl(bool close_flag, bool throw_) {
     if (handle_ != invalid_handle()) {
- bool success =
- #ifdef BOOST_IOSTREAMS_WINDOWS
- ::CloseHandle(handle_) == 1;
- #else
- BOOST_IOSTREAMS_FD_CLOSE(handle_) != -1;
- #endif
- if (!success)
- throw_system_failure("failed closing file");
+ if (close_flag) {
+ bool success =
+ #ifdef BOOST_IOSTREAMS_WINDOWS
+ ::CloseHandle(handle_) == 1;
+ #else
+ BOOST_IOSTREAMS_FD_CLOSE(handle_) != -1;
+ #endif
+ if (!success && throw_)
+ throw_system_failure("failed closing file");
+ }
         handle_ = invalid_handle();
         flags_ = 0;
     }
@@ -331,15 +351,27 @@
 
 file_descriptor::file_descriptor() : pimpl_(new impl_type) { }
 
+file_descriptor::file_descriptor(handle_type fd, file_descriptor_flags f)
+ : pimpl_(new impl_type)
+{ open(fd, f); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
 file_descriptor::file_descriptor(handle_type fd, bool close_on_exit)
     : pimpl_(new impl_type)
 { open(fd, close_on_exit); }
+#endif
 
 #ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
 
+file_descriptor::file_descriptor(int fd, file_descriptor_flags f)
+ : pimpl_(new impl_type)
+{ open(fd, f); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
 file_descriptor::file_descriptor(int fd, bool close_on_exit)
     : pimpl_(new impl_type)
 { open(fd, close_on_exit); }
+#endif
 
 #endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
 
@@ -357,13 +389,27 @@
     : pimpl_(other.pimpl_)
     { }
 
+void file_descriptor::open(handle_type fd, file_descriptor_flags f)
+{ pimpl_->open(fd, static_cast<detail::file_descriptor_impl::flags>(f)); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
 void file_descriptor::open(handle_type fd, bool close_on_exit)
-{ pimpl_->open(fd, close_on_exit); }
+{ pimpl_->open(fd, close_on_exit ?
+ detail::file_descriptor_impl::close_always :
+ detail::file_descriptor_impl::close_on_close); }
+#endif
 
 #ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
 
+void file_descriptor::open(int fd, file_descriptor_flags f)
+{ pimpl_->open(fd, static_cast<detail::file_descriptor_impl::flags>(f)); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
 void file_descriptor::open(int fd, bool close_on_exit)
-{ pimpl_->open(fd, close_on_exit); }
+{ pimpl_->open(fd, close_on_exit ?
+ detail::file_descriptor_impl::close_always :
+ detail::file_descriptor_impl::close_on_close); }
+#endif
 
 #endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
 
@@ -402,13 +448,24 @@
 //------------------Implementation of file_descriptor_source------------------//
 
 file_descriptor_source::file_descriptor_source(
+ handle_type fd, file_descriptor_flags f)
+{ open(fd, f); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
+file_descriptor_source::file_descriptor_source(
     handle_type fd, bool close_on_exit)
 { open(fd, close_on_exit); }
+#endif
 
 #ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
 
+file_descriptor_source::file_descriptor_source(int fd, file_descriptor_flags f)
+{ open(fd, f); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
 file_descriptor_source::file_descriptor_source(int fd, bool close_on_exit)
 { open(fd, close_on_exit); }
+#endif
 
 #endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
 
@@ -425,13 +482,25 @@
         : file_descriptor(static_cast<const file_descriptor&>(other))
     { }
 
+void file_descriptor_source::open(handle_type fd, file_descriptor_flags f)
+{ file_descriptor::open(fd, f); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
 void file_descriptor_source::open(handle_type fd, bool close_on_exit)
-{ file_descriptor::open(fd, close_on_exit); }
+{ file_descriptor::open(fd, close_on_exit); }
+#endif
 
 #ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
 
+void file_descriptor_source::open(int fd, file_descriptor_flags f)
+{ file_descriptor::open(fd, static_cast<detail::file_descriptor_impl::flags>(f)); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
 void file_descriptor_source::open(int fd, bool close_on_exit)
-{ file_descriptor::open(fd, close_on_exit); }
+{ file_descriptor::open(fd, close_on_exit ?
+ detail::file_descriptor_impl::close_always :
+ detail::file_descriptor_impl::close_on_close); }
+#endif
 
 #endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
 
@@ -454,13 +523,26 @@
 //------------------Implementation of file_descriptor_sink--------------------//
 
 file_descriptor_sink::file_descriptor_sink(
+ handle_type fd, file_descriptor_flags f)
+{ open(fd, f); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
+file_descriptor_sink::file_descriptor_sink(
     handle_type fd, bool close_on_exit)
 { open(fd, close_on_exit); }
+#endif
 
 #ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
 
+file_descriptor_sink::file_descriptor_sink(int fd, file_descriptor_flags f)
+{ open(fd, static_cast<detail::file_descriptor_impl::flags>(f)); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
 file_descriptor_sink::file_descriptor_sink(int fd, bool close_on_exit)
-{ open(fd, close_on_exit); }
+{ open(fd, close_on_exit ?
+ detail::file_descriptor_impl::close_always :
+ detail::file_descriptor_impl::close_on_close); }
+#endif
 
 #endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
 
@@ -476,13 +558,25 @@
     : file_descriptor(static_cast<const file_descriptor&>(other))
     { }
 
+void file_descriptor_sink::open(handle_type fd, file_descriptor_flags f)
+{ file_descriptor::open(fd, f); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
 void file_descriptor_sink::open(handle_type fd, bool close_on_exit)
-{ file_descriptor::open(fd, close_on_exit); }
+{ file_descriptor::open(fd, close_on_exit); }
+#endif
 
 #ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
 
+void file_descriptor_sink::open(int fd, file_descriptor_flags f)
+{ file_descriptor::open(fd, static_cast<detail::file_descriptor_impl::flags>(f)); }
+
+#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
 void file_descriptor_sink::open(int fd, bool close_on_exit)
-{ file_descriptor::open(fd, close_on_exit); }
+{ file_descriptor::open(fd, close_on_exit ?
+ detail::file_descriptor_impl::close_always :
+ detail::file_descriptor_impl::close_on_close); }
+#endif
 
 #endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
 

Modified: trunk/libs/iostreams/test/Jamfile.v2
==============================================================================
--- trunk/libs/iostreams/test/Jamfile.v2 (original)
+++ trunk/libs/iostreams/test/Jamfile.v2 2010-06-29 10:15:13 EDT (Tue, 29 Jun 2010)
@@ -33,6 +33,24 @@
         ] ;
 }
 
+rule compile-fail-iostreams ( sources * : requirements * : target-name ? ) {
+ return [
+ compile-fail
+ $(sources)
+ /boost/test//boost_unit_test_framework/<link>static
+ /boost/filesystem//boost_filesystem/<link>static
+ : # build requirements
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>cw-9.3,<os>darwin:<runtime-link>static
+ <define>BOOST_IOSTREAMS_NO_LIB
+ <link>shared:<define>BOOST_IOSTREAMS_DYN_LINK=1
+ $(requirements)
+ : $(target-name)
+ ] ;
+}
+
+
     local all-tests =
           [ test-iostreams array_test.cpp ]
           [ test-iostreams auto_close_test.cpp ]
@@ -52,6 +70,12 @@
           [ test-iostreams file_test.cpp ]
           [ test-iostreams file_descriptor_test.cpp
                 ../build//boost_iostreams ]
+ [ test-iostreams deprecated_file_descriptor_test.cpp
+ ../build//boost_iostreams
+ : <define>BOOST_IOSTREAMS_USE_DEPRECATED ]
+ [ compile-fail-iostreams deprecated_file_descriptor_test.cpp
+ :
+ : deprecated_file_descriptor_fail ]
           [ test-iostreams filtering_stream_test.cpp ]
           [ test-iostreams finite_state_filter_test.cpp ]
           [ test-iostreams flush_test.cpp ]

Added: trunk/libs/iostreams/test/deprecated_file_descriptor_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/iostreams/test/deprecated_file_descriptor_test.cpp 2010-06-29 10:15:13 EDT (Tue, 29 Jun 2010)
@@ -0,0 +1,235 @@
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+#include "detail/file_handle.hpp"
+
+// Test file_descriptor with the depreacted constructors.
+
+namespace boost_ios = boost::iostreams;
+namespace ios_test = boost::iostreams::test;
+
+void deprecated_file_descriptor_test()
+{
+ typedef boost_ios::stream<boost_ios::file_descriptor_source> fdistream;
+ typedef boost_ios::stream<boost_ios::file_descriptor_sink> fdostream;
+ typedef boost_ios::stream<boost_ios::file_descriptor> fdstream;
+
+ ios_test::test_file test1;
+ ios_test::test_file test2;
+
+ //--------------Deprecated file descriptor constructor--------------------//
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ boost_ios::file_descriptor_source source1(handle);
+ BOOST_CHECK(source1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ ios_test::close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ boost_ios::file_descriptor_source source1(handle, false);
+ BOOST_CHECK(source1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ ios_test::close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ boost_ios::file_descriptor_source source1(handle, true);
+ BOOST_CHECK(source1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ boost_ios::file_descriptor_source source1(handle);
+ BOOST_CHECK(source1.handle() == handle);
+ source1.close();
+ BOOST_CHECK(!source1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ boost_ios::file_descriptor_source source1(handle, false);
+ BOOST_CHECK(source1.handle() == handle);
+ source1.close();
+ BOOST_CHECK(!source1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ boost_ios::file_descriptor_source source1(handle, true);
+ BOOST_CHECK(source1.handle() == handle);
+ source1.close();
+ BOOST_CHECK(!source1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ //--------------Deprecated file descriptor open---------------------------//
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ boost_ios::file_descriptor_source source1;
+ source1.open(handle);
+ BOOST_CHECK(source1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ ios_test::close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ boost_ios::file_descriptor_source source1;
+ source1.open(handle, false);
+ BOOST_CHECK(source1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ ios_test::close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ boost_ios::file_descriptor_source source1;
+ source1.open(handle, true);
+ BOOST_CHECK(source1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ boost_ios::file_descriptor_source source1;
+ source1.open(handle);
+ BOOST_CHECK(source1.handle() == handle);
+ source1.close();
+ BOOST_CHECK(!source1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ boost_ios::file_descriptor_source source1;
+ source1.open(handle, false);
+ BOOST_CHECK(source1.handle() == handle);
+ source1.close();
+ BOOST_CHECK(!source1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ boost_ios::file_descriptor_source source1;
+ source1.open(handle, true);
+ BOOST_CHECK(source1.handle() == handle);
+ source1.close();
+ BOOST_CHECK(!source1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ //--------------Deprecated open with existing descriptor------------------//
+
+ {
+ boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name());
+
+ {
+ boost_ios::file_descriptor_source source1(handle1);
+ BOOST_CHECK(source1.handle() == handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ source1.open(handle2);
+ BOOST_CHECK(source1.handle() == handle2);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ source1.close();
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+
+ ios_test::close_file_handle(handle1);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name());
+
+ {
+ boost_ios::file_descriptor_source source1(handle1, true);
+ BOOST_CHECK(source1.handle() == handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ source1.open(handle2);
+ BOOST_CHECK(source1.handle() == handle2);
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ source1.close();
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name());
+
+ {
+ boost_ios::file_descriptor_source source1(handle1, false);
+ BOOST_CHECK(source1.handle() == handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ source1.open(handle2, false);
+ BOOST_CHECK(source1.handle() == handle2);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+
+ ios_test::close_file_handle(handle1);
+ ios_test::close_file_handle(handle2);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name());
+
+ {
+ boost_ios::file_descriptor_source source1(handle1, true);
+ BOOST_CHECK(source1.handle() == handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ source1.open(handle2, true);
+ BOOST_CHECK(source1.handle() == handle2);
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+ }
+}
+
+boost::unit_test::test_suite* init_unit_test_suite(int, char* [])
+{
+ boost::unit_test::test_suite* test = BOOST_TEST_SUITE("deprecated file_descriptor test");
+ test->add(BOOST_TEST_CASE(&deprecated_file_descriptor_test));
+ return test;
+}

Added: trunk/libs/iostreams/test/detail/file_handle.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/iostreams/test/detail/file_handle.hpp 2010-06-29 10:15:13 EDT (Tue, 29 Jun 2010)
@@ -0,0 +1,100 @@
+// (C) Copyright 2010 Daniel James
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2003-2007 Jonathan Turkanis
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
+
+// A few methods for getting and manipulating file handles.
+
+#ifndef BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED
+#define BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED
+
+#include <boost/iostreams/detail/file_handle.hpp>
+#include <boost/iostreams/detail/config/rtl.hpp>
+#include <boost/test/test_tools.hpp>
+#include <fcntl.h>
+#include <string>
+
+namespace boost { namespace iostreams { namespace test {
+
+#ifdef BOOST_IOSTREAMS_WINDOWS
+
+// Windows implementation
+
+boost::iostreams::detail::file_handle open_file_handle(std::string const& name)
+{
+ HANDLE handle =
+ ::CreateFileA( name.c_str(),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, // lpSecurityAttributes
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL ); // hTemplateFile
+
+ BOOST_REQUIRE (handle != INVALID_HANDLE_VALUE);
+ return HANDLE;
+}
+
+void close_file_handle(boost::iostreams::detail::file_handle handle)
+{
+ BOOST_REQUIRE(::CloseHandle(handle) == 1);
+}
+
+#define BOOST_CHECK_HANDLE_CLOSED(handle)
+#define BOOST_CHECK_HANDLE_OPEN(handle)
+
+#else // BOOST_IOSTREAMS_WINDOWS
+
+// Non-windows implementation
+
+boost::iostreams::detail::file_handle open_file_handle(std::string const& name)
+{
+ int oflag = O_RDWR;
+
+ #ifdef _LARGEFILE64_SOURCE
+ oflag |= O_LARGEFILE;
+ #endif
+
+ // Calculate pmode argument to open.
+
+ mode_t pmode = S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IWGRP |
+ S_IROTH | S_IWOTH;
+
+ // Open file.
+
+ int fd = BOOST_IOSTREAMS_FD_OPEN(name.c_str(), oflag, pmode);
+ BOOST_REQUIRE (fd != -1);
+
+ return fd;
+}
+
+void close_file_handle(boost::iostreams::detail::file_handle handle)
+{
+ BOOST_REQUIRE(BOOST_IOSTREAMS_FD_CLOSE(handle) != -1);
+}
+
+// This is pretty dubious. First you must make sure that no other
+// operations that could open a descriptor are called before this
+// check, otherwise it's quite likely that a closed descriptor
+// could be used. Secondly, I'm not sure if it's guaranteed that
+// fcntl will know that the descriptor is closed but this seems
+// to work okay, and I can't see any other convenient way to check
+// that a descripter has been closed.
+bool is_handle_open(boost::iostreams::detail::file_handle handle)
+{
+ return ::fcntl(handle, F_GETFD) != -1;
+}
+
+#define BOOST_CHECK_HANDLE_CLOSED(handle) \
+ BOOST_CHECK(!::boost::iostreams::test::is_handle_open(handle))
+#define BOOST_CHECK_HANDLE_OPEN(handle) \
+ BOOST_CHECK(::boost::iostreams::test::is_handle_open(handle))
+
+
+#endif // BOOST_IOSTREAMS_WINDOWS
+
+}}}
+
+#endif // BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED

Modified: trunk/libs/iostreams/test/file_descriptor_test.cpp
==============================================================================
--- trunk/libs/iostreams/test/file_descriptor_test.cpp (original)
+++ trunk/libs/iostreams/test/file_descriptor_test.cpp 2010-06-29 10:15:13 EDT (Tue, 29 Jun 2010)
@@ -6,16 +6,19 @@
 // See http://www.boost.org/libs/iostreams for documentation.
 
 #include <fstream>
+#include <fcntl.h>
 #include <boost/iostreams/device/file_descriptor.hpp>
 #include <boost/iostreams/stream.hpp>
 #include <boost/test/test_tools.hpp>
 #include <boost/test/unit_test.hpp>
 #include "detail/temp_file.hpp"
 #include "detail/verification.hpp"
+#include "detail/file_handle.hpp"
 
 using namespace boost;
 using namespace boost::iostreams;
 using namespace boost::iostreams::test;
+namespace boost_ios = boost::iostreams;
 using std::ifstream;
 using boost::unit_test::test_suite;
 
@@ -80,7 +83,7 @@
         first->close();
         BOOST_CHECK(!first->is_open());
     }
-
+
     // test illegal flag combinations
     {
         BOOST_CHECK_THROW(
@@ -507,9 +510,125 @@
     }
 }
 
+void file_handle_test()
+{
+ test_file test1;
+ test_file test2;
+
+ {
+ boost_ios::detail::file_handle handle = open_file_handle(test1.name());
+ {
+ boost_ios::file_descriptor_source source1(handle, boost_ios::never_close_handle);
+ BOOST_CHECK(source1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = open_file_handle(test1.name());
+ {
+ boost_ios::file_descriptor_source source1(handle, boost_ios::close_handle);
+ BOOST_CHECK(source1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = open_file_handle(test1.name());
+ boost_ios::file_descriptor_source source1(handle, boost_ios::never_close_handle);
+ BOOST_CHECK(source1.handle() == handle);
+ source1.close();
+ BOOST_CHECK(!source1.is_open());
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = open_file_handle(test1.name());
+ boost_ios::file_descriptor_source source1(handle, boost_ios::close_handle);
+ BOOST_CHECK(source1.handle() == handle);
+ source1.close();
+ BOOST_CHECK(!source1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = open_file_handle(test2.name());
+ {
+ boost_ios::file_descriptor_source source1(handle1, boost_ios::never_close_handle);
+ BOOST_CHECK(source1.handle() == handle1);
+ source1.open(handle2, boost_ios::never_close_handle);
+ BOOST_CHECK(source1.handle() == handle2);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ close_file_handle(handle1);
+ close_file_handle(handle2);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = open_file_handle(test2.name());
+ {
+ boost_ios::file_descriptor_source source1(handle1, boost_ios::close_handle);
+ BOOST_CHECK(source1.handle() == handle1);
+ source1.open(handle2, boost_ios::close_handle);
+ BOOST_CHECK(source1.handle() == handle2);
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = open_file_handle(test2.name());
+ {
+ boost_ios::file_descriptor_source source1(handle1, boost_ios::close_handle);
+ BOOST_CHECK(source1.handle() == handle1);
+ source1.open(handle2, boost_ios::never_close_handle);
+ BOOST_CHECK(source1.handle() == handle2);
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ close_file_handle(handle2);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = open_handle(test1.name());
+ {
+ boost_ios::file_descriptor_source source1;
+ BOOST_CHECK(!source1.is_open());
+ source1.open(handle, boost_ios::never_close_handle);
+ BOOST_CHECK(source1.handle() == handle);
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = open_handle(test1.name());
+ {
+ boost_ios::file_descriptor_source source1;
+ BOOST_CHECK(!source1.is_open());
+ source1.open(handle, boost_ios::close_handle);
+ BOOST_CHECK(source1.handle() == handle);
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+}
+
 test_suite* init_unit_test_suite(int, char* [])
 {
     test_suite* test = BOOST_TEST_SUITE("file_descriptor test");
     test->add(BOOST_TEST_CASE(&file_descriptor_test));
+ test->add(BOOST_TEST_CASE(&file_handle_test));
     return test;
 }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk