Boost logo

Boost-Commit :

From: john.groups_at_[hidden]
Date: 2007-11-02 22:58:20


Author: jtorjo
Date: 2007-11-02 22:58:19 EDT (Fri, 02 Nov 2007)
New Revision: 40711
URL: http://svn.boost.org/trac/boost/changeset/40711

Log:
[logging]
v0.10.3, 2 nov 2007
- added TSS tests
  - test test_tss works fine under VS 2005
  - test test_ts_resource not yet implemented

Added:
   sandbox/logging/lib/logging/tests/test_tss/count.h (contents, props changed)
   sandbox/logging/lib/logging/tests/test_tss/test_tss_objects.cpp (contents, props changed)
   sandbox/logging/lib/logging/tests/test_tss/test_tss_on_end_delete.cpp (contents, props changed)
Properties modified:
   sandbox/logging/lib/logging/tests/test_tss/ (props changed)
Text files modified:
   sandbox/logging/boost/logging/detail/raw_doc/changelog.hpp | 5
   sandbox/logging/boost/logging/detail/tss/tss_ensure_proper_delete.hpp | 29 +++++++
   sandbox/logging/boost/logging/detail/tss/tss_impl_pthread.hpp | 3
   sandbox/logging/boost/logging/detail/tss/tss_impl_win32.hpp | 14 ++-
   sandbox/logging/lib/logging/tests/test_tss/test_tss.cpp | 139 ++++-----------------------------------
   sandbox/logging/lib/logging/tests/test_tss/test_tss.vcproj | 12 +++
   6 files changed, 68 insertions(+), 134 deletions(-)

