stdcpp/tsrc/Boost_test/smart_ptr/src/weak_ptr_mt_test.cpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 #include <boost/config.hpp>
       
     2 
       
     3 #if defined(BOOST_MSVC)
       
     4 #pragma warning(disable: 4786)  // identifier truncated in debug info
       
     5 #pragma warning(disable: 4710)  // function not inlined
       
     6 #pragma warning(disable: 4711)  // function selected for automatic inline expansion
       
     7 #pragma warning(disable: 4514)  // unreferenced inline removed
       
     8 #endif
       
     9 
       
    10 //
       
    11 //  weak_ptr_mt_test.cpp
       
    12 //
       
    13 //  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
       
    14 //  Copyright 2005 Peter Dimov
       
    15 //
       
    16 // Distributed under the Boost Software License, Version 1.0. (See
       
    17 // accompanying file LICENSE_1_0.txt or copy at
       
    18 // http://www.boost.org/LICENSE_1_0.txt)
       
    19 //
       
    20 /*
       
    21  * © Portions copyright (c) 2006-2007 Nokia Corporation.  All rights reserved.
       
    22 */
       
    23 
       
    24 #include <boost/shared_ptr.hpp>
       
    25 #include <boost/weak_ptr.hpp>
       
    26 #include <boost/bind.hpp>
       
    27 
       
    28 #include <vector>
       
    29 #include <memory>
       
    30 #include <stdexcept>
       
    31 
       
    32 #include <cstdio>
       
    33 #include <ctime>
       
    34 #include <cstdlib>
       
    35 #include <string>
       
    36 
       
    37 #ifdef __SYMBIAN32__
       
    38 #include "std_log_result.h"
       
    39 #define LOG_FILENAME_LINE __FILE__, __LINE__
       
    40 #endif
       
    41 
       
    42 // 'portable' thread framework
       
    43 
       
    44 class abstract_thread
       
    45 {
       
    46 public:
       
    47 
       
    48     virtual ~abstract_thread() {}
       
    49     virtual void run() = 0;
       
    50 };
       
    51 
       
    52 #if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS)
       
    53 
       
    54 char const * title = "Using Windows threads";
       
    55 
       
    56 #include <windows.h>
       
    57 #include <process.h>
       
    58 
       
    59 typedef HANDLE pthread_t;
       
    60 
       
    61 unsigned __stdcall common_thread_routine(void * pv)
       
    62 {
       
    63     abstract_thread * pt = static_cast<abstract_thread *>(pv);
       
    64     pt->run();
       
    65     delete pt;
       
    66     return 0;
       
    67 }
       
    68 
       
    69 int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg)
       
    70 {
       
    71     HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0);
       
    72 
       
    73     if(h != 0)
       
    74     {
       
    75         *thread = h;
       
    76         return 0;
       
    77     }
       
    78     else
       
    79     {
       
    80         return 1; // return errno;
       
    81     }
       
    82 }
       
    83 
       
    84 int pthread_join(pthread_t thread, void ** /*value_ptr*/)
       
    85 {
       
    86     ::WaitForSingleObject(thread, INFINITE);
       
    87     ::CloseHandle(thread);
       
    88     return 0;
       
    89 }
       
    90 
       
    91 #else
       
    92 
       
    93 char const * title = "Using POSIX threads";
       
    94 
       
    95 #include <pthread.h>
       
    96 
       
    97 extern "C" void * common_thread_routine(void * pv)
       
    98 {
       
    99     abstract_thread * pt = static_cast<abstract_thread *>(pv);
       
   100     pt->run();
       
   101     delete pt;
       
   102     return 0;
       
   103 }
       
   104 
       
   105 #endif
       
   106 
       
   107 //
       
   108 
       
   109 template<class F> class thread: public abstract_thread
       
   110 {
       
   111 public:
       
   112 
       
   113     explicit thread(F f): f_(f)
       
   114     {
       
   115     }
       
   116 
       
   117     void run()
       
   118     {
       
   119         f_();
       
   120     }
       
   121 
       
   122 private:
       
   123 
       
   124     F f_;
       
   125 };
       
   126 
       
   127 template<class F> pthread_t createThread(F f)
       
   128 {
       
   129     std::auto_ptr<abstract_thread> p(new thread<F>(f));
       
   130 
       
   131     pthread_t r;
       
   132 
       
   133     if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0)
       
   134     {
       
   135         p.release();
       
   136         return r;
       
   137     }
       
   138 
       
   139    	throw std::runtime_error("createThread failed.");
       
   140 }
       
   141 
       
   142 //
       
   143 #ifdef __SYMBIAN32__
       
   144 int const n = 1024;
       
   145 #else
       
   146 int const n = 16384;
       
   147 #endif
       
   148 int const k = 512; // vector size
       
   149 int const m = 16; // threads
       
   150 
       
   151 void test( std::vector< boost::shared_ptr<int> > & v )
       
   152 {
       
   153     using namespace std; // printf, rand
       
   154 
       
   155     std::vector< boost::weak_ptr<int> > w( v.begin(), v.end() );
       
   156 
       
   157     int s = 0, f = 0, r = 0;
       
   158 
       
   159     for( int i = 0; i < n; ++i )
       
   160     {
       
   161         // randomly kill a pointer
       
   162 
       
   163         v[ rand() % k ].reset();
       
   164         ++s;
       
   165 
       
   166         for( int j = 0; j < k; ++j )
       
   167         {
       
   168             if( boost::shared_ptr<int> px = w[ j ].lock() )
       
   169             {
       
   170                 ++s;
       
   171 
       
   172                 if( rand() & 4 )
       
   173                 {
       
   174                     continue;
       
   175                 }
       
   176 
       
   177                 // rebind anyway with prob. 50% for add_ref_lock() against weak_release() contention
       
   178                 ++f;
       
   179             }
       
   180             else
       
   181             {
       
   182                 ++r;
       
   183             }
       
   184 
       
   185             w[ j ] = v[ rand() % k ];
       
   186         }
       
   187     }
       
   188 
       
   189     printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r );
       
   190 }
       
   191 
       
   192 int main()
       
   193 {
       
   194     std_log(LOG_FILENAME_LINE,"[Test Case for weak_ptr_mt_test]");
       
   195     using namespace std; // printf, clock_t, clock
       
   196 
       
   197     printf("%s: %d threads, %d * %d iterations: ", title, m, n, k );
       
   198 
       
   199     std::vector< boost::shared_ptr<int> > v( k );
       
   200 
       
   201     for( int i = 0; i < k; ++i )
       
   202     {
       
   203         v[ i ].reset( new int( 0 ) );
       
   204     }
       
   205 
       
   206     clock_t t = clock();
       
   207 
       
   208     pthread_t a[m];
       
   209 
       
   210     for(int i = 0; i < m; ++i)
       
   211     {
       
   212         a[i] = createThread( boost::bind( test, v ) );
       
   213     }
       
   214 
       
   215     v.resize( 0 ); // kill original copies
       
   216 
       
   217     for(int j = 0; j < m; ++j)
       
   218     {
       
   219         pthread_join( a[j], 0 );
       
   220     }
       
   221 
       
   222     t = clock() - t;
       
   223 
       
   224     printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLK_TCK);
       
   225 
       
   226 #ifdef __SYMBIAN32__
       
   227 	std_log(LOG_FILENAME_LINE,"Result : Passed");
       
   228 	std_log(LOG_FILENAME_LINE,"[End Test Case ]");
       
   229 #endif
       
   230 	testResultXml("weak_ptr_mt_test");
       
   231 	close_log_file();
       
   232     return 0;
       
   233 }