circular referencing classes with two-way by-value conversionfunctions

J

Joshua Maurice

Take this example code:

// // // //

#include <boost/shared_ptr.hpp>

class ConstBuffer;

//The goal of the two separate buffer classes, Buffer and ConstBuffer,
//and the two conversion functions makeConst and makeWritable,
//is multifold:
//- The user can pass these around by value efficiency, as they have
reference
// semantics, thus avoiding dynamic allocation worries
//- To guarantee that for a single BufferImpl, that there is exactly
one
// write view on it, or multiple read views. This allows us to
share
// BufferImpl objects without having to do deep copies or have the
user
// worry about synchronization of buffers.

//Has reference semantics, implemented with Boost::shared_ptr
class Buffer
{
private:
friend class ConstBuffer;
struct BufferImpl
{ //[insert stuff]
};

public:
~Buffer() {}

//[insert functions to read and write to the actual buffer]

private:
friend class ConstBuffer;

Buffer(BufferImpl* buf) : x(buf) {}
Buffer(boost::shared_ptr<BufferImpl> y) : x(y) {}

Buffer(Buffer const& ); //not defined, not copyable
Buffer& operator= (Buffer ); //not defined, not copyable

boost::shared_ptr<BufferImpl> x;
};

//Has reference semantics, implemented with Boost::shared_ptr
class ConstBuffer
{
public:
ConstBuffer(ConstBuffer const& buf) : x(buf.x) {}
ConstBuffer& operator= (ConstBuffer const& buf) { x = buf.x; }
~ConstBuffer() {}

//[insert functions to read from the actual buffer]

//Sets this to null pointer. Returns a copy of this which is
writable.
//(Note that this is optimized to return shallow copy when only a
single
//read view exists on the buffer.)
Buffer makeWritable()
{ if (x.unique())
{ Buffer retVal(x);
x.reset();
return retVal;
}else
{ Buffer retVal(new Buffer::BufferImpl(*x));
x.reset();
return retVal;
}
}

//Sets buf to the null pointer. Returns a copy of buf which is
const.
//(Note that this is optimized to not do a deep copy.)
static ConstBuffer makeConst(Buffer& buf)
{ ConstBuffer retVal(buf.x);
buf.x.reset();
return retVal;
}
private:
ConstBuffer(boost::shared_ptr<Buffer::BufferImpl> y) : x(y) {}
boost::shared_ptr<Buffer::BufferImpl> x;
};

// // // //

I think I would prefer it if I could have makeConst and makeWritable
be namespace scope functions, or makeConst to be a non-static member
of Buffer and makeWritable be a non-static member of ConstBuffer.
However, I don't seem to be able to do that. I'd like there to be some
symmetric in the interface for ease of use, either they're both non-
static member functions or they're both namespace functions. I don't
really like the extra typing you would have to do if they were static
class member functions. I'd prefer to have ADL kick in with namespace
scope functions or have both be member functions.

At least, I don't think I can do this and maintain encapsulation, aka
keep the data members private. I know that anyone can easily defeat
encapsulation if they feel like it, but keeping the private things
private still fulfills a purpose, and I'd rather not rely on a big
note saying "DON'T USE THIS OR ELSE!" ... Maybe if I did some hackery
with subclasses, I could pull this off...

The use case is: my company performs jobs on data which is split up
into separate threads, where each thread is a data sink, a data
source, or it performs a transformation on its input data to produce
output data. The relationship between these different threads can be
quite complex and is not a simple chain: one thread can send data to
multiple threads, and one thread can read data from multiple reader
threads. I was thinking about a cleaner abstraction for use in the
engine, and I was toying around with this.

Has anyone encountered something similar? And how was it resolved? And
how would you resolve it yourself? I'm probably agonizing over
something not worth agonizing over.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top