<div dir="ltr">Hi Dimitris,<br><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jan 17, 2016 at 8:57 AM, Dimitris Chloupis <span dir="ltr">&lt;<a href="mailto:kilon.alios@gmail.com" target="_blank">kilon.alios@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <br><div dir="ltr">I attach the forwarded post I posted in pharo-users but if you want the summary its a collection of questions whether its possible to use memory mapped files shared memory with Pharo VM for IPC. I thought to forward also here since this may be a VM related too. Any help is appreciated<br><div><br><div class="gmail_quote"><div dir="ltr">---------- Forwarded message ---------<br>From: Dimitris Chloupis &lt;<a href="mailto:kilon.alios@gmail.com" target="_blank">kilon.alios@gmail.com</a>&gt;<br>Date: Sun, Jan 17, 2016 at 6:41 PM<br>Subject: Memory mapped files and Pharo (aka Unreal Engine 4 integration with Pharo)<br>To: Any question about pharo is welcome &lt;<a href="mailto:pharo-users@lists.pharo.org" target="_blank">pharo-users@lists.pharo.org</a>&gt;<br></div><br><br><div dir="ltr"><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div>An apology for the long post but this is not a simple issue and hence not a simple question.<br></div><div><br>So I am looking into ways to integrate Pharo with Unreal to bring some nuclear powered graphics to Pharo and make us first class citizents to 2D and 3D world.<br><br></div>For those not aware this is unreal <br><br><a href="https://www.unrealengine.com/what-is-unreal-engine-4" target="_blank">https://www.unrealengine.com/what-is-unreal-engine-4</a><br><br></div>As suprising it may sound Unreal and Pharo share a lot in common <br><br></div>1) Both integrated languages with IDEs<br></div>2) Both promote live coding and live manipulation of data<br></div>3) Both promote visual coding<br></div>4) Both promote ease of use and wizard based development (aka RAD)<br><br></div>Unreal is indeed a C++ based project made to be used by C++ coders but it comes with a very powerful visual coding language that can map visual nodes to any C++ function/Method and another common ground with Pharo is the very strict OO nature of both projects. But then OOP is very big in game development anyway. <br><br></div>Of course my goal is not to force Pharoers to learn C++, but rather make a Pharo API so Pharo can be used to do some simple graphics development in the start and then we can continue importing more and more functionality. Unreal is generally a heavy engine that requires quite a powerful GPU but its rendering is just amazing. <br><br></div>So how I make Pharo talk to Unreal is the million dollar question.<br><br></div>The road of compiling Unreal as a set of DLLs to be loaded by Pharo via FFI is a road full of thorns because its quite an undertaking cause Unreal is HUGE and it will be nightmare to maintain since Unreal moves forward very fast.<br><br></div>So we come to the subject of IPC, or Inter Process Communication. I am not new to this as you know I have build a socket bridge between Pharo and Python that allows Pharo to use Python libraries and in my implementation I focus on Blender Python API. <br><br></div>But sockets are not exactly blazzing fast, calling functions is fine because you can even get responses bellow 1 millisecond but if try to run some heavy loops you will be in trouble. There are work arounds of course, like sending the loop with the socket and language etc but they overcomplicate something that at least in my opinion should remain simple. <br><br></div>Another IPC method is shared memory, it is what it says , basically processes that share a place in memory where they can access the same data. Extremely fast but it has its own traps for example how to make sure the processes dont access the same data at the same time etc. <br><br></div>So after some reading I came across to a shared memory model called Memory mapped files, basically what that means is essentially a virtual file that resides on memory (it may also reside on the hard disk or other permanent physical storage but its not necessary) that different processes can access. <br><br></div>So in our case we can have memory mapped file that Unreal , Pharo and even Blender can access where we can store command / messages that each diffirent application must execute, let them share data and sky is the limit. <br><br></div>Now I know this will not be a walk in the park specially to someone like me a C++ noob but I am looking for the Pharo wisemen wisewomen to guide me at least through the obstacles of this. <br><br></div>So the questions are the following <br><br></div>1) Do you think this is possible with the current Pharo ?<br></div></div></div></div></div></div></div></div></blockquote><div><br></div><div>You should be able to map a file via the FFI calling mmap, and access it via an ExternalPointer.  But that&#39;s crappy.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><div class="gmail_quote"><div dir="ltr"><div><div><div><div></div><br>2) Will I be limited by the fact that the VM currently does not multithread or cannot use multithreading libraries ? ( I have no intention of using multithreading but some handling of process access to the data may be necessary to make sure data is safe from concurent modification) <br></div></div></div></div></div></div></div></blockquote><div><br></div><div>As you&#39;ve noticed we intend to provide a threaded FFI that will allow you to use threaded libraries.  But that&#39;s not really the issue.  There must be some handshaking protocol for the two halves to communicate via shared memory without conflict.  The threaded FFI should make it possible to call e.g. pthread_cond_wait to synchronise, but a lower-level test-and-set or conditional move facility would be nicer.  See below.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><div class="gmail_quote"><div dir="ltr"><div><div><div></div>3) Is there anything else I should be aware of as common pitfalls for such implementation ? <br><br></div>4) Can the current FFI help in this task or would I need to implement this as a C DLL and load it from Pharo<br></div></div></div></div></div></blockquote><div><br></div><div>Forgive me for diving down a bit before I answer your question, but I find being concrete helps.</div><div><br></div><div>Spur has a segmented memory model.  When one grows the heap the VM allocates memory via mmap and integrates it with the rest of the heap by using &quot;bridge&quot; objects at the end of each segment.  A bridge object is two 64-bit words.  It says &quot;I am a bytes object&quot; so that the GC will never look inside the object, and it lies about its size, saying &quot;I am large enough to span to the start of the next segment&quot;.  So when adding a new segment, the bridge in the segment before the new one is &quot;shortened&quot; to point to the start of the new segment, and a new bridge is added to the end of the segment so that it points to the start of the next segment in memory.  The last segment&#39;s bridge has a zero length.  Spur also provides pinning, as simple as a per-object flag that tells the GC not to move an object.  So bridges are pinned, and hence compaction leaves bridges unmolested, but any object in old space can be pinned also.</div><div><br></div><div>So an elegant way of providing shared memory in Spur would be to add a &quot;map a file as a byte array&quot; primitive.  There are issues with this.  The first 16 bytes of the mapped file would have to be used to construct the header for a ByteArray that would comprise the rest of the segment, excepting another 16 bytes at the end that would need to be a bridge.  So if you wanted to share this with another application you&#39;d probably want to allocate a file that was, say, 2k bytes bigger than needed, and use the first and last 1k bytes to hide the header and the bridge.</div><div><br></div><div>Ah, better still would be to construct three objects in the segment, an initial ByteArray that stretches to 16 bytes before the second page, a ByteArray whose contents start at the beginning of the second page and reach all the way to the penultimate page, and then a ByteArray to reach from the end of the penultimate page to the bridge at the end of the mmapped file segment.  All three objects could be pinned and be prevented from being GC&#39;ed until the entire segment was released.  That would give you a ByteArray (the middle of the three) whose contents were all but the first and last pages of the mmapped file, aligned on a file page boundary and whose length was a multiple of the page size.  C++/C clients could then map the central portion and use e.g. pointers to access it.</div><div><br></div><div>To implement this there would be an mmap-file-as-segment primitive and perhaps a release-segment primitive, or some magic in the GC to release the segment when the ByteArrays were no longer accessed.</div><div><br></div><div>So then I could imagine test-and-set or conditional-move primitives on ByteArray that supported manipulating locks in a ByteArray, and by extension, in the shared file.  I think this kind of approach would give you the fastest, most direct access to shared memory I can think of.  Does this appeal?</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><div class="gmail_quote"><div dir="ltr"><div>PS: I have no intention of messing with the Pharo VM and I also want to avoid the use of plugins as I want this to work with standard Pharo distributions. </div></div></div></div></div></blockquote></div><div><br></div><div class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div></div>