Modified: sandbox/logging/boost/logging/detail/raw_doc/changelog.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/raw_doc/changelog.hpp (original)
+++ sandbox/logging/boost/logging/detail/raw_doc/changelog.hpp 2007-11-02 22:58:19 EDT (Fri, 02 Nov 2007)
@@ -1,8 +1,9 @@
 /**
 @page page_changelog Changelog
 
-v0.10.2, 2 nov 2007
-- added TSS tests - they do run; however, they don't work successfully (they cause memory corruption)
+v0.10.3, 2 nov 2007
+- added TSS tests
+ - test test_tss works fine under VS 2005
 - added TSS - however, not tested (TSS is off, for now)
 - compiles on VS2005, gcc 3.4.2 , gcc 4.1 and gcc 4.3
 

Modified: sandbox/logging/boost/logging/detail/tss/tss_ensure_proper_delete.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/tss/tss_ensure_proper_delete.hpp (original)
+++ sandbox/logging/boost/logging/detail/tss/tss_ensure_proper_delete.hpp 2007-11-02 22:58:19 EDT (Fri, 02 Nov 2007)
@@ -23,6 +23,7 @@
 
 #include <boost/logging/detail/fwd.hpp>
 #include <vector>
+#include <stdlib.h>
 
 namespace boost { namespace logging { namespace detail {
 
@@ -36,27 +37,49 @@
     type * m_val;
 };
 
+#ifdef BOOST_LOG_TEST_TSS
+// just for testing
+void on_end_delete_objects();
+#endif
+
 struct delete_array : std::vector< do_delete_base* > {
+ typedef boost::logging::threading::mutex mutex;
+ typedef std::vector< do_delete_base* > vector_base;
+
     ~delete_array () {
         for ( const_iterator b = begin(), e = end(); b != e; ++b)
             delete *b;
+
+#ifdef BOOST_LOG_TEST_TSS
+ on_end_delete_objects();
+#endif
+ }
+ void push_back(do_delete_base* p) {
+ mutex::scoped_lock lk(cs);
+ vector_base::push_back(p);
     }
+private:
+ mutex cs;
 };
 
+
 inline delete_array & object_deleter() {
- static delete_array a;
+ static delete_array a ;
     return a;
 }
 
+
 template<class type> inline type * new_object_ensure_delete() {
     type * val = new type;
- object_deleter().push_back( new do_delete<type>(val) );
+ delete_array & del = object_deleter();
+ del.push_back( new do_delete<type>(val) );
     return val;
 }
 
 template<class type> inline type * new_object_ensure_delete(const type & init) {
     type * val = new type(init);
- object_deleter().push_back( new do_delete<type>(val) );
+ delete_array & del = object_deleter();
+ del.push_back( new do_delete<type>(val) );
     return val;
 }
 

Modified: sandbox/logging/boost/logging/detail/tss/tss_impl_pthread.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/tss/tss_impl_pthread.hpp (original)
+++ sandbox/logging/boost/logging/detail/tss/tss_impl_pthread.hpp 2007-11-02 22:58:19 EDT (Fri, 02 Nov 2007)
@@ -55,6 +55,9 @@
 inline void init_tss_data()
 {
     pthread_key_create(&tss_data_native_key(), &cleanup_slots);
+
+ // make sure the static gets created
+ object_deleter();
 }
 
 

Modified: sandbox/logging/boost/logging/detail/tss/tss_impl_win32.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/tss/tss_impl_win32.hpp (original)
+++ sandbox/logging/boost/logging/detail/tss/tss_impl_win32.hpp 2007-11-02 22:58:19 EDT (Fri, 02 Nov 2007)
@@ -46,20 +46,28 @@
 
 typedef std::vector<void*> tss_slots;
 
+DWORD& tss_data_native_key () ;
+void init_tss_data();
+unsigned long slot_idx() ;
+tss_slots* get_slots();
+
+
 inline DWORD& tss_data_native_key () {
     static DWORD key = TLS_OUT_OF_INDEXES;
     return key;
 }
 
 // note: this should be called ONLY ONCE
-inline void init_tss_data()
-{
+inline void init_tss_data() {
     //Allocate tls slot
 
     // if you get an assertion here, this function was called twice - should never happen!
     BOOST_ASSERT( tss_data_native_key() == TLS_OUT_OF_INDEXES);
     // now, allocate it
     tss_data_native_key() = TlsAlloc();
+
+ // make sure the static gets created
+ object_deleter();
 }
 
 inline unsigned long slot_idx() {
@@ -78,8 +86,6 @@
     return idx;
 }
 
-
-
 inline tss_slots* get_slots()
 {
     tss_slots* slots = 0;

Added: sandbox/logging/lib/logging/tests/test_tss/count.h
==============================================================================
--- (empty file)
+++ sandbox/logging/lib/logging/tests/test_tss/count.h 2007-11-02 22:58:19 EDT (Fri, 02 Nov 2007)
@@ -0,0 +1,43 @@
+#ifndef object_count_h
+#define object_count_h
+
+#include <boost/thread/mutex.hpp>
+
+/*
+ counts the number of objects.
+ When it's destroyed, there should be no objects left.
+*/
+struct object_count {
+ typedef boost::mutex mutex;
+ typedef mutex::scoped_lock scoped_lock;
+
+ object_count() : m_count(0) {
+ }
+
+ ~object_count() {
+ scoped_lock lk(m_cs);
+// BOOST_ASSERT(m_count == 0);
+ }
+
+ void increment() {
+ scoped_lock lk(m_cs);
+ ++m_count;
+ }
+
+ void decrement() {
+ scoped_lock lk(m_cs);
+ --m_count;
+ BOOST_ASSERT(m_count >= 0);
+ }
+
+ int count() const {
+ scoped_lock lk(m_cs);
+ return m_count;
+ }
+
+private:
+ mutable mutex m_cs;
+ int m_count;
+};
+
+#endif

Modified: sandbox/logging/lib/logging/tests/test_tss/test_tss.cpp
==============================================================================
--- sandbox/logging/lib/logging/tests/test_tss/test_tss.cpp (original)
+++ sandbox/logging/lib/logging/tests/test_tss/test_tss.cpp 2007-11-02 22:58:19 EDT (Fri, 02 Nov 2007)
@@ -15,13 +15,18 @@
     The thread information is all kept using TSS
 
 
+
+ Note: I've split the logic on multiple files, to test to see that we don't run into the Meyers Singleton bug.
+
 */
 
+// so that we can catch the end of deleting all objects
+#define BOOST_LOG_TEST_TSS
+
 #define BOOST_LOG_TSS_USE_INTERNAL
 // this includes tss_value class
 #include <boost/logging/logging.hpp>
 #include <boost/thread/thread.hpp>
-#include <boost/thread/mutex.hpp>
 #include <boost/thread/xtime.hpp>
 #include <boost/bind.hpp>
 #include <boost/assert.hpp>
@@ -30,138 +35,21 @@
 #include <fstream>
 #include <sstream>
 #include <iostream>
+#include "count.h"
 
 using namespace boost;
 
 // creating this (a log, or a filter), makes sure we initialize TSS
 BOOST_DEFINE_LOG_FILTER_WITH_ARGS(g_log_filter, filter::use_tss_with_cache , 10)
 
