101
101

Reputation: 31

Multithreading to decrease CPU time

I am trying to make a multithreading iteration for a complicated calculation which needs to communicate with other stream of threads coming from other program and exchange data (receive/send), how can I make them communicate? Using file mapping for example? Will this work?

Upvotes: 0

Views: 181

Answers (2)

rcgldr
rcgldr

Reputation: 28911

Some structures are needed for the semaphores and process creation.

The no warnings define is to prevent warnings for using sscanf or sprintf. abCmdLine has the name of process B (pb.exe) and the value for the shared memory handle. (note - handles are pointer types).

There's a 1/2 second sleep in the loops so you can see how this works. In this example, both loops run at the same time.

Update - the original post was edited. Previously it specifically mentioned process A and process B, along with semaphores named SemA, SemB, and a counter named count. With the removal of these names from the original post, people reading this thread may wonder why these names are used in the examples here. The other names in this example follow the Microsoft / Windows Hungarian notation style.

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <windows.h>

typedef struct SMEM_                /* shared memory offsets */
{
    HANDLE SemA;
    HANDLE SemB;
    int    count;
}SMEM, *PSMEM;
static HANDLE   hMem;               /* handle for shared memory */
static PSMEM    psMem;              /* ptr to shared memory */

/* bInheritHandle = TRUE */
static SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES),
                               NULL, TRUE};
static STARTUPINFO si = {sizeof(STARTUPINFO),
                        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
/* hProcess = hThread = INVALID_HANDLE_VALUE */
static PROCESS_INFORMATION piB = {INVALID_HANDLE_VALUE,
                                  INVALID_HANDLE_VALUE,
                                  0, 0};

int main(int argc, char *argv[])
{
char abCmdLine[64];
    hMem = CreateFileMapping(INVALID_HANDLE_VALUE,&sa,PAGE_READWRITE,0,
                            sizeof(SMEM),NULL);
    if(hMem == INVALID_HANDLE_VALUE){
        goto exit0;}
    psMem = MapViewOfFile(hMem, FILE_MAP_WRITE, 0, 0, sizeof(SMEM));
    if(psMem == NULL){
        goto exit0;}
    memset(psMem, 0, sizeof(SMEM));

    /* process A waits before psMem->count++ */
    psMem->SemA = CreateSemaphore(&sa,0,2,NULL);
    if(psMem->SemA == INVALID_HANDLE_VALUE)
        goto exit0;
    /* process B waits for count to be updated */
    psMem->SemB = CreateSemaphore(&sa,0,2,NULL);
    if(psMem->SemB == INVALID_HANDLE_VALUE)
        goto exit0;
    /* create process B */
    sprintf(abCmdLine, "pb.exe %p", hMem);
    if(0 == CreateProcess(NULL, abCmdLine, NULL, NULL, TRUE,
            CREATE_NEW_CONSOLE, NULL, NULL, &si, &piB))
        goto exit0;
    for(psMem->count = 0; psMem->count < 20; psMem->count++){
        /* allow process B to use psMem->count */
        ReleaseSemaphore(psMem->SemB, 1, NULL);
        printf("%d\n", psMem->count);
        Sleep(500);
        /* wait before psMem->count++ */
        WaitForSingleObject(psMem->SemA, INFINITE);
    }
    /* wait for process B to terminate */
    WaitForSingleObject(piB.hProcess, INFINITE);
exit0:
    if(piB.hThread != INVALID_HANDLE_VALUE)
        CloseHandle(piB.hThread);
    if(piB.hProcess != INVALID_HANDLE_VALUE)
        CloseHandle(piB.hProcess);
    if(psMem->SemB != INVALID_HANDLE_VALUE)
        CloseHandle(psMem->SemB);
    if(psMem->SemA != INVALID_HANDLE_VALUE)
        CloseHandle(psMem->SemA);
    if(hMem != INVALID_HANDLE_VALUE)
        CloseHandle(hMem);
    return(0);
}

process B (pb.exe)

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <windows.h>

typedef struct SMEM_                /* shared memory offsets */
{
    HANDLE SemA;
    HANDLE SemB;
    int    count;
}SMEM, *PSMEM;
static HANDLE   hMem;               /* handle for shared memory */
static PSMEM    psMem;              /* ptr to shared memory */

int main(int argc, char *argv[])
{
int done = 0;                       /* done flag */
    sscanf(argv[1], "%p", &hMem);
    psMem = MapViewOfFile(hMem, FILE_MAP_WRITE, 0, 0, sizeof(SMEM));
    if(psMem == NULL)
        goto exit0;
    while(!done){
        /* wait for psMem->count to be updated */
        WaitForSingleObject(psMem->SemB, INFINITE);
        printf("%d\n", psMem->count);
        Sleep(500);
        done = psMem->count < 19 ? 0 : 1;
        /* allow process A to update psMem->count */
        ReleaseSemaphore(psMem->SemA, 1, NULL);
    }
exit0:
    return(0);
}

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 754410

Assuming you want the processes to alternate, then you will need two semaphores and each process will need code with a slightly different sequence of calls:

Process A:

SemA = CreateAndInitializeSemaphore();
SemB = CreateAndInitializeSemaphore();

for (i = 0; i < Numpoints; i++)
{
    WaitForSemaphore(SemA);
    …code for process A…
    SignalSemaphore(SemB);
}

And similarly for B except that the semaphores are reversed.

for (i = 0; i < Numpoints; i++)
{
    WaitForSemaphore(SemB);
    …code for process A…
    SignalSemaphore(SemA);
}

Note that when SemA is created, it needs to be set so that A will get access to it immediately.

All semaphore function names need to be mapped to the correct actual system calls.

Upvotes: 1

Related Questions