Designing a template class for memory access (part 2)

J

James Brown

Hi again,

I'm referring back to my previous posting of the same title,
with everyone's help I've now got a better understanding of what my
goals are and I have a class which now looks like:

template <typename type>
class PhysMem
{
public:
type & operator [] (size_t index);
type operator * ( );
type * operator -> ();


private:
type *PhysMem;

void phys_readmem(void *dest, const void *phys, size_t len);
void phys_writemem(void *phys, const void *src, size_t len);
};


I have listed the three main public interfaces that I am interested in,
as I basically want my class to behave like a pointer to a memory region.
So if I had a "normal" pointer to somewhere in memory, it would do this:

struct mystruct
{
int member1, member2;
};

mystruct *ptr = (mystruct *) 0x12345678; // put in my memory region here

mystruct[0].member1 = 1; // use the pointer to address my memory region
mystruct->member1 = 2;

And if I had a "PhysMem" template class object, then it would do exactly the
same:

PhysMem<mystruct> ptr;
ptr->member1 = 2; // etc

This (in theory) works great with my current class design -
OK so the problem I face is as follows. I have an existing "C" interface to
my
physical memory, using two functions:

void phys_readmem(void *dest, const void *phys, size_t len);
void phys_writemem(void *phys, const void *src, size_t len);

This function takes care of mapping/unmapping physical memory, and what
happens when
memory accesses cross segment boundaries etc. I somehow need to build my C++
class around this C interface, the problem being I don't know how. Take for
example
the member-selection operator:

template <typename type>
type * PhysMem<type>::eek:perator -> ()
{
return ???;
}

The function above must return a pointer to some memory. The problem is,
I ideally want to use the phys_writemem or phys_readmem routine, but where
do I copy the memory to
so I can return it? I need some kind of intermediate buffer, but how do I
manage the
lifetime of this buffer? And how do I handle a write-operation?

i.e. ptr->member1 = some_value;

I need to have control over the mystruct::eek:perator= and invoke the
phys_writemem routine
when appropriate - the problem is, I have returned a general pointer in the
operator-> function
and it is too late at this stage.

I hope I have explained my thoughts clearly enough for someone to
have a stab at this one.

TIA,
James
 
M

Max Vasin

James Brown said:
Hi again, Hello!

I somehow need to build my C++
class around this C interface, the problem being I don't know how. Take for
example
the member-selection operator:

template <typename type>
type * PhysMem<type>::eek:perator -> ()
{
return ???;
}

The function above must return a pointer to some memory. The problem is,
I ideally want to use the phys_writemem or phys_readmem routine, but where
do I copy the memory to
so I can return it? I need some kind of intermediate buffer, but how do I
manage the
lifetime of this buffer?
Well, one idea: one PhysMem object should correspond to one object in your
memory. This address should be given to PhysMem constructor. Then include
an instance of the object in the PhysMem instance:

template <typename type>
class PhysMem
{
public:
// These functions can be used to modify object
type & operator [] (size_t index);
type& operator* (); // I think this should return a reference
type * operator-> ();

// For const PhysMem - non modifing functions:
const type& operator[] (size_t index) const;
const type& operator* () const;
const type* operator-> () const;

private:
type buffer; // so we have memory to copy to
};
And how do I handle a write-operation?
i.e. ptr->member1 = some_value;
That's up to you.
1. E.g. you can add a function flush() to PhysMem class, which
will write the object to the physical memory, e.g.:

PhysMem<mystruct> foo(0x123456789);
foo->member1 = 1;
foo->member2 = 2;
foo.flush(); // Write occurs here

Also add call to flush() to the PhysMem destructor.

2. Change
type* operator-> ();
to
PhysMemFlusher<type> operator-> ();
where PhysMemFlusher is

template <typename type>
class PhysMemFlusher
{
type* object;
public:
PhysMemFlusher(type* object)
: object(object)
{ }

~PhysMemFlusher()
{
// Write an object to phys_mem
}

type* operator-> ()
{
return object;
}
};

So, consider following code:
PhysMem<mystruct> foo(0x123456789);
foo->member1 = 1;

foo::eek:perator-> returns an object of class PhysMemFlusher, then
compiler applies operator-> to that object and gets type* object (that
we want to change). Than it applies operator-> to get the member you
need, assigns new value to the member. Than it destoys the PhysMemFlusher
object, thus causing to write your object to phys_mem.
I need to have control over the mystruct::eek:perator= and invoke the
Nope. you need to control operator= of mystruct members.
phys_writemem routine
when appropriate - the problem is, I have returned a general pointer in the
operator-> function
and it is too late at this stage.
I think the second solution will not require to change client code.
I hope I have explained my thoughts clearly enough for someone to
have a stab at this one.
Hope this will help you.
 
J

James Brown

Max Vasin said:
James Brown said:
Hi again, Hello!
I somehow need to build my C++
class around this C interface, the problem being I don't know how. Take
for
example
the member-selection operator:

template <typename type>
type * PhysMem<type>::eek:perator -> ()
{
return ???;
}

The function above must return a pointer to some memory. The problem is,
I ideally want to use the phys_writemem or phys_readmem routine, but
where
do I copy the memory to
so I can return it? I need some kind of intermediate buffer, but how do I
manage the
lifetime of this buffer?
Well, one idea: one PhysMem object should correspond to one object in your
memory. This address should be given to PhysMem constructor. Then include
an instance of the object in the PhysMem instance:

template <typename type>
class PhysMem
{
public:
// These functions can be used to modify object
type & operator [] (size_t index);
type& operator* (); // I think this should return a reference
type * operator-> ();

// For const PhysMem - non modifing functions:
const type& operator[] (size_t index) const;
const type& operator* () const;
const type* operator-> () const;

private:
type buffer; // so we have memory to copy to
};
And how do I handle a write-operation?
i.e. ptr->member1 = some_value;
That's up to you.
1. E.g. you can add a function flush() to PhysMem class, which
will write the object to the physical memory, e.g.:

PhysMem<mystruct> foo(0x123456789);
foo->member1 = 1;
foo->member2 = 2;
foo.flush(); // Write occurs here

Also add call to flush() to the PhysMem destructor.

2. Change
type* operator-> ();
to
PhysMemFlusher<type> operator-> ();
where PhysMemFlusher is

template <typename type>
class PhysMemFlusher
{
type* object;
public:
PhysMemFlusher(type* object)
: object(object)
{ }

~PhysMemFlusher()
{
// Write an object to phys_mem
}

type* operator-> ()
{
return object;
}
};

So, consider following code:
PhysMem<mystruct> foo(0x123456789);
foo->member1 = 1;

foo::eek:perator-> returns an object of class PhysMemFlusher, then
compiler applies operator-> to that object and gets type* object (that
we want to change). Than it applies operator-> to get the member you
need, assigns new value to the member. Than it destoys the PhysMemFlusher
object, thus causing to write your object to phys_mem.
I need to have control over the mystruct::eek:perator= and invoke the
Nope. you need to control operator= of mystruct members.
phys_writemem routine
when appropriate - the problem is, I have returned a general pointer in
the
operator-> function
and it is too late at this stage.
I think the second solution will not require to change client code.
I hope I have explained my thoughts clearly enough for someone to
have a stab at this one.
Hope this will help you.

Hi Max,
Yes your suggestions are certainly helpful to me, I'm still trying to digest
what you
have detailed but it seems a good way forward for me now, I'll let the group
know how I get on.

thanks,
James
 

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,755
Messages
2,569,536
Members
45,008
Latest member
HaroldDark

Latest Threads

Top