-->

Share CGAL's geometry between processes in C++

2019-05-03 11:29发布

问题:

I'm looking for the fastest way to send CGAL's geometry between processes (C++). Lets assume, that we have 2 processes - A and B. Process A is generating geometry and process B is displaying it. I want to connect them in the fastest awailable way. The geometry is of CGALs Polyhedron type.

I know I can use shared memory, but then I've got some problems:

  1. When I want to copy geometry from process A to shared memory I can use streaming Polyhedron to/from OFF format, but I’m not interested in it, because conversion to this format is too slow for my purpose.
  2. I can create shared memory and use "placement new" to create my object in shared memory and overcome the overhead of streaming and conversion, but then I have no further control of memory allocation by internal Polyhedron functions. (For example when adding new vertex with Polyhedron_incremental_builder_3 I can’t specify where exactly in the memory it should be placed – I can just call B.add_vertex( Point( 0, 0, 0)); and memory allocation is handled in that method internally)

Is there any way to create object in a specific place in shared memory and ensure, that it and its dynamic structures will "live" in this memory?

Or maybe there’s another fast way of sharing dynamic data (ie. Halfedge structures) between two processes?

回答1:

I have no further control of memory allocation by internal Polyhedron functions.

You actually do have control.

The reference manual says:

The class Polygon_2 implements polygons. The Polygon_2 is parameterized by a traits class and a container class. The latter can be any class that fulfills the requirements for an STL container. It defaults to the vector class.

In addition to using placement new for the polygon itself, you need a container that you can place in the shared memory. You can try to use boost::interprocess::vector, or roll your own container class.

If you use boost::interprocess::vector, you will need to create a wrapper class for it, because unlike an STL container, its constructor requires an allocator object. Polygon_2 will not be able to construct it correctly. So you will have to get your shared memory allocator object from some kind of global variable. For example:

using namespace boost::interprocess;
typedef allocator<int, managed_shared_memory::segment_manager>  ShmemAllocator;
ShmemAllocator some_global_shmem_allocator;
template <typename T>
class my_shared_memory_vector : vector<T, ShmemAllocator>
{
public:
  my_shared_memory_vector() : vector(some_global_shmem_allocator) {}
};

Disclaimer: I have not actually done any of this myself. If your computer catches flame as a result of doing this and your house burns down, don't hold me responsible. It would be wise to double-check (by looking at the GCAL source) that any memory Polygon_2 allocates is actually managed by the container.

Edit: I have misread the question, it asks about Polyhedra, not Polygons. See comment below.



回答2:

Of course, the most obvious thing to do would be to use threads instead of processes. That would solve the whole problem with no effort at all.

Other than that, short of hacking the runtime library of your compiler to replace its memory management, you can actually override "operator new" for a class, and/or you can provide a global one. This will let you replace "new" calls with your own memory allocation code. You could use a global flag that you set before making CGAL calls and reset afterwards, to tell the memory allocator what memory heap you want to use (you will obviously have to make some form of heap management for the shared memory).

Overriding the new operator will only work for "new" calls, of course. Anything that gets allocated e.g. through malloc() or some system call isn't going to go through your code. You could try to provide your own malloc() and free() calls (functions contained in object files are preferred over functions from libraries) to see if this can work, but these would probably have to deal with the operating system for the memory management since you loose the library functions. It's definitely going to be messy.