• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 506
  • Last Modified:

Shared Memory

Can anyone provide me detailed information on the topic shared memory or how to create shared memory in C++ asap ?
Is it correct to say that share memory allows concurrent access to the memory location ? If not, pls show proof to stake your claims .... thanx
0
SkyWolf
Asked:
SkyWolf
  • 3
  • 3
  • 2
  • +2
1 Solution
 
msa092298Commented:
Do you mean shared memory between processes or between threads? On which platform?   As for NT/95 : between processes you will need using pipes or memory mapped files.  Between threads in the same process, you can do this of course.  But you may need critical sections to avoid concurrent writing to the same location since it may cause problems.
Define a global variable in your program like this:
CRITICAL_SECTION myGlobalLock;
then call this code once from the main part before using the shared memory :   InitializeCriticalSection(&myGlobalLock);
and call this after you no longer need the shared memory and after all threads have exited at the end of your program:
DeleteCriticalSection(&myGlobalLock);

Inside each thread, to access the shared memory you will need:

EnterCriticalSection (&myGlobalLock);
  ... do your code here (and do not return without executing the following line)
LeaveCriticalSection (&myGlobalLock);

Hope this helps.
0
 
SkyWolfAuthor Commented:
MSA,
i have to reject ur answer 1st else i think u cannot add ur comments, which i hope u will still be around.
1st, my platform is 32bit application....shared memory as in , the piece of C++ codes will receives multiple request, put them into memory locations.I think the purpose is to avoid error due to concurrent access of memory location. so actually i do not know whether they are threads or processes ....i dun tink it's process ....they r juz messages stored temporary in the memory location, waiting to be retrieve to be process ....
I shall try ur coding method 1st, so do stay around so tat i can give u the pts ...:)
0
 
agreenCommented:
Use the CreateFileMapping() function to create a segment of memory that may be mapped into more than one process.

The first process uses CreateFileMaping() to get a handle to the file.  It specifies a name for the file mapping object in the last parameter.  The second process uses OpenFileMapping() and specifies the name of the file mapping object the first process created. Then the two processes use the handle in the MapViewOfFile() function to map the file into their memory spaces.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
nietodCommented:
SkyWolf, you do not have to reject an answer when you just want the expert to give more information.  When th question is locked, the expert can still add comments to the question, as can you.  In fact in most cases, an expert will answer a question and a "dialog" between the expert and the client will start until the problem is completely solved.
0
 
msa092298Commented:
Supposing you are running under windows (you didn't mention the platform).
If you are running a dll that will be run from a service (eg. ISAPI extension DLL) then all the dlls under that service share the same memory locations and file handles.  Your callback functions are called from different threads but inside the same process (or application).  If you service the request through web CGIs then they are run in different processes so they cannot share the memory,  only the code.   Inside threads, you can share memory easily using critical sections. Don't ever forget to free the critical section (LeaveCriticalSection) before leaving the thread, otherwise other threads will be blocked forever.   Also, only the thread that entered the critical section can leave it.  Initialize the critical section and shared data once in the startup of your code, and DeleteCriticalSection after all threads have done their work and before the whole dll is removed from memory.
How?
I usually define a single object from a hidden class in my DLL, the constructor of that object initializes all the data and all the critical sections.  The destructor destroys the global static data and the global critical sections.
e.g.

static CRITICAL_SECTION c1;
void Lock1() {EnterCriticalSection(&c1);}
void UnLock1() {LeaveCriticalSection(&c1);}
static CRITICAL_SECTION c2;
void Lock2() {EnterCriticalSection(&c2);}
void UnLock2() {LeaveCriticalSection(&c2);}
static CRITICAL_SECTION c3;
void Lock3() {EnterCriticalSection(&c3);}
void UnLock3() {LeaveCriticalSection(&c3);}

static MyDataType *mySharedData;

class initializer
{
public:
initializer()
{
  InitializeCriticalSection(&c1);
  InitializeCriticalSection(&c2);
  InitializeCriticalSection(&c3);
  mySharedData=new MyDataType();
}

~initializer()
{
  Lock1();UnLock1(); // ensure that none is waiting for it.
  Lock2();UnLock2(); // ensure that none is waiting for it.
  Lock3();UnLock3(); // ensure that none is waiting for it.
  DeleteCriticalSection(&c1);
  DeleteCriticalSection(&c2);
  DeleteCriticalSection(&c3);
  delete mySharedData;
  mySharedData=NULL; // safeguard against using freed memory.
}
} theInitializer; // the only object of this type.
0
 
gysbert1Commented:
agreen, sorry but I cannot see how your answer is any different from that of msa. I think that msa's answer is closer to the solution here and I would reject yours.

The question here would be how many different programs can access the memory and will they be on the same machine (and thus the same platform).

If you were using threads, beleive me you would know it !

If you say the messages get put in a temporary location for later retreival, how is this done, does the same application that generates the messages read them in again ?

If you use threads you do not need shared memory since the memory space is shared between threads. You would have to use a critical section to PREVENT concurrent access. This pauses the one thread until the other releases the critical section for use.

If you do not the only reason for shared memory would be if you have more than one process (or application) that needs to share the memory. In this case you would also need to use semaphores in order to allow concurrent access.

If none of the above apply the only reason to use any of the above would be because of interrupted processing. In this case an interrupt could cause one function to interrupt the other while it is modifying the data. This is a common scenario when using timers. In this case you cannot use a critical section or shared memory (as me if you cannot figure out why !)

Memory mapped files as mentioned by msa are another method for inter process (application) communication and falls in the shared memory case.

Shared memory is handled  using shmget and related functions. If you still need info on that we can talk.
0
 
SkyWolfAuthor Commented:
ok, everyone be bear with me , bcoz right now i cannot get the codes to run due to some missing *.h files ... some declarations are missing , and the guy who knows where the files are is not available ... i shall post the codes here ...

    #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(DB_TYPE));
    memset((queue+line),'\0',sizeof(DB_TYPE));
    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",rmsg.retcode);
    else
    return -5;
    if (cols != NULL)
    sprintf(cols,"%02d",rmsg.cols);
    else
    return -6;
    if (rows != NULL)
    sprintf(rows,"%02d",rmsg.rows);
    else
    return -7;
    return 1;
    }
    i++;
    Sleep(500);
    }
    memset((queue+line),'\0',sizeof(DB_TYPE));
    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,server,ssql,rsql,retcode,cols,rows,strlen(ssql),MAX_SIZE);
    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,server->u.value,ssql->u.ptr,
    rsql->u.ptr,retcode->u.ptr,cols->u.ptr,rows->u.ptr,
    ssql->length,rsql->length);
    if (r == 1)
    {
    LeaveQueue();
    return 1;
    }
    else
    {
    LeaveQueue();
    return r;
    }
    }
