Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Is this standard c++...

Reply
Thread Tools

Is this standard c++...

 
 
Chris Thomasson
Guest
Posts: n/a
 
      02-27-2007
I am thinking about using this technique for all the "local" memory pools in
a paticular multi-threaded allocator algorithm I invented. Some more info on
that can be found here:

http://groups.google.com/group/comp....c40d42a04ee855

Anyway, here is the code snippet:

#include <cstdio>
#include <cstddef>
#include <new>


template<size_t T_sz>
class lmem {
unsigned char m_buf[T_sz];
public:
void* loadptr() {
return m_buf;
}
};


class foo {
public:
foo() { printf("(%p)foo::~foo()", (void*)this); }
~foo() { printf("(%p)foo::~foo()", (void*)this); }
};


int main(void) {
foo *f;
lmem<sizeof(*f)> foomem;
f = new (foomem.loadptr()) foo;
f->~foo();
return 0;
}



 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      02-27-2007
Chris Thomasson wrote:
> I am thinking about using this technique for all the "local" memory
> pools in a paticular multi-threaded allocator algorithm I invented.
> Some more info on that can be found here:
>
> http://groups.google.com/group/comp....c40d42a04ee855
>
> Anyway, here is the code snippet:
>
> #include <cstdio>
> #include <cstddef>
> #include <new>
>
>
> template<size_t T_sz>
> class lmem {
> unsigned char m_buf[T_sz];
> public:
> void* loadptr() {
> return m_buf;
> }
> };
>
>
> class foo {
> public:
> foo() { printf("(%p)foo::~foo()", (void*)this); }


The string seems to be incorrect.

> ~foo() { printf("(%p)foo::~foo()", (void*)this); }
> };
>
>
> int main(void) {
> foo *f;
> lmem<sizeof(*f)> foomem;
> f = new (foomem.loadptr()) foo;


It's not "incorrect", but I believe you may have a problem
with alignment. Only a memory block sized 'sizeof(foo)'
obtained from free store is aligned correctly to have a 'foo'
constructed in it like that.

> f->~foo();
> return 0;
> }


V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      02-27-2007
Chris Thomasson wrote:
> I am thinking about using this technique for all the "local" memory pools in
> a paticular multi-threaded allocator algorithm I invented. Some more info on
> that can be found here:
>
> http://groups.google.com/group/comp....c40d42a04ee855
>
> Anyway, here is the code snippet:
>
> #include <cstdio>
> #include <cstddef>
> #include <new>
>
>
> template<size_t T_sz>
> class lmem {
> unsigned char m_buf[T_sz];


You may run into alignment problems by using an array of unsigned char,
you should follow the same system specific alignment rules as malloc.

> public:
> void* loadptr() {
> return m_buf;
> }
> };
>
>
> class foo {
> public:
> foo() { printf("(%p)foo::~foo()", (void*)this); }
> ~foo() { printf("(%p)foo::~foo()", (void*)this); }
> };
>

