DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 12 of 12

Thread: Shared memory in DLL's

  1. #1
    Join Date
    Oct 2006
    Posts
    5

    Shared memory in DLL's

    Hi,

    I'm at my first attempt at creating a DLL that utilizes memory area that is shared between all instances of the DLL. This is the shared section declaration:

    Code:
    #pragma data_seg(".ESC_SHARED")
    unsigned char		sg_pXMLBuffer[XMLBUFFER_SIZE];
    volatile bool		sg_bLocked;
    Message		sg_iMessage		= MSG_NoMessage;
    #pragma data_seg()
    #pragma comment(linker,"/SECTION:.ESC_SHARED,RWS")
    The idea is that an application should be able to post a message in the sg_iMessage, telling another instance to retrieve the data in sg_pXMLBuffer and process it. The problem is that the data in sg_pXMLBuffer never changes in the "remote" instance. The other variables (sg_bLocked and sg_iMessage) propagate nicely into all other instances, but when i change something in sg_PXMLBuffer, it still appears to be all 0's in the other instances. Why? XMLBUFFER_SIZE is 32k by the way.

    EDIT: I should probably add that I'm using VS2005

  2. #2
    Join Date
    Oct 2006
    Posts
    5
    Found it myself.
    For anyone who interested:

    It turns out I need to initialize the memory or it will be "optimized away"(?).
    The following works fine:

    Code:
    #pragma data_seg(".ESC_SHARED")
    unsigned char		sg_pXMLBuffer[XMLBUFFER_SIZE] = { 0 };
    volatile bool		sg_bLocked = false;
    MessengerMessage	sg_iMessage = MSG_NoMessage;
    HHOOK				sg_hCallCBTHook	= 0;
    #pragma data_seg()
    #pragma comment(linker,"/SECTION:.ESC_SHARED,RWS")
    Feel free to lock the thread :)

  3. #3
    Join Date
    Nov 2003
    Posts
    4,118
    Is there a reason why sg_pXMLBuffer isn't volatile? It could also be the cause of that "optimization".
    Danny Kalev

  4. #4
    Join Date
    Oct 2006
    Posts
    5
    i didn't declare it volatile since i wont be looking for changes in it in a tight loop, as I do with sg_bLocked. As such:

    while(sg_bLocked)
    ;

    So i figured it wouldn't be subject to cache trouble. However, it should be pointed out that my understanding of when to declare stuff as volatile isn't as good as I'd like it to be. I rarely use it, and most often it's on data that might be changed by another thread, an interrupt etc.

  5. #5
    Join Date
    Nov 2003
    Posts
    4,118
    volatile has little to do with tight loops. You should declare any object that can be changed asynchronously as volatile. In this case, sg_pXMLBuffer might be modified by another thread or DLL asynchronously. If another thread has a cached copy of sg_pXMLBuffer, and the memory buffer has changed behind its back, the program's behavior is undefined.
    Danny Kalev

  6. #6
    Join Date
    Apr 2006
    Location
    Zagreb, Croatia
    Posts
    152
    Quote Originally Posted by korona
    Hi,

    I'm at my first attempt at creating a DLL that utilizes memory area that is shared between all instances of the DLL. This is the shared section declaration:

    Code:
    #pragma data_seg(".ESC_SHARED")
    unsigned char		sg_pXMLBuffer[XMLBUFFER_SIZE];
    volatile bool		sg_bLocked;
    Message		sg_iMessage		= MSG_NoMessage;
    #pragma data_seg()
    #pragma comment(linker,"/SECTION:.ESC_SHARED,RWS")
    Unfortunately the pragma data_seg() won't work in c++ builder and it may not work in some other compilers (other than VC++). So here's another solution to creating a shared memory area.

    HANDLE hsm = 0; //handle to a shared memory file
    LPVOID lpshrmem = NULL; //pointer to shared memory area

    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {

    bool initproc=0;

    switch (reason) {
    case DLL_PROCESS_ATTACH:

    hsm = CreateFileMapping((HANDLE)0xffffffff,NULL, PAGE_READWRITE,0,1024,"DLLSHAREDDATA");
    if (!hsm)
    return 0;
    initproc = (GetLastError() != ERROR_ALREADY_EXISTS);
    lpshrmem = MapViewOfFile(hsm, FILE_MAP_WRITE,0,0,0);
    if (!lpshrmem)
    return 0;
    if (initproc)
    memset(lpshrmem, '\0',1024);//zero initialize the memory
    break;
    case DLL_THREAD_ATTACH:
    //DisableThreadLibraryCalls(hinst);
    break;

    // The thread of the attached process terminates.

    case DLL_THREAD_DETACH:
    break;
    case DLL_PROCESS_DETACH:

    // Unmap shared memory from the process's address space.


    UnmapViewOfFile(lpshrmem);

    // Close the process's handle to the file-mapping object.

    CloseHandle(hsm);

    break;

    default:
    break; }
    return 1;
    }

  7. #7
    Join Date
    Nov 2003
    Posts
    4,118
    You're right, #prgamas by their nature aren't portable so it's best to avoid them when possible if the code is meant to be used by various compilers. Anyway, you should note that this code will only work on specific variants of Windows, certainly not POSIX.
    Also, instead of using hard coded literals and magic numbers such as 1024 it's best to use a constant. Different OSs have different page sizes. Finally, I would check the initproc value right after assigning it.
    Danny Kalev

  8. #8
    Join Date
    Nov 2006
    Posts
    7

    Is there a reason why sg_pXMLBuffer isn't volatile

    Quote Originally Posted by Danny
    Is there a reason why sg_pXMLBuffer isn't volatile? It could also be the cause of that "optimization".
    Is there a reason why sg_pXMLBuffer isn't volatile

  9. #9
    Join Date
    Nov 2006
    Posts
    7

    Is there a reason

    Quote Originally Posted by geeta
    Is there a reason why sg_pXMLBuffer isn't volatile
    Is there a reason why sg_pXMLBuffer isn't volatile

  10. #10
    Join Date
    Apr 2006
    Location
    Zagreb, Croatia
    Posts
    152
    Hi, Danny
    initproc need not be checked first because the first dll to create a shared memory area will initialize the memory. The other dll instances will always have 0 for initproc and MapViewOfFile will simply return a pointer to the already allocated shared memory.

  11. #11
    Join Date
    Nov 2003
    Posts
    4,118
    OK, another nit. Wouldn't it be better to declare it like this:

    bool initproc = (GetLastError() != ERROR_ALREADY_EXISTS);

    I would also prefer a Boolean value as the initializer, i.e., bool initproc=false. Anyway, thanks for the clarification.
    Danny Kalev

  12. #12
    Join Date
    Jun 2006
    Posts
    15
    As far as volatility goes, korona, you are confusing "volatile" with "register". Register is a suggestion to the compiler to place the variable in a register for faster access. Volatile on the other hand, means asynchronous access, as was mentioned above.

    I would personally use GlobalAlloc with GMEM_MOVEABLE and GMEM_SHARED, but I supposed you can do it this way. Are there any advantages to one way or another?

Similar Threads

  1. Re: App Object (fixes)
    By Rob Teixeira in forum .NET
    Replies: 129
    Last Post: 06-06-2002, 05:23 AM
  2. App Object
    By Rob Teixeira in forum .NET
    Replies: 15
    Last Post: 05-31-2002, 03:30 PM
  3. help memory
    By kathy in forum Java
    Replies: 0
    Last Post: 11-02-2001, 05:22 PM
  4. How To Do It - Shared Class Variables Part III
    By Patrick Ireland in forum .NET
    Replies: 5
    Last Post: 05-10-2001, 06:19 PM
  5. Replies: 0
    Last Post: 04-26-2001, 10:01 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center