stdcpp/tsrc/Boost_test/smart_ptr/src/weak_ptr_mt_test.cpp
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stdcpp/tsrc/Boost_test/smart_ptr/src/weak_ptr_mt_test.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,233 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786)  // identifier truncated in debug info
+#pragma warning(disable: 4710)  // function not inlined
+#pragma warning(disable: 4711)  // function selected for automatic inline expansion
+#pragma warning(disable: 4514)  // unreferenced inline removed
+#endif
+
+//
+//  weak_ptr_mt_test.cpp
+//
+//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+//  Copyright 2005 Peter Dimov
+//
+// 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)
+//
+/*
+ * © Portions copyright (c) 2006-2007 Nokia Corporation.  All rights reserved.
+*/
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/bind.hpp>
+
+#include <vector>
+#include <memory>
+#include <stdexcept>
+
+#include <cstdio>
+#include <ctime>
+#include <cstdlib>
+#include <string>
+
+#ifdef __SYMBIAN32__
+#include "std_log_result.h"
+#define LOG_FILENAME_LINE __FILE__, __LINE__
+#endif
+
+// 'portable' thread framework
+
+class abstract_thread
+{
+public:
+
+    virtual ~abstract_thread() {}
+    virtual void run() = 0;
+};
+
+#if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS)
+
+char const * title = "Using Windows threads";
+
+#include <windows.h>
+#include <process.h>
+
+typedef HANDLE pthread_t;
+
+unsigned __stdcall common_thread_routine(void * pv)
+{
+    abstract_thread * pt = static_cast<abstract_thread *>(pv);
+    pt->run();
+    delete pt;
+    return 0;
+}
+
+int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg)
+{
+    HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0);
+
+    if(h != 0)
+    {
+        *thread = h;
+        return 0;
+    }
+    else
+    {
+        return 1; // return errno;
+    }
+}
+
+int pthread_join(pthread_t thread, void ** /*value_ptr*/)
+{
+    ::WaitForSingleObject(thread, INFINITE);
+    ::CloseHandle(thread);
+    return 0;
+}
+
+#else
+
+char const * title = "Using POSIX threads";
+
+#include <pthread.h>
+
+extern "C" void * common_thread_routine(void * pv)
+{
+    abstract_thread * pt = static_cast<abstract_thread *>(pv);
+    pt->run();
+    delete pt;
+    return 0;
+}
+
+#endif
+
+//
+
+template<class F> class thread: public abstract_thread
+{
+public:
+
+    explicit thread(F f): f_(f)
+    {
+    }
+
+    void run()
+    {
+        f_();
+    }
+
+private:
+
+    F f_;
+};
+
+template<class F> pthread_t createThread(F f)
+{
+    std::auto_ptr<abstract_thread> p(new thread<F>(f));
+
+    pthread_t r;
+
+    if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0)
+    {
+        p.release();
+        return r;
+    }
+
+   	throw std::runtime_error("createThread failed.");
+}
+
+//
+#ifdef __SYMBIAN32__
+int const n = 1024;
+#else
+int const n = 16384;
+#endif
+int const k = 512; // vector size
+int const m = 16; // threads
+
+void test( std::vector< boost::shared_ptr<int> > & v )
+{
+    using namespace std; // printf, rand
+
+    std::vector< boost::weak_ptr<int> > w( v.begin(), v.end() );
+
+    int s = 0, f = 0, r = 0;
+
+    for( int i = 0; i < n; ++i )
+    {
+        // randomly kill a pointer
+
+        v[ rand() % k ].reset();
+        ++s;
+
+        for( int j = 0; j < k; ++j )
+        {
+            if( boost::shared_ptr<int> px = w[ j ].lock() )
+            {
+                ++s;
+
+                if( rand() & 4 )
+                {
+                    continue;
+                }
+
+                // rebind anyway with prob. 50% for add_ref_lock() against weak_release() contention
+                ++f;
+            }
+            else
+            {
+                ++r;
+            }
+
+            w[ j ] = v[ rand() % k ];
+        }
+    }
+
+    printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r );
+}
+
+int main()
+{
+    std_log(LOG_FILENAME_LINE,"[Test Case for weak_ptr_mt_test]");
+    using namespace std; // printf, clock_t, clock
+
+    printf("%s: %d threads, %d * %d iterations: ", title, m, n, k );
+
+    std::vector< boost::shared_ptr<int> > v( k );
+
+    for( int i = 0; i < k; ++i )
+    {
+        v[ i ].reset( new int( 0 ) );
+    }
+
+    clock_t t = clock();
+
+    pthread_t a[m];
+
+    for(int i = 0; i < m; ++i)
+    {
+        a[i] = createThread( boost::bind( test, v ) );
+    }
+
+    v.resize( 0 ); // kill original copies
+
+    for(int j = 0; j < m; ++j)
+    {
+        pthread_join( a[j], 0 );
+    }
+
+    t = clock() - t;
+
+    printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLK_TCK);
+
+#ifdef __SYMBIAN32__
+	std_log(LOG_FILENAME_LINE,"Result : Passed");
+	std_log(LOG_FILENAME_LINE,"[End Test Case ]");
+#endif
+	testResultXml("weak_ptr_mt_test");
+	close_log_file();
+    return 0;
+}