Factored out boost/detail/lightweight_thread.hpp.

[SVN r44638]
This commit is contained in:
Peter Dimov
2008-04-20 15:37:08 +00:00
parent 04be979670
commit 71fa2cd658
2 changed files with 46 additions and 229 deletions

View File

@@ -7,167 +7,76 @@
#pragma warning(disable: 4514) // unreferenced inline removed #pragma warning(disable: 4514) // unreferenced inline removed
#endif #endif
//
// shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads // shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads
// //
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2008 Peter Dimov
// //
// Distributed under the Boost Software License, Version 1.0. (See // Distributed under the Boost Software License, Version 1.0.
// accompanying file LICENSE_1_0.txt or copy at // See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <vector> #include <vector>
#include <memory>
#include <stdexcept>
#include <cstdio> #include <cstdio>
#include <ctime> #include <ctime>
// 'portable' thread framework #include <boost/detail/lightweight_thread.hpp>
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.");
}
// //
int const n = 1024 * 1024; int const n = 1024 * 1024;
void test(boost::shared_ptr<int> const & pi) void test( boost::shared_ptr<int> const & pi )
{ {
std::vector< boost::shared_ptr<int> > v; std::vector< boost::shared_ptr<int> > v;
for(int i = 0; i < n; ++i) for( int i = 0; i < n; ++i )
{ {
v.push_back(pi); v.push_back( pi );
} }
} }
int const m = 16; // threads int const m = 16; // threads
#if defined( BOOST_HAS_PTHREADS )
char const * thmodel = "POSIX";
#else
char const * thmodel = "Windows";
#endif
int main() int main()
{ {
using namespace std; // printf, clock_t, clock using namespace std; // printf, clock_t, clock
printf("%s: %d threads, %d iterations: ", title, m, n); printf( "Using %s threads: %d threads, %d iterations: ", thmodel, m, n );
boost::shared_ptr<int> pi(new int(42)); boost::shared_ptr<int> pi( new int(42) );
clock_t t = clock(); clock_t t = clock();
pthread_t a[m]; pthread_t a[ m ];
for(int i = 0; i < m; ++i) for( int i = 0; i < m; ++i )
{ {
a[i] = createThread( boost::bind(test, pi) ); boost::detail::lw_thread_create( a[ i ], boost::bind( test, pi ) );
} }
for(int j = 0; j < m; ++j) for( int j = 0; j < m; ++j )
{ {
pthread_join(a[j], 0); pthread_join( a[j], 0 );
} }
t = clock() - t; t = clock() - t;
printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC); printf( "\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC );
return 0; return 0;
} }

View File

@@ -7,128 +7,26 @@
#pragma warning(disable: 4514) // unreferenced inline removed #pragma warning(disable: 4514) // unreferenced inline removed
#endif #endif
//
// weak_ptr_mt_test.cpp // weak_ptr_mt_test.cpp
// //
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright 2005 Peter Dimov // Copyright 2005, 2008 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)
// //
// 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
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp> #include <boost/weak_ptr.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <vector> #include <vector>
#include <memory>
#include <stdexcept>
#include <cstdio> #include <cstdio>
#include <ctime> #include <ctime>
#include <cstdlib> #include <cstdlib>
// 'portable' thread framework #include <boost/detail/lightweight_thread.hpp>
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.");
}
// //
@@ -177,11 +75,21 @@ void test( std::vector< boost::shared_ptr<int> > & v )
printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r ); printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r );
} }
#if defined( BOOST_HAS_PTHREADS )
char const * thmodel = "POSIX";
#else
char const * thmodel = "Windows";
#endif
int main() int main()
{ {
using namespace std; // printf, clock_t, clock using namespace std; // printf, clock_t, clock
printf("%s: %d threads, %d * %d iterations: ", title, m, n, k ); printf("Using %s threads: %d threads, %d * %d iterations: ", thmodel, m, n, k );
std::vector< boost::shared_ptr<int> > v( k ); std::vector< boost::shared_ptr<int> > v( k );
@@ -192,16 +100,16 @@ int main()
clock_t t = clock(); clock_t t = clock();
pthread_t a[m]; pthread_t a[ m ];
for(int i = 0; i < m; ++i) for( int i = 0; i < m; ++i )
{ {
a[i] = createThread( boost::bind( test, v ) ); boost::detail::lw_thread_create( a[ i ], boost::bind( test, v ) );
} }
v.resize( 0 ); // kill original copies v.resize( 0 ); // kill original copies
for(int j = 0; j < m; ++j) for( int j = 0; j < m; ++j )
{ {
pthread_join( a[j], 0 ); pthread_join( a[j], 0 );
} }