-
-/*
- counts the number of objects.
- When it's destroyed, there should be no objects left.
-*/
-struct object_count {
- typedef mutex::scoped_lock scoped_lock;
-
- object_count() : m_count(0) {}
-
- ~object_count() {
- scoped_lock lk(m_cs);
- BOOST_ASSERT(m_count == 0);
- }
-
- void increment() {
- scoped_lock lk(m_cs);
- ++m_count;
- }
-
- void decrement() {
- scoped_lock lk(m_cs);
- --m_count;
- }
-
- int count() const {
- scoped_lock lk(m_cs);
- return m_count;
- }
-
-private:
- mutable mutex m_cs;
- int m_count;
-};
-
-
-object_count g_object_count;
-object_count g_running_thread_count;
+extern object_count * g_object_count ;
+extern object_count * g_running_thread_count ;
 
 // the actual number of started threads
 int g_thread_count = 50;
 
-
-struct managed_object {
- managed_object(object_count & counter) : m_counter(counter) {
- m_counter.increment();
- }
- ~managed_object() {
- m_counter.decrement();
- }
-private:
- object_count & m_counter;
-};
-
-struct read_file : private managed_object {
- // read this file itself
- read_file() : managed_object(g_object_count), m_in(new std::ifstream("test_tss.cpp")), m_word_idx(0) {
- }
-
- std::string read_word() {
- ++m_word_idx;
- if ( m_word_idx < g_thread_count) {
- std::string word;
- (*m_in) >> word;
- return word;
- }
- else
- return "";
- }
-
-private:
- boost::shared_ptr<std::ifstream> m_in;
- int m_word_idx;
-};
-
-struct string_no_spaces : private managed_object {
- string_no_spaces() : managed_object(g_object_count) {}
-
- void add_word(const std::string & word) {
- m_str += word;
- }
-
- char at_idx(int idx) {
- if ( idx < (int)m_str.size())
- return m_str[idx];
- else
- return ' ';
- }
-
-private:
- std::string m_str;
-};
-
-void do_sleep(int ms) {
- xtime next;
- xtime_get( &next, TIME_UTC);
- next.nsec += ms * 1000;
-
- int nano_per_sec = 1000000000;
- next.sec += next.nsec / nano_per_sec;
- next.nsec %= nano_per_sec;
- thread::sleep( next);
-}
-
-void process_file() {
- managed_object m(g_running_thread_count);
- int thread_idx = g_running_thread_count.count();
- std::cout << "started thread " << thread_idx << std::endl;
-
- using namespace logging;
- tss_value<read_file> file;
- tss_value<string_no_spaces> str;
- while ( true) {
- std::string word = file->read_word();
- str->add_word(word);
- if ( word.empty() )
- break;
- do_sleep(1);
- }
-
- std::cout << "char at idx " << thread_idx << ":" << str->at_idx(thread_idx) << std::endl ;
-
- std::cout << "ended thread " << thread_idx << std::endl;
-}
-
-
+void do_sleep(int ms) ;
+void process_file() ;
 
 int main(int argc, char* argv[])
 {
@@ -174,9 +62,10 @@
     for ( int idx = 0; idx < g_thread_count ; ++idx)
         thread t( &process_file);
 
- while ( g_running_thread_count.count() > 0 ) {
+ do_sleep(1000);
+ while ( g_running_thread_count->count() > 0 ) {
         do_sleep(100);
- std::cout << "remaining running threads " << g_running_thread_count.count() << std::endl;
+ std::cout << "remaining running threads " << g_running_thread_count->count() << std::endl;
     }
         return 0;
 }

Modified: sandbox/logging/lib/logging/tests/test_tss/test_tss.vcproj
==============================================================================
--- sandbox/logging/lib/logging/tests/test_tss/test_tss.vcproj (original)
+++ sandbox/logging/lib/logging/tests/test_tss/test_tss.vcproj 2007-11-02 22:58:19 EDT (Fri, 02 Nov 2007)
@@ -172,9 +172,21 @@
         </References>
         <Files>
                 <File
+ RelativePath=".\count.h"
+ >
+ </File>
+ <File
                         RelativePath=".\test_tss.cpp"
>
                 </File>
+ <File
+ RelativePath=".\test_tss_objects.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\test_tss_on_end_delete.cpp"
+ >
+ </File>
         </Files>
         <Globals>
         </Globals>

Added: sandbox/logging/lib/logging/tests/test_tss/test_tss_objects.cpp
==============================================================================
--- (empty file)
+++ sandbox/logging/lib/logging/tests/test_tss/test_tss_objects.cpp 2007-11-02 22:58:19 EDT (Fri, 02 Nov 2007)
@@ -0,0 +1,119 @@
+
+// so that we can catch the end of deleting all objects
+#define BOOST_LOG_TEST_TSS
+
+#define BOOST_LOG_TSS_USE_INTERNAL
+// this includes tss_value class
+#include <boost/logging/logging.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/xtime.hpp>
+#include <boost/bind.hpp>
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include "count.h"
+
+using namespace boost;
+
+
+
+
+
+// we specifically let these 2 objects leak - making them static, would destroy them too soon (before the other objects being destroyed)
+object_count * g_object_count = new object_count;
+object_count * g_running_thread_count = new object_count;
+
+extern int g_thread_count ;
+
+
+
+struct managed_object {
+ managed_object(object_count & counter) : m_counter(counter) {
+ m_counter.increment();
+ }
+ managed_object(const managed_object& other) : m_counter(other.m_counter) {
+ m_counter.increment();
+ }
+ ~managed_object() {
+ m_counter.decrement();
+ }
+private:
+ object_count & m_counter;
+};
+
+struct read_file : private managed_object {
+ // read this file itself
+ read_file() : managed_object(*g_object_count), m_in(new std::ifstream("test_tss.cpp")), m_word_idx(0) {
+ }
+
+ std::string read_word() {
+ ++m_word_idx;
+ if ( m_word_idx < g_thread_count) {
+ std::string word;
+ (*m_in) >> word;
+ return word;
+ }
+ else
+ return "";
+ }
+
+private:
+ boost::shared_ptr<std::ifstream> m_in;
+ int m_word_idx;
+};
+
+struct string_no_spaces : private managed_object {
+ string_no_spaces() : managed_object(*g_object_count) {}
+
+ void add_word(const std::string & word) {
+ m_str += word;
+ }
+
+ char at_idx(int idx) {
+ if ( idx < (int)m_str.size())
+ return m_str[idx];
+ else
+ return ' ';
+ }
+
+private:
+ std::string m_str;
+};
+
+void do_sleep(int ms) {
+ xtime next;
+ xtime_get( &next, TIME_UTC);
+ next.nsec += ms * 1000;
+
+ int nano_per_sec = 1000000000;
+ next.sec += next.nsec / nano_per_sec;
+ next.nsec %= nano_per_sec;
+ thread::sleep( next);
+}
+
+void process_file() {
+ managed_object m(*g_running_thread_count);
+ int thread_idx = g_running_thread_count->count();
+ std::cout << "started thread " << thread_idx << std::endl;
+
+ using namespace logging;
+ tss_value<read_file> file;
+ tss_value<string_no_spaces> str;
+ while ( true) {
+
+ std::string word = file->read_word();
+ str->add_word(word);
+ if ( word.empty() )
+ break;
+ do_sleep(5);
+ }
+
+ std::cout << "char at idx " << thread_idx << ":" << str->at_idx(thread_idx) << std::endl ;
+
+ std::cout << "ended thread " << thread_idx << std::endl;
+}
+

Added: sandbox/logging/lib/logging/tests/test_tss/test_tss_on_end_delete.cpp
==============================================================================
--- (empty file)
+++ sandbox/logging/lib/logging/tests/test_tss/test_tss_on_end_delete.cpp 2007-11-02 22:58:19 EDT (Fri, 02 Nov 2007)
@@ -0,0 +1,34 @@
+
+// so that we can catch the end of deleting all objects
+#define BOOST_LOG_TEST_TSS
+
+#define BOOST_LOG_TSS_USE_INTERNAL
+// this includes tss_value class
+#include <boost/logging/logging.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/xtime.hpp>
+#include <boost/bind.hpp>
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include "count.h"
+
+using namespace boost;
+
+
+
+// we specifically let these 2 objects leak - making them static, would destroy them too soon (before the other objects being destroyed)
+extern object_count * g_object_count ;
+extern object_count * g_running_thread_count ;
+
+namespace boost { namespace logging { namespace detail {
+void on_end_delete_objects() {
+ BOOST_ASSERT( g_object_count->count() == 0);
+}
+
+}}}
+


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