Sarth
asked on
Re-entrant Codes
This code encounters an error after running < 1000 or > 1000 times. This code works in a way that messages are stored in a shared memory. I suspect that the behaviour the message is being stored or accesses the memory location is not shared.
How/where do I look into the way the message access the memory location ? Below is the code
#include <stdio.h>
#include "direcsql.h"
int EnterQueue(int line,int server, char *s, char *r,
char *retcode,char *cols,char *rows,IQSIZE_T length, IQSIZE_T rlen)
{
//This function put the message onto the message queue that is shared.
BOOL fInit;
DB_TYPE smsg, rmsg;
int i=0;
if (line == 0)
return -1;
else
line = (line*2) -2;
hSharedQ = CreateFileMapping((HANDLE) 0xFFFFFFFF ,
NULL,
PAGE_READWRITE,
0,
SHMEMSIZE,
QUEUE_NAME);
fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
if (hSharedQ == NULL)
{//Cannot allocate memory
return -2;
}
else
{
queue = (DB_TYPE *)MapViewOfFile(hSharedQ,
FILE_MAP_ALL_ACCESS,
0,
0,
0);
if (queue == NULL)
return -3;
if (fInit)
{
memset(queue, '\0', SHMEMSIZE);
}
if (length >= MAX_SIZE)
return -6;
smsg.server = server;
memcpy(smsg.msg,s,length);
smsg.msg[length] = '\0';
//Put information to my own slot.
memcpy((queue+line),&smsg, sizeof(DB_ TYPE));
//wait for message return or time out.
while (i < NO_OF_SECS_TO_WAIT*2)
{
if (*(queue+line+1)->msg != '\0')
{
memcpy(&rmsg,(queue+line+1 ),sizeof(D B_TYPE));
memset((queue+line),'\0',s izeof(DB_T YPE));
memset((queue+line+1),'\0' ,sizeof(DB _TYPE));
if (r != NULL)
{
memcpy(r,rmsg.msg,rlen-1);
r[rlen-1] = '\0';
}
else
return -4;
if (retcode != NULL)
sprintf(retcode,"%02d",rms g.retcode) ;
else
return -5;
if (cols != NULL)
sprintf(cols,"%02d",rmsg.c ols);
else
return -6;
if (rows != NULL)
sprintf(rows,"%02d",rmsg.r ows);
else
return -7;
return 1;
}
i++;
Sleep(500);
}
memset((queue+line),'\0',s izeof(DB_T YPE));
memset((queue+line+1),'\0' ,sizeof(DB _TYPE));
return -8;
}
return -9;
}
BOOL LeaveQueue()
{
//This function is called to remove the DLL from the share memory.
if (queue != NULL)
UnmapViewOfFile(queue);
if (hSharedQ != NULL)
CloseHandle(hSharedQ);
return TRUE;
}
UDLLENTRYEXP ExecSQL(int identity,int server, char *ssql, char *rsql,
char *retcode,char *cols,char *rows)
{
int r;
//This is the function called by the external program to do sending.
if (identity > 96)
identity = 96;
r=EnterQueue(identity,serv er,ssql,rs ql,retcode ,cols,rows ,strlen(ss ql),MAX_SI ZE);
if (r == 1)
{
LeaveQueue();
return 1;
}
else
{
LeaveQueue();
return r;
}
}
UDLLENTRYEXP ExeDirectSQL(IQVAL identity,PUSERDLLPARAM32 server,
PUSERDLLPARAM32 ssql, PUSERDLLPARAM32 rsql,
PUSERDLLPARAM32 retcode,PUSERDLLPARAM32 cols,
PUSERDLLPARAM32 rows)
{
int r;
identity++;
if (identity > 96)
identity = 96;
//This is the function called by the external program to do sending.
r=EnterQueue(identity,serv er->u.valu e,ssql->u. ptr,
rsql->u.ptr,retcode->u.ptr ,cols->u.p tr,rows->u .ptr,
ssql->length,rsql->length) ;
if (r == 1)
{
LeaveQueue();
return 1;
}
else
{
LeaveQueue();
return r;
}
}
How/where do I look into the way the message access the memory location ? Below is the code
#include <stdio.h>
#include "direcsql.h"
int EnterQueue(int line,int server, char *s, char *r,
char *retcode,char *cols,char *rows,IQSIZE_T length, IQSIZE_T rlen)
{
//This function put the message onto the message queue that is shared.
BOOL fInit;
DB_TYPE smsg, rmsg;
int i=0;
if (line == 0)
return -1;
else
line = (line*2) -2;
hSharedQ = CreateFileMapping((HANDLE)
NULL,
PAGE_READWRITE,
0,
SHMEMSIZE,
QUEUE_NAME);
fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
if (hSharedQ == NULL)
{//Cannot allocate memory
return -2;
}
else
{
queue = (DB_TYPE *)MapViewOfFile(hSharedQ,
FILE_MAP_ALL_ACCESS,
0,
0,
0);
if (queue == NULL)
return -3;
if (fInit)
{
memset(queue, '\0', SHMEMSIZE);
}
if (length >= MAX_SIZE)
return -6;
smsg.server = server;
memcpy(smsg.msg,s,length);
smsg.msg[length] = '\0';
//Put information to my own slot.
memcpy((queue+line),&smsg,
//wait for message return or time out.
while (i < NO_OF_SECS_TO_WAIT*2)
{
if (*(queue+line+1)->msg != '\0')
{
memcpy(&rmsg,(queue+line+1
memset((queue+line),'\0',s
memset((queue+line+1),'\0'
if (r != NULL)
{
memcpy(r,rmsg.msg,rlen-1);
r[rlen-1] = '\0';
}
else
return -4;
if (retcode != NULL)
sprintf(retcode,"%02d",rms
else
return -5;
if (cols != NULL)
sprintf(cols,"%02d",rmsg.c
else
return -6;
if (rows != NULL)
sprintf(rows,"%02d",rmsg.r
else
return -7;
return 1;
}
i++;
Sleep(500);
}
memset((queue+line),'\0',s
memset((queue+line+1),'\0'
return -8;
}
return -9;
}
BOOL LeaveQueue()
{
//This function is called to remove the DLL from the share memory.
if (queue != NULL)
UnmapViewOfFile(queue);
if (hSharedQ != NULL)
CloseHandle(hSharedQ);
return TRUE;
}
UDLLENTRYEXP ExecSQL(int identity,int server, char *ssql, char *rsql,
char *retcode,char *cols,char *rows)
{
int r;
//This is the function called by the external program to do sending.
if (identity > 96)
identity = 96;
r=EnterQueue(identity,serv
if (r == 1)
{
LeaveQueue();
return 1;
}
else
{
LeaveQueue();
return r;
}
}
UDLLENTRYEXP ExeDirectSQL(IQVAL identity,PUSERDLLPARAM32 server,
PUSERDLLPARAM32 ssql, PUSERDLLPARAM32 rsql,
PUSERDLLPARAM32 retcode,PUSERDLLPARAM32 cols,
PUSERDLLPARAM32 rows)
{
int r;
identity++;
if (identity > 96)
identity = 96;
//This is the function called by the external program to do sending.
r=EnterQueue(identity,serv
rsql->u.ptr,retcode->u.ptr
ssql->length,rsql->length)
if (r == 1)
{
LeaveQueue();
return 1;
}
else
{
LeaveQueue();
return r;
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
1) i assume you're using windows 95/98 or windows nt.
2) you might want to get a copy of "advanced windows nt" by jeffrey richter. it's a great book for 32 bit programming.
events, critical sections, mutexes, semaphores are operating system objects that allows gating of who gets access to shared resources.
in the most basic terms, they're simple flags so you can essentially think of them as such. so for example:
thread1func()
{
while ( !done )
{
if ( bCanUseResource )
{
bCanUseResource = false;
dowork1( someresource );
bCanUseResource = true;
}
sleep(sometime);
}
}
thread1func()
{
while ( !done )
{
if ( bCanUseResource )
{
bCanUseResource = false;
dowork2( someresource );
bCanUseResource = true;
}
sleep(sometime);
}
}
in this example, bCanUseResource acts as a gatekeeper for the shared resource (someresource). more evident on a machine with 2 or more processors, without some sort of gating mechanism, someresource can be accessed simultaneously (by each processor) and could cause havoc on your program. single processor machines can cause the same problems due to the multitasking nature of the OS.
events are synonimous with the bCanUseResource but the OS guarantees that when you reset or set an event you will not be interrupted (ie this procedure is atomic) and thus will have no chance for reentracy problems.
use the WaitForSingleObject() function along with CreateEvent(), ResetEvent() and SetEvent() functions to provide your gating mechanism.
WaitForSingleObject will wait on an event that has been Resetted until the event is Set again through another thread or function. so the example above translates to:
thread1func()
{
while ( !done )
{
if ( WaitForSingleObject( hCanUseResource, INFINITE ) == WAIT_OBJECT_O )
(
ResetEvent( hCanUseResource );
dowork1( someresource );
SetEvent ( hCanUseResource );
}
sleep(sometime);
}
}
thread1func()
{
while ( !done )
{
if ( WaitForSingleObject( hCanUseResource, INFINITE ) == WAIT_OBJECT_O )
(
ResetEvent( hCanUseResource );
dowork2( someresource );
SetEvent ( hCanUseResource );
}
sleep(sometime);
}
}
here hCanUseResource is created via CreateEvent() and set by the main program before the threads are spawned.
2) you might want to get a copy of "advanced windows nt" by jeffrey richter. it's a great book for 32 bit programming.
events, critical sections, mutexes, semaphores are operating system objects that allows gating of who gets access to shared resources.
in the most basic terms, they're simple flags so you can essentially think of them as such. so for example:
thread1func()
{
while ( !done )
{
if ( bCanUseResource )
{
bCanUseResource = false;
dowork1( someresource );
bCanUseResource = true;
}
sleep(sometime);
}
}
thread1func()
{
while ( !done )
{
if ( bCanUseResource )
{
bCanUseResource = false;
dowork2( someresource );
bCanUseResource = true;
}
sleep(sometime);
}
}
in this example, bCanUseResource acts as a gatekeeper for the shared resource (someresource). more evident on a machine with 2 or more processors, without some sort of gating mechanism, someresource can be accessed simultaneously (by each processor) and could cause havoc on your program. single processor machines can cause the same problems due to the multitasking nature of the OS.
events are synonimous with the bCanUseResource but the OS guarantees that when you reset or set an event you will not be interrupted (ie this procedure is atomic) and thus will have no chance for reentracy problems.
use the WaitForSingleObject() function along with CreateEvent(), ResetEvent() and SetEvent() functions to provide your gating mechanism.
WaitForSingleObject will wait on an event that has been Resetted until the event is Set again through another thread or function. so the example above translates to:
thread1func()
{
while ( !done )
{
if ( WaitForSingleObject( hCanUseResource, INFINITE ) == WAIT_OBJECT_O )
(
ResetEvent( hCanUseResource );
dowork1( someresource );
SetEvent ( hCanUseResource );
}
sleep(sometime);
}
}
thread1func()
{
while ( !done )
{
if ( WaitForSingleObject( hCanUseResource, INFINITE ) == WAIT_OBJECT_O )
(
ResetEvent( hCanUseResource );
dowork2( someresource );
SetEvent ( hCanUseResource );
}
sleep(sometime);
}
}
here hCanUseResource is created via CreateEvent() and set by the main program before the threads are spawned.
ASKER
hi mnguyen, SkyWolf is oso nick of mine ...Sarth is a nick i use from office , i use Skywolf at home...so hope u r not confuse or watever....i will try out 1st then i will get back to you say, 3 or 4 days time ? thanz !
my mail addr is yulh@gitpl.com.sg
u help will be greatly appreciated ,,thanks!