Solved

Shared Memory

Posted on 1998-09-23
10
494 Views
Last Modified: 2012-06-27
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
Comment
Question by:SkyWolf
  • 3
  • 3
  • 2
  • +2
10 Comments
 
LVL 1

Expert Comment

by:msa092298
ID: 1173513
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
 

Author Comment

by:SkyWolf
ID: 1173514
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
 
LVL 4

Expert Comment

by:agreen
ID: 1173515
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
Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

 
LVL 22

Expert Comment

by:nietod
ID: 1173516
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
 
LVL 1

Expert Comment

by:msa092298
ID: 1173517
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
 
LVL 2

Expert Comment

by:gysbert1
ID: 1173518
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
 

Author Comment

by:SkyWolf
ID: 1173519
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
 

Author Comment

by:SkyWolf
ID: 1173520
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
 
LVL 22

Expert Comment

by:nietod
ID: 1173521
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
 
LVL 1

Accepted Solution

by:
msa092298 earned 170 total points
ID: 1173522
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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
MSVCR80.dll crash 2 141
FMX enumerated colours 2 117
Task manager indicates my c++ program memory consumption is growing? 12 123
draw a Christmas tree by using a nested loop? 26 77
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question