Shared Memory

Share your advanced PureBasic knowledge/code with the community.
User avatar
RichAlgeni
Addict
Addict
Posts: 935
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Shared Memory

Post by RichAlgeni »

Thanks to Mistrel & Siggi Rings for their code. I used it as a base to understand how to write a shared memory process. There are two programs, a producer and a consumer. The producer creates the shared memory, and the consumer is able to read it.

Code: Select all

; shm_producer.pb

EnableExplicit

Procedure.i CreateMap(*MapName, Size.i)

    Protected hFileMap.i
    Protected *MapView.i
    Protected Security.SECURITY_ATTRIBUTES

    hFileMap = CreateFileMapping_(-1, 0, #PAGE_READWRITE, 0, Size, *MapName)
    ProcedureReturn hFileMap

EndProcedure

Procedure.s GetMapString(*MapName)

    Protected hFileMap.i
    Protected *MapView
    Protected Value.s

    hFileMap = OpenFileMapping_(#FILE_MAP_ALL_ACCESS, 0, *MapName)
    If hFileMap
        *MapView = MapViewOfFile_(hFileMap, #FILE_MAP_WRITE, 0, 0, 0)

;/ Read the map value to the file then Unmap the mapped view of the file from memory

        If *MapView
            Value = PeekS(*MapView)
            UnmapViewOfFile_(*MapView)
        Else
            Value = ""
        EndIf
        CloseHandle_(hFileMap)
    Else
        Value = ""
    EndIf

    ProcedureReturn Value

EndProcedure

Procedure.i SetMapString(*MapName, *Value)

    Protected hFileMap.i
    Protected *MapView
    Protected Value.s    = PeekS(*Value)
    Protected retValue.i = #False

    hFileMap = OpenFileMapping_(#FILE_MAP_ALL_ACCESS, 0, *MapName)
    If hFileMap
        *MapView = MapViewOfFile_(hFileMap, #FILE_MAP_WRITE, 0, 0, 0)

;/ Write the map value to the file, then Unmap the mapped view of the file from memory

        If *MapView
            PokeS(*MapView, Value)
            UnmapViewOfFile_(*MapView)
            retValue = #True
        EndIf
        CloseHandle_(hFileMap)
    EndIf

    ProcedureReturn retValue

EndProcedure

Procedure.i CloseMapPtr(*MapPtr)

    Protected Value.i

;/ Unmap the mapped view of the file from memory

    If UnmapViewOfFile_(*MapPtr)
        Value = #True
    Else
        Value = #False
    EndIf

    ProcedureReturn Value

EndProcedure

Procedure CloseMap(hMap)

    Protected Value.i

    If CloseHandle_(hMap)
        Value = #True
    Else
        Value = #False
    EndIf

    ProcedureReturn Value

EndProcedure

Define hMap.i
Define *MapView
Define MapName.s = "SharedMapName"
Define sendStr.s = ""
Define mapSize.i = 512

hMap = CreateMap(@MapName, mapSize)

;/ Output from source

OpenConsole()

sendStr = "First string to be sent..., start consumer process"
SetMapString(@MapName, @sendStr)
PrintN("Set Map = " + GetMapString(@MapName))

Repeat

    PrintN("")
    Print("Enter text To send, or press <enter> to quit: ")
    sendStr = Input()

    If sendStr <> ""
        SetMapString(@MapName, @sendStr)
        PrintN("Set Map = " + GetMapString(@MapName))
    Else
        Break
    EndIf

ForEver
    
CloseMapPtr(*MapView)
CloseMap(hMap)

CloseConsole()

End

Code: Select all

; shm_consumer.pb

EnableExplicit

Procedure.i GetMapPtr(*MapName)

    Protected hFileMap.i
    Protected *MapView
    Protected Value.i = #False

    hFileMap = OpenFileMapping_(#FILE_MAP_ALL_ACCESS, 0, *MapName)

    If hFileMap
        *MapView = MapViewOfFile_(hFileMap, #FILE_MAP_WRITE, 0, 0, 0)

        If *MapView
            Value = *MapView
        EndIf

        CloseHandle_(hFileMap)
    EndIf

    ProcedureReturn Value

EndProcedure

Define *MapView
Define MapName.s  = "SharedMapName"
Define sentText.s = ""

;/ Output from source

OpenConsole()

;/ Output from other process

Repeat

    *MapView = GetMapPtr(@MapName)
    If *MapView > 0
        sentText = PeekS(*MapView)
        If sentText <> ""
            PrintN("Read Map = " + sentText)
            PrintN("")
            PrintN("Press <enter> to check shared memory")
            Input()
        Else
            Break
        EndIf
    Else
        Break
    EndIf

ForEver

CloseConsole()

End
Switch between the two, you'll see how they work.

Question for those who may know: Can there be a possibility of IMA's if a read is done while data is being written to the shared memory? Has anyone handled such a situation?

Rich
User avatar
idle
Always Here
Always Here
Posts: 5915
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Shared Memory

Post by idle »

thanks good tip.

No you shouldn't get an IMA
See here for details on file mapping
http://msdn.microsoft.com/en-us/library ... s.85).aspx
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
RichAlgeni
Addict
Addict
Posts: 935
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: Shared Memory

Post by RichAlgeni »

Idle, can you repost your link? It's broken.
User avatar
luis
Addict
Addict
Posts: 3895
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Shared Memory

Post by luis »

If you hover on it you can see the part missing and rebuild it:

Code: Select all

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366556(v=vs.85).aspx
"Have you tried turning it off and on again ?"
User avatar
RichAlgeni
Addict
Addict
Posts: 935
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: Shared Memory

Post by RichAlgeni »

Thanks Luis!
Nico
Enthusiast
Enthusiast
Posts: 274
Joined: Sun Jan 11, 2004 11:34 am
Location: France

Re: Shared Memory

Post by Nico »

RichAlgeni,

Your code is welcome but it is not a novelty, code similar have already been posted (Original code coded by me in 2004), already eight years ago, here:
http://www.purebasic.fr/english/viewtop ... ViewOfFile
User avatar
RichAlgeni
Addict
Addict
Posts: 935
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: Shared Memory

Post by RichAlgeni »

Then thanks to Nico too!

It was never my intent to claim credit for anyone else's code. It's just that it helps me better understand it when I deconstruct it, then build it back up as I might do it.

Rich
Nico
Enthusiast
Enthusiast
Posts: 274
Joined: Sun Jan 11, 2004 11:34 am
Location: France

Re: Shared Memory

Post by Nico »

No problem :)
Post Reply