
Hi, Firstly after defining my own sh::pool allocator new doors opened on their own and now I am able to replace the "new_sh<>()" function call with a much more neat C++ approach with "new shifted<>()". For example instead of: shifted_ptr<char[9]> u = new_sh<char[9]>(); Now we can write: shifted_ptr<char[9]> u = new shifted<char[9]>(); This will allows us defining STL container allocators more easily because of the distinct steps the constructor and allocator are called; new_sh<>() was mixing them altogether. Secondly I was able to drastically clean up "class shifted<>" (was: owned<>) by unifying the construction of the member object with the construction of the class itself. This was necessary to use "new shifted<>()" adequately. Last but not least the library now takes advantage of the fast_pool_allocator for objects such as "struct set" and "numeric::interval<int>". FYI I am using "numeric::interval<int>" instead of "numeric::interval<void *>" because of a compilation failure with the latter. I am casting the pointers to an "int" meanwhile because there is no lost of information by doing so according to the standards. The files are both on Vault and the Sandbox and is nearly the official release. Documentation will follow soon for those who got no clue what I'm talking about: http://www.boost-consulting.com/vault/index.php?action=downloadfile&filename=shifted_ptr.zip&directory=Memory Thanks, -Phil

Last but not least the library now takes advantage of the fast_pool_allocator for objects such as "struct set" and "numeric::interval<int>". FYI I am using "numeric::interval<int>" instead of "numeric::interval<void *>" because of a compilation failure with
Phil wrote: the
latter. I am casting the pointers to an "int" meanwhile because there is >no lost of information by doing so according to the standards.
Pointers are certainly not guaranteed to be the same width as int by the standard. The standard doesn't get to say anything about the size of the built-in types, which may differ by hardware and compiler flags. void * p = ordered_malloc(s); get()->push_back(numeric::interval<int>((int) p, int((char *)(p) + s))); There are many platforms in which int is not the same number of bytes as a pointer. Most commonly such casts will cause code to fail to port to 64 bit platforms. Perhaps we can figure out how to overcome the compile error that caused you to add the cast, or figure out something you can cast the pointer to that will portably result in no loss of data, such as perhaps size_t. Luke

Last but not least the library now takes advantage of the fast_pool_allocator for objects such as "struct set" and "numeric::interval<int>". FYI I am using "numeric::interval<int>" instead of "numeric::interval<void *>" because of a compilation failure with
Phil wrote: the
latter. I am casting the pointers to an "int" meanwhile because there is >no lost of information by doing so according to the standards.
void * p = ordered_malloc(s); get()->push_back(numeric::interval<int>((int) p, int((char *)(p) + s))); I forgot to mention that casting the pointer to signed integer will cause problems even if they happen to be the same bit width. This is because pointer values with a 1 in the msb will cast to negative integer values, which will cause the order of p and p+s to become inverted, leading to an error condition in numeric::interval, which will result in a null interval, according to interval's documentation. That would be difficult to debug. Luke

"Simonson, Lucanus J" <lucanus.j.simonson@intel.com> wrote in message news:33E1C72C74DBE747B7B59C1740F7443703593075@orsmsx417.amr.corp.intel.com... [...]
I forgot to mention that casting the pointer to signed integer will cause problems even if they happen to be the same bit width. This is because pointer values with a 1 in the msb will cast to negative integer values, which will cause the order of p and p+s to become inverted, leading to an error condition in numeric::interval, which will result in a null interval, according to interval's documentation. That would be difficult to debug.
Like previously mentionned that cast is simply a temporary solution but hopefully void * types will be easy to integrate into interval<>. I will also change int for unsigned until void * works. -Phil

I am not following this thread but when I hear of things like boost::numeric::interval<void *>, I have to wonder: what is it you are trying to do? Interval is a *numeric* type, intended for *computation* (i.e., operator+,-,*,/). It is not really intended for integral types, and certainly not for pointer types. If you want an interval of void*, maybe you should consider std::complex<void*> (just kidding, but you can actually see the parallel), or more likely std::pair<void*>. -- Hervé Brönnimann hervebronnimann@mac.com On Jun 6, 2008, at 4:14 AM, Phil Bouchard wrote:
"Simonson, Lucanus J" <lucanus.j.simonson@intel.com> wrote in message news: 33E1C72C74DBE747B7B59C1740F7443703593075@orsmsx417.amr.corp.intel.com. ..
[...]
I forgot to mention that casting the pointer to signed integer will cause problems even if they happen to be the same bit width. This is because pointer values with a 1 in the msb will cast to negative integer values, which will cause the order of p and p+s to become inverted, leading to an error condition in numeric::interval, which will result in a null interval, according to interval's documentation. That would be difficult to debug.
Like previously mentionned that cast is simply a temporary solution but hopefully void * types will be easy to integrate into interval<>. I will also change int for unsigned until void * works.
-Phil
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/ listinfo.cgi/boost

