ThreadServer.cpp 

All non-multithreading class library programs can run on both 32-bit Windows and UNIX platforms. This sample program is for Microsoft Windows developers. The program shows how the class library can be used with the MFC to provide a user interface. For more information, please see the detailed comments in each program and the documentation for each class library function.

 

///////////////////////////////////////////////////////

// CrServTh.cpp : implementation file

///////////////////////////////////////////////////////

#include "CrServTh.h"

CSAPCriticalSection CrServThLock;

extern CRfcTrace RfcClassTrace; // For debugging trace

main( int argc, char ** argv)

{

CrServTh servThObj;

char inputBuffer[MAX_LEN];

int nThreads = 0;

memset(inputBuffer, 0, MAX_LEN);

printf("\n\nPlease enter the number of child threads for the server (default is zero): "); gets(inputBuffer) ;

if (strlen(inputBuffer) == 0)

nThreads = 0;

else

{

nThreads = atoi(inputBuffer);

if (nThreads < 0)

nThreads = 0;

}

servThObj.DoMultithreading(argv, nThreads);

return 0;

}

// Get destination, client, user name, password, and functional name

// for Logon

CrServTh::CrServTh()

{

}

CrServTh::~CrServTh()

{

}

// Get data from R/3 and display on screens

void CrServTh::DoMultithreading(char** argv, int nThreads)

{

RfcClassTrace.Trace("Now in CrServTh::DoMultithreading");

#if !defined(CRFCwithTHREADS)

nThreads = 0;

#endif

if(nThreads < 0) nThreads = 0;

StartThreads(argv, nThreads);

}

// This method starts the mulithreading server

void CrServTh::StartThreads(char** argv, int nThreads)

{

RfcClassTrace.Trace("Processing in CrServTh::StartThreads");

CRfcConnection Connection ;

CRfcMyApp MyApp(&Connection);

CRfcShow RfcShow(this, &MyApp);

 

int nSuccessThreads = 0;

try

{

//Establish a connection to the R/3 system or the

//R/3 gateway server depending on which mode is

//used

//_asm int 3;

Connection.Accept (argv) ;

//Register the RFC server function to the Server App

//object

//Server App object knows how to dispatch a call from

//the R/3 System to the server function

RfcShow.SetnThreads(nThreads);

MyApp.AddServerFunction (RfcShow);

//_asm int 3;

//MyApp.Run() ;

MyApp.Run(nThreads);

 

//_asm int 3;

}

catch(RFC_ERROR_INFO err)

{

DumpErrorInfo(err);

}

catch (char *pException)

{

printf("\n%s\n\n", pException);

}

}

/////////////////////////////////////////////////////////

// Class definition for CRfcMyApp

/////////////////////////////////////////////////////////

CRfcMyApp::CRfcMyApp (CRfcConnection* pConnection)

:CRfcServerApp (pConnection),

m_bPrintWait(TRUE)

{

}

//Do something when the program receives no RFC call from the R/3

//system

//(single threads only)

void CRfcMyApp::OnIdle()

{

#ifdef SAPonUNIX

sleep(1);

#elif defined(SAPonNT)

sleep(1000);

#endif

if(m_bPrintWait)

{

cout << endl << endl << endl << endl

<< "Waiting for call..." << endl << endl << flush;

m_bPrintWait = FALSE;

}

}

void CRfcMyApp::EnableIdlePrint(void)

{

m_bPrintWait = TRUE;

}

CRfcMyApp::~CRfcMyApp(void)

{

}

/////////////////////////////////////////////////////////

// Class definiation for CRfcShow

/////////////////////////////////////////////////////////

RFC_FIELD_INFO CRfcShow::FieldsCONTENTS[] = {{"TEXT", 0, 0, TYPC, 80, 0}} ;

CRfcShow::CRfcShow (CrServTh * pServTh, CRfcMyApp *pApp)

: CRfcServerFunc ("RFC_SHOW"),

m_pServTh(pServTh),

m_pApp(pApp),

m_nThreads(0)