C++ purists avoid printf. Never mix it with iostreams.
>
> int main(void) {


Just int main() is the norm in C++.

--
Ian Collins.
 
Reply With Quote
 
Default User
Guest
Posts: n/a
 
      02-28-2007
Ian Collins wrote:


> C++ purists avoid printf. Never mix it with iostreams.


Bah. Pointlessly dogmatic. Sometimes it's the right thing.




Brian
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      02-28-2007
Default User wrote:
> Ian Collins wrote:
>
>>C++ purists avoid printf. Never mix it with iostreams.

>
> Bah. Pointlessly dogmatic. Sometimes it's the right thing.
>

Care to cite an example?

--
Ian Collins.
 
Reply With Quote
 
kwikius
Guest
Posts: n/a
 
      02-28-2007
On 27 Feb, 22:59, "Victor Bazarov" <(E-Mail Removed)> wrote:
> Chris Thomasson wrote:
> > I am thinking about using this technique for all the "local" memory
> > pools in a paticular multi-threaded allocator algorithm I invented.
> > Some more info on that can be found here:

>
> >http://groups.google.com/group/comp....ead/24c40d42a0...

>
> > Anyway, here is the code snippet:

>
> > #include <cstdio>
> > #include <cstddef>
> > #include <new>

>
> > template<size_t T_sz>
> > class lmem {
> > unsigned char m_buf[T_sz];
> > public:
> > void* loadptr() {
> > return m_buf;
> > }
> > };

>
> > class foo {
> > public:
> > foo() { printf("(%p)foo::~foo()", (void*)this); }

>
> The string seems to be incorrect.
>
> > ~foo() { printf("(%p)foo::~foo()", (void*)this); }
> > };

>
> > int main(void) {
> > foo *f;
> > lmem<sizeof(*f)> foomem;
> > f = new (foomem.loadptr()) foo;

>
> It's not "incorrect", but I believe you may have a problem
> with alignment. Only a memory block sized 'sizeof(foo)'
> obtained from free store is aligned correctly to have a 'foo'
> constructed in it like that.
>


IMO, because the array is wrapped in a class there shouldnt be a
problem. IOW thc class alignment will take care of the issue. However
It should be possible to check . (Not absolutely sure if this is the
correct solution but whatever ...

regards
Andy Little

#include <stdexcept>

// aka std::tr1::
template <typename T>
struct alignment_of{
#if defined _MSC_VER
static const unsigned int value = __alignof(T);
#elif defined __GNUC__
static const unsigned int value = __alignof__(T);
#else
#error need to define system dependent align_of
#endif
};


template<typename T, size_t T_sz>
class lmem {

unsigned char m_buf[T_sz];
public:
void* loadptr() {
// check its aligned correctly
ptrdiff_t dummy = m_buf - static_cast<char*>(0);
ptrdiff_t offset = dummy % alignment_of<T>::value;
if(!offset)
return m_buf;
throw std::logic_error("lmem memory doesnt satisfy alignment");
}
};


int main()
{
typedef double type;
lmem<type,sizeof(type)> x;
}

 
Reply With Quote
 
kwikius
Guest
Posts: n/a
 
      02-28-2007
On 28 Feb, 01:25, "kwikius" <(E-Mail Removed)> wrote:

> IMO, because the array is wrapped in a class there shouldnt be a
> problem. IOW thc class alignment will take care of the issue.


Well I was wrong about that :.
(Back to the drawing board I guess)

But at least the code seems to detect the problem :

#include <stdexcept>

// aka std::tr1::
template <typename T>
struct alignment_of{
#if defined _MSC_VER
static const unsigned int value = __alignof (T);
#elif defined __GNUC__
static const unsigned int value = __alignof__(T);
#else
#error need to define system dependent align_of
#endif
};


template<typename T, size_t T_sz>
class lmem {

unsigned char m_buf[T_sz];
public:
void* loadptr() {
// check its aligned correctly
ptrdiff_t dummy = m_buf - static_cast<unsigned char*>(0);
ptrdiff_t offset = dummy % alignment_of<T>::value;
if(!offset)
return m_buf;
throw std::logic_error("lmem memory doesnt staisfy alignment");
}
};

#include <iostream>
int main()
{
try{
typedef double type;
char c;
lmem<type,sizeof(type)> x;
void * p = x.loadptr() ;
}
catch(std::exception & e)
{
std::cout << e.what() <<'\n';
}
}
/* output:
lmem memory doesnt staisfy alignment

*/
regards
Andy Little

 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      02-28-2007
kwikius wrote:
>
> IMO, because the array is wrapped in a class there shouldnt be a
> problem. IOW thc class alignment will take care of the issue. However
> It should be possible to check . (Not absolutely sure if this is the
> correct solution but whatever ...
>

No, the class may be aligned according to the alignment requirements of
its members, in this case unsigned char.

--
Ian Collins.
 
Reply With Quote
 
kwikius
Guest
Posts: n/a
 
      02-28-2007
On 28 Feb, 02:47, Ian Collins <(E-Mail Removed)> wrote:
> kwikius wrote:
>
> > IMO, because the array is wrapped in a class there shouldnt be a
> > problem. IOW thc class alignment will take care of the issue. However
> > It should be possible to check . (Not absolutely sure if this is the
> > correct solution but whatever ...

>
> No, the class may be aligned according to the alignment requirements of
> its members, in this case unsigned char.


Yep. I figured it out eventaully I think.
It seems to be possible but at the expense of always allocating your
char array oversize by alignment_of<T> -1. Its not possible to know
where on the stack the lmem object will go.

Anyway the following seems to work :


template<typename T, size_t T_sz>
class lmem {
// Don't think there is a way to avoid
// allocating extra stack space ...
unsigned char m_buf[T_sz + alignment_of<T>::value -1];
public:
void* loadptr() {
// align memory to T
ptrdiff_t dummy = m_buf - static_cast<unsigned char*>(0);
ptrdiff_t offset = dummy % alignment_of<T>::value;
ptrdiff_t result = offset == 0
? dummy
: dummy + alignment_of<T>::value - offset;
// check this works
assert( result % alignment_of<T>::value == 0);
return static_cast<unsigned char*>(0) + result;
}
};

struct my{
int x, y;
double z;
my(int xx, int yy, double zz): x(xx),y(yy),z(zz){}
};

#include <iostream>
int main()
{

// muck about with stack offsets
char c = '\n';
short n = 1;
lmem<double,sizeof(double)> x;
double * pd = new (x.loadptr()) double(1234.56789);
std::cout << *pd <<'\n';

lmem<my, sizeof(my)> y;
my * pc = new (y.loadptr()) my(1,2,3);

std::cout << pc->x << ' ' << pc->y << ' ' << pc->z <<'\n';

}

regards
Andy Little


>
> --
> Ian Collins.



 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      02-28-2007
kwikius wrote:
> On 28 Feb, 02:47, Ian Collins <(E-Mail Removed)> wrote:
>
>>kwikius wrote:
>>
>>
>>>IMO, because the array is wrapped in a class there shouldnt be a
>>>problem. IOW thc class alignment will take care of the issue. However
>>>It should be possible to check . (Not absolutely sure if this is the
>>>correct solution but whatever ...

>>
>>No, the class may be aligned according to the alignment requirements of
>>its members, in this case unsigned char.

>
>
> Yep. I figured it out eventaully I think.
> It seems to be possible but at the expense of always allocating your
> char array oversize by alignment_of<T> -1. Its not possible to know
> where on the stack the lmem object will go.
>
> Anyway the following seems to work :
>
>
> template<typename T, size_t T_sz>
> class lmem {
> // Don't think there is a way to avoid
> // allocating extra stack space ...
> unsigned char m_buf[T_sz + alignment_of<T>::value -1];
> public:
> void* loadptr() {
> // align memory to T
> ptrdiff_t dummy = m_buf - static_cast<unsigned char*>(0);
> ptrdiff_t offset = dummy % alignment_of<T>::value;
> ptrdiff_t result = offset == 0
> ? dummy
> : dummy + alignment_of<T>::value - offset;
> // check this works
> assert( result % alignment_of<T>::value == 0);
> return static_cast<unsigned char*>(0) + result;
> }
> };
>

Or even:

template <typename T>
class lmem {
T t;
public:
void* loadptr() {
return &t;
}
};


--
Ian Collins.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
standard libraries don't behave like standard 'libraries' Sriram Srinivasan Python 13 11-12-2009 06:05 PM
What are the standard network functions provided in standard C? disappearedng@gmail.com C Programming 5 06-10-2008 08:57 PM
How to redirect a "system" standard output and standard error to avariable (Linux) Venks Ruby 5 12-06-2007 12:21 AM
add pexpect to the standard library, standard "install" mechanism. funkyj Python 5 01-20-2006 08:35 PM
How standard is the standard library? steve.leach Python 1 04-18-2005 04:07 PM



Advertisments