Re: How to use CreateProcess for multiple processes?
This is a multi-part message in MIME format.
--------------060309020401080606020503
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Tommy wrote:
Tommy wrote:
So its a perpetual motion concept, which stops when the bucket is empty.
Ami, I wrote this very quickly to illustrate the bucket/worker threads
method. Attached is:
TestMaster.Cpp
TestSlave.cpp
Note: I wrote this very quickly, and its proof of concept. I'm sure
there are part that can be done more cleanly or C++ correct.
Attached is slightly cleaner testmaster, CBucket had missing
destructor, added sync to Add function.
Note, I change the constant MAX_WORKERS = 20 and it screamed on my
machine. :-) With good simulation of testslave, you can make your
master pretty solid.
--------------060309020401080606020503
Content-Type: text/plain;
name="testmaster.cpp"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline;
filename="testmaster.cpp"
#include <stdio.h>
#include <afx.h>
#include <afxtempl.h>
#include <conio.h>
//------------------------------------------------------
const DWORD MAX_JOBS = 100;
const DWORD MAX_WORKERS = 20;
const char *SLAVE_EXE = "testslave.exe";
typedef struct _tagTSlaveData {
char szUser[256];
char szPwd[256];
char szHost[256];
} TSlaveData;
typedef struct _tagTThreadData {
DWORD index;
DWORD dwStartTime;
DWORD dwEndTime;
DWORD dwExitCode;
TSlaveData sd;
} TThreadData;
class CBucket : public CList< TSlaveData, TSlaveData>
{
public:
CBucket() { InitializeCriticalSection(&cs); }
~CBucket() { DeleteCriticalSection(&cs); }
void Add( const TSlaveData &o )
{
EnterCriticalSection(&cs);
AddHead( o );
LeaveCriticalSection(&cs);
}
void Add(const char *user, const char *pwd, const char *host)
{
TSlaveData td = {0};
strncpy(td.szUser,user,sizeof(td.szUser));
strncpy(td.szPwd,pwd,sizeof(td.szPwd));
strncpy(td.szHost,host,sizeof(td.szHost));
Add(td); =00
}
BOOL Fetch(TSlaveData &o)
{
EnterCriticalSection(&cs);
BOOL res = !IsEmpty();
if (res) o = RemoveTail();
LeaveCriticalSection(&cs);
return res;
}
private:
CRITICAL_SECTION cs;
} Bucket;
//----------------------------------------------------------------
// Slave Work
//----------------------------------------------------------------
BOOL SlaveWork(TThreadData *data)
{
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
CString sCmd;
sCmd.Format("%s %d /user:%s /pwd:%s /host:%s",
SLAVE_EXE,
data->index+1,
data->sd.szUser,
data->sd.szPwd,
data->sd.szHost);
if (!CreateProcess(NULL, (LPSTR &)sCmd,
NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
return FALSE;
}
CloseHandle(pi.hThread);
if (WAIT_OBJECT_0== WaitForSingleObject(pi.hProcess, INFINITE)) {=
GetExitCodeProcess(pi.hProcess, &data->dwExitCode);
}
CloseHandle(pi.hProcess);
return TRUE;
}
void WINAPI SlaveThread(TThreadData *data)
{
data->dwStartTime = GetTickCount();
TSlaveData sd;
while (Bucket.Fetch(sd)) {
data->sd = sd;
SlaveWork(data);
}
data->dwEndTime = GetTickCount();
return;
}
void DoThreads()
{
TThreadData ThreadData[MAX_WORKERS] = {0};
ZeroMemory(&ThreadData,sizeof(ThreadData));
HANDLE hThreads[MAX_WORKERS] = {0};
DWORD tid;
DWORD i;
for(i=0;i < MAX_WORKERS; i++){
ThreadData[i].index = i;
hThreads[i] = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE) SlaveThread,
(void *)&ThreadData[i],
0,
&tid);
}
DWORD dwMasterTime = GetTickCount();
DWORD nRemaining = 0;
while (WaitForMultipleObjects(MAX_WORKERS, hThreads, TRUE, 1000) ===
WAIT_TIMEOUT) {
int n = Bucket.GetSize();
if (n != nRemaining) {
nRemaining = n;
printf("- Remaining: %d\n",nRemaining);
}
if (_kbhit() && _getch() == 27) {
break;
}
}
dwMasterTime = GetTickCount() - dwMasterTime;
_cprintf("* Done\n");
// show some thread times
DWORD dwTime = 0;
for (i = 0; i < MAX_WORKERS; i++) {
TThreadData dt = ThreadData[i];
dwTime += dt.dwEndTime-dt.dwStartTime;
printf("%-3d | Time: %-6d\n",
i,dt.dwEndTime-dt.dwStartTime);
}
printf("---------------------------------------\n");
printf("Total Slave Time : %d\n",dwTime);
printf("Total Master Time : %d\n",dwMasterTime);
}
void FillBucket()
{
for (int i = 0; i < MAX_JOBS; i++)
{
Bucket.Add("user","password", "host");
}
}
//----------------------------------------------------------------
// Main Thread
//----------------------------------------------------------------
int main(char argc, char *argv[])
{
FillBucket();
DoThreads();
return 0;
}
--------------060309020401080606020503--