0
 
SkyWolfAuthor Commented:
hi agreen,
as u can see, the piece of code which i have just posted contains the CreateFileMapping and MapViewOfFile.
hi all,
i tink i did not make myself clear during the last comment. :) i am really not aware that i do not have to reject MSA's answer to comment ...and that this code cannot be compiled due to some missing declarations or something therefore i cannot make changes to this code.
0
 
nietodCommented:
skywolf, in order to comment just leave the grades blank, that is, don't mark reject or one of the grades, and type a new comment in the comment box, then press submit.  
0
 
msa092298Commented:
You will have a lot or concurrency bugs!   You see, 2 or more threads (or processes) may try to write at the same position at the same time, you cannot know exactly which will write first and the data might end up in a mixture of the 2 or more messages.  This depends on when the OS will switch between them.
It seems you are using threads, i.e. all your code resides in the same exe or dll or in different dlls loaded by the same application.  This makes the memory shared by all the DLLs and the exe.   All you need here is a linked list of messages with a critical section which controls concurrency when adding to the end of the list or removing from the top of it.
Yo will need to define a structure for your data that contains the data to post in the message list and a pointer to next member in the list (needed by the following code).
assuming this is your global data include the following code once in one of your files:
==================================================
// the following not needed to be global as long as
// it is in the same file.
static CRITICAL_SECTION c1;  
static void Lock1() {EnterCriticalSection(&c1);}  
static void UnLock1() {LeaveCriticalSection(&c1);}
MyDataType *head;
MyDataType *tail;

static class initializer
{
  public:
  initializer()
  {
    InitializeCriticalSection(&c1);
    head=NULL;
    tail=NULL;
  }
  ~initializer()
  {
     Lock1();UnLock1(); // ensure that none is waiting for it.
     DeleteCriticalSection(&c1);
  }
} theInitializer; // the only object of this type.
 //assuming appending at tail and removing at head
 //now whenever you want to add
void AddToList (MyDataType *data)  // must be global
{
   data->next=NULL;
   Lock1();  // only this thread can change the list
   // can safely and quickly access the shared data.
   if (tail)
     tail->next=data;
   else
     head=data;  // this is the first entry in the list
   tail=data;
   Unlock1(); // other threads can access the shared data safely.
}
MyDataType *RemoveFromList() // must be global
{
   // returns NULL if the list is empty
   MyDataType *data;
   Lock1();
   // can safely and quickly access the shared data.
   *data=head; // whether NULL or not.
   if (head)
   {
      head=head->next;  // may become NULL if the last item
      if (!head)  // the last one in the list
         tail=NULL;
   }
   UnLock1();  // other threads can now access it.
   return data;
}
==================================================

0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 3
  • 3
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now