"Hervé Brönnimann" <hervebronnimann@mac.com> wrote in message news:AA37BF5C-9007-45AC-92DC-4790A699F610@mac.com... I am not following this thread but when I hear of things like boost::numeric::interval<void *>, I have to wonder: what is it you are trying to do? Interval is a *numeric* type, intended for *computation* (i.e., operator+,-,*,/). It is not really intended for integral types, and certainly not for pointer types. If you want an
[...] I think it's more of a usability issue here because "interval" is a very generic term and we all know what it is supposed to do without reading its introduction. If the required changes become too much of an issue then let's forget about it but up to now the only required change would be to substitute a static_cast<>() of a constant integer to a constructor followed by an addition: Problem: .../include/boost/numeric/interval/checking.hpp:62: error: invalid static_cast from type `int' to type `void*' static T empty_lower() { return (std::numeric_limits<T>::has_quiet_NaN ? std::numeric_limits<T>::quiet_NaN() : static_cast<T>(1)); } Solution: static T empty_lower() { return (std::numeric_limits<T>::has_quiet_NaN ? std::numeric_limits<T>::quiet_NaN() : T(0) + 1); } I was hoping using interval<void *> to trace what block of memory the construction of an object is being made on but it can easily be used to unify a block of memory with a pool or memory segment for example. Thanks, -Phil

Hervé suggested:
std::pair<void *>
Phil replied:
I was hoping using interval<void *> to trace what block of memory the construction of an object is being made on but it can easily be used to unify a block of memory with a pool or memory segment for example.
I agree with Hervé, I wouldn't have thought to use numeric::interval for your use case because I wouldn't expect you are using enough of what that library provides to justify the dependency. std::pair<void *> and a predicate contains(pair1, pair2) would be fine. You could even store your std::pair<void *> in a std::set and look up which block a given std::pair<void *> was contained in quite conveniently using std::set::lower_bound and the less than operator of std::pair as the comparator on std::set. Similarly, I wouldn't suggest that you use my gtl interval concept with a gtl::interval_data<void *> either because I don't think the benefit you might get out weighs the cost of a dependency. Luke

Inclusion of interval headers aren't necessary dependencies in my case and would create compilation overhead, ... agreed. Thanks anyways. Regards, -Phil

"Simonson, Lucanus J" <lucanus.j.simonson@intel.com> wrote in message news:33E1C72C74DBE747B7B59C1740F7443703592F5F@orsmsx417.amr.corp.intel.com... [...]
Perhaps we can figure out how to overcome the compile error that caused you to add the cast, or figure out something you can cast the pointer to that will portably result in no loss of data, such as perhaps size_t.
Agreed. The int cast is a quick fix to make everything work; there is no intent of keeping it the way it is ;) Here is the following sample compiled using GCC for Windows: #include <list> #include <boost/numeric/interval.hpp> using namespace std; using namespace boost::numeric; int main() { list< interval<void *> > seg; seg.push_back(interval<void *>((void *)(10), (void *)(11))); } Y:/UNIX/local/bin/../lib/gcc/mingw32/3.4.5/../../../../include/boost/numeric/interval/checking.hpp: In static member function `static T boost::numeric::interval_lib::checking_base<T>::empty_lower() [with T = void*]': Y:/UNIX/local/bin/../lib/gcc/mingw32/3.4.5/../../../../include/boost/numeric/interval/checking.hpp:88: instantiated from `static T boost::numeric::interval_lib::checking_no_empty<T, Checking, Exception>::empty_lower() [with T = void*, Checking = boost::numeric::interval_lib::checking_base<void*>, Exception = boost::numeric::interval_lib::exception_create_empty]' Y:/UNIX/local/bin/../lib/gcc/mingw32/3.4.5/../../../../include/boost/numeric/interval/interval.hpp:269: instantiated from `void boost::numeric::interval<T, Policies>::set_empty() [with T = void*, Policies = boost::numeric::interval_lib::policies<boost::numeric::interval_lib::rounded_math<void*>, boost::numeric::interval_lib::checking_strict<void*> >]' Y:/UNIX/local/bin/../lib/gcc/mingw32/3.4.5/../../../../include/boost/numeric/interval/interval.hpp:171: instantiated from `boost::numeric::interval<T, Policies>::interval(const T&, const T&) [with T = void*, Policies = boost::numeric::interval_lib::policies<boost::numeric::interval_lib::rounded_math<void*>, boost::numeric::interval_lib::checking_strict<void*> >]' interval2.cpp:11: instantiated from here Y:/UNIX/local/bin/../lib/gcc/mingw32/3.4.5/../../../../include/boost/numeric/interval/checking.hpp:62: error: invalid static_cast from type `int' to type `void*' -Phil

Phil Bouchard wrote:
Y:/UNIX/local/bin/../lib/gcc/mingw32/3.4.5/ ../../../../include/boost/numeric>/interval/checking.hpp:62: error: invalid static_cast from type `int' to type `void*'
This is line 62 of checking.hpp: std::numeric_limits<T>::quiet_NaN() : static_cast<T>(1)); It looks like we are casting a constant integer to void*, which it doesn't like. Obviously we could force the compiler to eat the line by changing static_cast to reinterpret_cast, but that isn't good. Instead of casting to an integer constant, we could construct a T from the integer constant: std::numeric_limits<T>::quiet_NaN() : T(1)); , which seems like a reasonable thing to do. I don't know why they use static_cast instead, but there must have been a reason. It looks like there are numerous places in interval that need to be modified where constants are being static_cast to T that prevent it from compiling for intervals of pointer type. I think intervals of pointer type make a lot of sense. In fact, it moves us in the direction of intervals of random access iterators, which is sort of intriguing. I guess its up to you to make the case for a code change in interval to accommodate your use case. Luke

