Maybe I should just split this into a new topic and call it "Designing my smart pointer"
Maybe I should just split this into a new topic and call it "Designing my smart pointer"
Or you could just use Boost's shared_ptr.
Coming as std::tr1::shared_ptr to a compiler near you.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
Why toss away such a huge amount of work on something so great?
Oh, and does Boost's shared_ptr allow you to do this?
I store all pointers handled by the class in a map so it will never forget the ref count, even if you strip it from the class and attach it somewhere else.Code:int main() { ppnew<int> p = 0; // Ref count == 1 int* test = p; pp<int> p2 = test; // Ref count == 2 ... }
No, it doesn't. But then, I consider this scenario quite contrived and useless. I also predict huge performance and/or correctness problems for you when you go multi-threaded.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
Not so useless when passing a raw pointer to a thread and then attaching it to a local smart pointer class.
Ah, but that's why the copy constructor in my thread affinity example didn't have a thread affinity check: because you're actually supposed to pass a (const!) reference/pointer to an existing smart pointer and create a copy there immediately, and only then signaling the creating thread that initialization is complete.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
Eh, two sides of a coin, two ways to do it, the same result. And it's more secure this way. Don't forget your pointers.
Plus it will only check if you assign or attach (although it will store a pointer every time you make a new one).
I quite disagree. I see hardly any security advantage at all. You can't ever forget your pointers if they're locked in smart pointers. And it raises the question (again!) of why you're passing around raw pointers in the first place.And it's more secure this way. Don't forget your pointers.
Also, have you considered the threading implications? Are your map accesses properly thread-safe? What's the effect of locking an application-wide mutex for every pointer destruction operation? (Especially since you seem to prefer passing the smart pointer by value to subroutines.)
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
Well... I think I can locate AMD's profiler and give it a try.
The current amount of time spent in the memory manager class (with thread safety ON) is... 0.00%!
Last edited by Elysia; 10-29-2007 at 01:10 PM.
I've never heard of someone doing that before. What it does though is decouple the pointer value from the ownership semantics of the refcounting. Sure, that enables you to pass it around as a raw pointer, but that isn't particularly safe. The whole point of a smart pointer is that you wont have the class it points to getting deleted whilst anyone has a pointer to it, and it will be deleted as soon as there is nothing pointing to it. Dangling pointers lead to very nasty bugs!
So again, just because you can do it, doesn't mean you should.
The other thing is certainly efficiency. A global map of reference counts requires locking for every refcount change. This might work okay for a few pointers being accessed by just a few threads. However it would be a killer for an app I've worked on that may have 200 threads under normal operation. It just doesn't scale well. As a minimum you'd want to use an unordered_map (hash_map), or lock-free data structures, but even then it is an awful lot of bother for something that essentially does something we don't really want it to do.
The profiling benchmark you mentioned is fairly meaningless. You could write a loop that uses your smart pointer 1000 times and then have a Sleep or GetMessage in there and you'd get the same result. In other words, it took 1/10000th the amount of time of what?
My homepage
Advice: Take only as directed - If symptoms persist, please see your debugger
Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"
Yes, it's a big hit when time critical, but then I can always add functionality to disable it.
And then you remember for which pointers you disabled this functionality at runtime and don't try this trick? I don't believe it.
I have the same opinion about your runtime decision for thread safety, by the way. It's just way too brittle.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law