bind返回的函数对象不能拷贝么????
我自己写了一个多线程的for_each,windows下的。环境VS2008,控制台程序。
思路就是获取当前处理器数量,然后创建处理器数量-1个线程。直到所有线程跑完,for_each返回。
但是现在发现这个东西似乎不能支持bind,如果不能支持bind用起来就很麻烦啊。
因为是日文系统,所以报错信息也没啥用。对于报错信息,我的理解是,因为bind没有赋值/拷贝构造函数,所以在构造thread_parameter的时候会找不到复制构造函数。
但是这不科学啊,没有复制构造函数,传值怎么传过来的啊??!!
请大家帮帮忙啊!!
报错如下:
1>main.cpp
1>d:\mydocuments\visual studio 2008\projects\parallel_for_each\parallel_for_each\parallel.h(39) : error C2512: 'std::tr1::_Bind<_Ret,_BindN>' : クラス、構造体、共用体に既定のコンストラクタがありません。
1> with
1> [
1> _Ret=std::tr1::_Notforced,
1> _BindN=std::tr1::_Bind0<std::tr1::_Callable_obj<void (__cdecl *)(int),false>>
1> ]
1> d:\mydocuments\visual studio 2008\projects\parallel_for_each\parallel_for_each\parallel.h(81) : コンパイルされたクラスの テンプレート のインスタンス化 'parallel::thread_parameter<InputIterator,Function>::thread_parameter<InputIterator,Function>(InputIterator,InputIterator,UINT,UINT,Function,HANDLE)' の参照を確認してください
1> with
1> [
1> InputIterator=int *,
1> Function=std::tr1::_Bind<std::tr1::_Notforced,std::tr1::_Bind0<std::tr1::_Callable_obj<void (__cdecl *)(int),false>>>
1> ]
1> d:\mydocuments\visual studio 2008\projects\parallel_for_each\parallel_for_each\main.cpp(24) : コンパイルされたクラスの テンプレート のインスタンス化 'Function parallel::for_each<int*,std::tr1::_Bind<_Ret,_BindN>>(InputIterator,InputIterator,Function)' の参照を確認してください
1> with
1> [
1> Function=std::tr1::_Bind<std::tr1::_Notforced,std::tr1::_Bind0<std::tr1::_Callable_obj<void (__cdecl *)(int),false>>>,
1> _Ret=std::tr1::_Notforced,
1> _BindN=std::tr1::_Bind0<std::tr1::_Callable_obj<void (__cdecl *)(int),false>>,
1> InputIterator=int *
1> ]
1>ビルドログは "file://d:\myDocuments\Visual Studio 2008\Projects\parallel_for_each\parallel_for_each\Debug\BuildLog.htm" に保存されました。
// main.cpp
#include "parallel.h"
#include <iostream>
#include <functional>
using std::cout;
using std::tr1::bind;
using namespace std::tr1::placeholders;
void print(int i)
{
for(int j = 0 ; j < 1000000 ; ++j)
bool t = true;
//cout << "hello "<< i <<"\n";
}
int main()
{
const unsigned c = 1000;
int ar[c] ;
for(int i = 0 ; i < c ; ++i)
ar[i] = i;
parallel::Initialize();
parallel::for_each(ar,ar+c,bind(print));
return 0;
}
// parallel.h
#include "windows.h"
#include <vector>
#include <string>
#include <cassert>
using std::vector;
using std::wstring;
namespace parallel
{
bool init = false;
UINT CoreCount = 0;
void Initialize()
{
// get system infomation
LPSYSTEM_INFO info = new SYSTEM_INFO;
GetSystemInfo(info);
// cpu number, the cores you see in task manager
CoreCount = info->dwNumberOfProcessors - 1;
if(CoreCount==0)
CoreCount = 1;
init = true;
}
template<class InputIterator, class Function>
class thread_parameter{
public:
InputIterator first;
InputIterator last;
UINT Begin;
UINT StepLength;
Function f;
HANDLE mutex;
thread_parameter(thread_parameter& param){first = param.first;last = param.last;Begin = param.Begin;StepLength = param.StepLength;f = param.f; mutex = param.mutex;};
thread_parameter(){Begin = 0;StepLength = 0;mutex = 0;};
template<class InputIterator, class Function>
thread_parameter(InputIterator fst,InputIterator l,UINT bg,UINT sl,Function func,HANDLE m)
{first = fst; last = l; Begin = bg; StepLength = sl; f = func; mutex = m;};
};
template<class InputIterator, class Function>
DWORD WINAPI thread_function(LPVOID lpParameter)
{
thread_parameter<InputIterator, Function>* param = (thread_parameter<InputIterator, Function>*)(lpParameter);
WaitForSingleObject(param->mutex,INFINITE);
UINT stepCount = 0;
while(param->first != param->last)
{
Function func = param->f;
if(stepCount>=param->Begin && (stepCount-param->Begin)%param->StepLength==0)
{
func(*(param->first));
}
stepCount++;
(param->first)++;
}
ReleaseMutex(param->mutex);
return 0;
}
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f)
{
assert(init);
vector<HANDLE> mutexes;
mutexes.reserve(CoreCount);
for(UINT i = 0 ; i < CoreCount ; ++i)
{
// prepare mutex
wchar_t buffer[100];
::swprintf_s(buffer,L"zs@FNST parallel for_each mutex%d",i);
wstring mutexName((wchar_t*)buffer);
mutexes.push_back(CreateMutex(0,false,mutexName.c_str()));
// prepare other parameter
thread_parameter<InputIterator,Function>* param = new thread_parameter<InputIterator,Function>(
first,
last,
i,
CoreCount,
f,
mutexes.back());
CreateThread(0,0,thread_function<InputIterator,Function>,static_cast<void*>(param),0,0);
}
// wait for all the threads to return
for(UINT i = 0 ; i < mutexes.size() ; ++i)
{
WaitForSingleObject(mutexes[i],INFINITE);
}
for(UINT i = 0 ; i < mutexes.size() ; ++i)
{
ReleaseMutex(mutexes[i]);
}
return f;
}
}
namespace parallel
{
bool init = false;
UINT CoreCount = 0;
void Initialize()
{
// get system infomation
LPSYSTEM_INFO info = new SYSTEM_INFO;
GetSystemInfo(info);
// cpu number, the cores you see in task manager
CoreCount = info->dwNumberOfProcessors - 1;
if(CoreCount==0)
CoreCount = 1;
init = true;
}
template<class InputIterator, class Function>
class thread_parameter{
public:
InputIterator first;
InputIterator last;
UINT Begin;
UINT StepLength;
Function f;
HANDLE mutex;
thread_parameter(thread_parameter& param){first = param.first;last = param.last;Begin = param.Begin;StepLength = param.StepLength;f = param.f; mutex = param.mutex;};
thread_parameter(){Begin = 0;StepLength = 0;mutex = 0;};
thread_parameter(InputIterator fst,InputIterator l,UINT bg,UINT sl,Function func,HANDLE m):f(func)
{first = fst; last = l; Begin = bg; StepLength = sl; mutex = m;};
};
template<class InputIterator, class Function>
DWORD WINAPI thread_function(LPVOID lpParameter)
{
thread_parameter<InputIterator, Function>* param = (thread_parameter<InputIterator, Function>*)(lpParameter);
WaitForSingleObject(param->mutex,INFINITE);
UINT stepCount = 0;
while(param->first != param->last)
{
if(stepCount>=param->Begin && (stepCount-param->Begin)%param->StepLength==0)
{
param->f( *(param->first) );
}
stepCount++;
(param->first)++;
}
ReleaseMutex(param->mutex);
return 0;
}
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f)
{
assert(init);
vector<HANDLE> mutexes;
mutexes.reserve(CoreCount);
for(UINT i = 0 ; i < CoreCount ; ++i)
{
// prepare mutex
wchar_t buffer[100];
::swprintf_s(buffer,L"zs@FNST parallel for_each mutex%d",i);
wstring mutexName((wchar_t*)buffer);
mutexes.push_back(CreateMutex(0,false,mutexName.c_str()));
// prepare other parameter
thread_parameter<InputIterator,Function>* param = new thread_parameter<InputIterator,Function>(
first,
last,
i,
CoreCount,
f,
mutexes.back());
CreateThread(0,0,thread_function<InputIterator,Function>,static_cast<void*>(param),0,0);
}
// wait for all the threads to return
for(UINT i = 0 ; i < mutexes.size() ; ++i)
{
WaitForSingleObject(mutexes[i],INFINITE);
}
for(UINT i = 0 ; i < mutexes.size() ; ++i)
{
ReleaseMutex(mutexes[i]);
}
return f;
}
}