"Simonson, Lucanus J" <lucanus.j.simonson@intel.com> wrote in message news:33E1C72C74DBE747B7B59C1740F74437035DF242@orsmsx417.amr.corp.intel.com... [...]
It looks like we are casting a constant integer to void*, which it doesn't like. Obviously we could force the compiler to eat the line by changing static_cast to reinterpret_cast, but that isn't good.
Instead of casting to an integer constant, we could construct a T from the integer constant:
std::numeric_limits<T>::quiet_NaN() : T(1));
Exactly but quiet_NaN() will return false and I think there might be alignment convertions depending on the type of the pointer in the first place. It may hence be rounded down to 0 if we use an "int *" on a SPARC machine for example. If we want to have the lowest possible value of a pointer type we'll have to have something like: std::numeric_limits<T>::quiet_NaN() : T(0) + 1); -Phil

"Simonson, Lucanus J" <lucanus.j.simonson@intel.com> wrote in message news:33E1C72C74DBE747B7B59C1740F7443703592F5F@orsmsx417.amr.corp.intel.com... [...]
Pointers are certainly not guaranteed to be the same width as int by the standard. The standard doesn't get to say anything about the size of the built-in types, which may differ by hardware and compiler flags.
void * p = ordered_malloc(s); get()->push_back(numeric::interval<int>((int) p, int((char *)(p) + s)));
There are many platforms in which int is not the same number of bytes as a pointer. Most commonly such casts will cause code to fail to port to 64 bit platforms.
[...] Indeed I think I forgot to delete that sentence before posting because there is no such integral promotion of pointer types. -Phil

"Phil Bouchard" <philippe@fornux.com> wrote in message news:g292r8$12m$1@ger.gmane.org...
Hi,
Firstly after defining my own sh::pool allocator new doors opened on their own and now I am able to replace the "new_sh<>()" function call with a much more neat C++ approach with "new shifted<>()". For example instead of:
shifted_ptr<char[9]> u = new_sh<char[9]>();
Now we can write: shifted_ptr<char[9]> u = new shifted<char[9]>();
This will allows us defining STL container allocators more easily because of the distinct steps the constructor and allocator are called; new_sh<>() was mixing them altogether.
[...] Ok I just added a skeleton for a STL compliant allocator called "shifted_allocator" in "sh_owned_base_nt.hpp" of my sandbox. This is an example of how it should be written, unfortunately I wasn't able to make it compile but this is basically the final step. There are some FIXME in the header and shifted_ptr_test2.cpp file. Thanks, -Phil

"Phil Bouchard" <philippe@fornux.com> wrote in message news:g2b1pp$pir$1@ger.gmane.org...
Ok I just added a skeleton for a STL compliant allocator called "shifted_allocator" in "sh_owned_base_nt.hpp" of my sandbox. This is an example of how it should be written, unfortunately I wasn't able to make it compile but this is basically the final step. There are some FIXME in the header and shifted_ptr_test2.cpp file.
Now I added a PowerPoint presentation comparing the pointer with all other existing memory managers out there: sandbox/shifted_ptr/libs/example/doc/ShiftedPointer.ppt While writing it I came to realize the mark & sweep algorithm is deleting objects even if they are still parent of an object still being referenced from the stack. Suppose for example I got a widget having a std::string as a member. This means if the stack refers to the buffer of the string but nobody points to the widget anymore then the string buffer will be deleted and thus a segfault will occur. On the other hand one feature I really like from the garbage collector is that one might use it to silently replace all malloc() and free() from an existing C project without the need to rewrite any code. I think this is a nice feature and I would encourage people using it more in that matter. Thanks, -Phil

"Phil Bouchard" <philippe@fornux.com> wrote in message news:g2irdo$uv5$1@ger.gmane.org...
Now I added a PowerPoint presentation comparing the pointer with all other existing memory managers out there: sandbox/shifted_ptr/libs/example/doc/ShiftedPointer.ppt
Ok I just updated the doc again with a more complete version.
While writing it I came to realize the mark & sweep algorithm is deleting objects even if they are still parent of an object still being referenced from the stack. Suppose for example I got a widget having a std::string as a member. This means if the stack refers to the buffer of the string but nobody points to the widget anymore then the string buffer will be deleted and thus a segfault will occur.
[...] Sorry, this is a bad example. But imagine we have widgets piled up on each other and the last one is a popup dialog box. If the only referenced one is the popup one then all parent widget are going to be deleted if it is handled by the mark & sweep algorithm. Another example would be a this pointer being part of that parent object; no pointers from the stack are referencing it only the this pointer being cached in a register. Registers aren't handled by garbage collectors. -Phil
participants (3)
-
Hervé Brönnimann
-
Phil Bouchard
-
Simonson, Lucanus J