{

RfcClassTrace.Trace("Processing in CRfcShow::CRfcShow");

try

{

m_pSimTitle = new CRfcSimpleParam ("TITLE", TYPC, TEXT_LEN);

//Must specify data type here

m_pSimCount = new CRfcSimpleParam ("COUNT", TYPINT, sizeof(TYPINT));

m_pTabContents = new CRfcTableParam ("CONTENTS",TEXT_LEN) ;

m_pTabContents->AddFieldInfo (FieldsCONTENTS,

sizeof(FieldsCONTENTS) / sizeof(RFC_FIELD_INFO)) ;

//Add parameters to the function object

AddImportParam (*m_pSimTitle) ;

AddExportParam (*m_pSimCount) ;

AddTableParam (*m_pTabContents) ;

}

catch (char*)

{

printf("Memory error in CRfcShow::CRfcShow.\n\n");

ClearParams() ;

}

}

CRfcShow::CRfcShow(const CRfcShow & pShow)

: CRfcServerFunc(pShow)

{

m_pSimTitle = (CRfcSimpleParam *)GetImportParam("TITLE");

m_pSimCount = (CRfcSimpleParam *)GetExportParam("COUNT");

m_pTabContents = GetTableParam("CONTENTS");

m_pServTh = pShow.m_pServTh;

m_pApp = pShow.m_pApp;

m_nThreads = pShow.m_nThreads;

}

#if defined(CRFCwithTHREADS)

extern int rfc_thread[10000]; //You do not have to know this, it is

//for debugging only

//Allows you to find out which threads

//are performing which tasks.

/*-----------------------------------------------------------*/

/* Macro for output RFC-Call on screen */

/*-----------------------------------------------------------*/

#define PRINT_RFC_CALL(thread_id, text) \

if (thread_id) \

printf("\n Thread %3d: %s", thread_id, text); \

else \

printf("\n Main Thread %s", text); \

fflush(stdout)

#else

#define PRINT_RFC_CALL(thread_id, text) \

printf("\n %s", text); \

fflush(stdout)

#endif

void CRfcShow::Process()

{

RfcClassTrace.Trace("Processing in CRfcShow::Process");

 

RFC_HANDLE RfcHandle;

GET_VERIFIED_CONNECTION(RfcHandle);

char dbuf[512];

memset(dbuf, 0, 511);

int nRow;

int nCount ; // Number of rows

//Get row count for the table

//Print out the title

sprintf(dbuf, " Title: %s\n\n", (CSTR)m_pSimTitle->Value());

PRINT_RFC_CALL(rfc_thread[RfcHandle], dbuf);

nCount = m_pTabContents->GetRowCount() ;

for (nRow = 0; nRow < nCount; nRow++)

{

//A column can be specified by name or index.

sprintf(dbuf, "%s\n", (CSTR)m_pTabContents->Cell(nRow, 0));

PRINT_RFC_CALL(rfc_thread[RfcHandle], dbuf);

}

m_pSimCount->Value() = nCount;

if (m_nThreads == 0 && m_pApp)

m_pApp->EnableIdlePrint();

}

char* CRfcShow::GetDescription (void)

{

RfcClassTrace.Trace("Processing in CRfcShow::GetDescription");

static char docu[] =

"RFC Server Sample program using the RFC class library." NL

"EXPORTING" NL

"m_nTableLines TYPC" NL

"m_pChildThreads TYPC" NL

"IMPORTING" NL

"m_pCustNum TYPC" NL

"m_pCustName TYPC" NL

"TABLES" NL

"m_pTabContents text" NL ;

return docu;

}

void CRfcShow::ClearParams(void)

{

if (m_pSimTitle != NULL) delete m_pSimTitle ;

if (m_pSimCount != NULL) delete m_pSimCount ;

if (m_pTabContents != NULL) delete m_pTabContents ;

m_pSimTitle = NULL;

m_pSimCount = NULL;

m_pTabContents = NULL;

}

CRfcShow::~CRfcShow()

{

ClearParams();

}