Date: Sat, 22 Mar 2025 12:47:49 +0000
Hi, I have been quiet because I have been busy, not because I've given up on this proposal.
The big sticking point seems to be that it is possible to write code with it that will compile and run but would not be threadsafe.
There are three approaches to deal with this:
1 As per C++ tradition. It is useful functionality, read the docs, learn the rules, don't abuse it.
2 Somehow give it the same thread safety as shared_ptr.
3 Build in detection of unsafe use.
I am beginning to think that for a Standard Library entry it has to be the first because anything else I try seems to be snookered by some form of questionable deviance or brittleness of use.
The second has to mess with either single ownership or the progress of another thread. The thread blocking idea is interesting but really it is solving a different problem.
I have been working on the third. The thread safety breaching act is to use a ptr_to_unique which references something that could be deleted by another running thread. There are two ways to stay clear of this:
1 Make sure that everything to do with the ptr_to_unique and the unique_ptr it references happens in the same thread.
2 Allow them to be acted on by multiple threads but make sure that only one can act at a time.
The best I can do is to limit it to same thread use and throw if there is any deviation from this. This is a safe and practical solution for predominantly single thread end user application development which is where I have found its use cases. You get the simple use of ptr_to_unique and any deviation from the conditions that make it safe will be detected and throw.
But rejecting controlled use by multiple threads would give ptr_to_unique a new type of brittleness of use that will infect anything that uses it. It wouldn't work with mutex protected multithread access more typical in server side code. It also wouldn't be suitable for general purpose code that doesn't know how it will be called and that is an impediment to it sitting in the Standard Library as a general purpose smart pointer.
There is a bit of a dilemma here. For it to be a first class C++type (without any funny brittleness) it has to be presented with no defence against incorrect use. Yet having that defence is practical in the single thread setting where I most anticipate it being used. Maybe it needs a template parameter that selects between the the two – but which should be the default? Or perhaps it could be a modular setting so that application level code compiles with single thread protection and server side code compiles without it.
I think I have just convinced myself that the last one is the way to go. The code that you write with ptr_to_unique has to be able to work anywhere without modification and without putting up unusual or unexpected barriers. Same thread checking could be activated in selected cpp files by a declaration that precedes the ptr_to_unique header. It doesn't change the data structure so all cpp files will find everything in the same place.
I have a feeling that is it application developers like myself that are more likely to misuse ptr_to_unique (a 'clever' trick to allow a worker thread to see something in the main thread) and might need to be protected from it. Application code can also be fast changing and subject to desperate fix-ups that may not always be fully thought out. Same thread enforcement can be used here and will keep things safe.
I can't speak for the server side managing multithread clients but I imagine that if you work there, you would know better anyway. My guess is that you would know that ptr_to_unique is a single ownership thing and rather than use it to point into the activity of other threads, you will be protecting it with a mutex. Is there anything that might tempt you to misuse it? Or even use it at all?
It still has to compile in a server setting because it might sit inside a data type being hosted and that will have to be without single thread enforcement for it to work.
Thoughts on this would be appreciated.
The big sticking point seems to be that it is possible to write code with it that will compile and run but would not be threadsafe.
There are three approaches to deal with this:
1 As per C++ tradition. It is useful functionality, read the docs, learn the rules, don't abuse it.
2 Somehow give it the same thread safety as shared_ptr.
3 Build in detection of unsafe use.
I am beginning to think that for a Standard Library entry it has to be the first because anything else I try seems to be snookered by some form of questionable deviance or brittleness of use.
The second has to mess with either single ownership or the progress of another thread. The thread blocking idea is interesting but really it is solving a different problem.
I have been working on the third. The thread safety breaching act is to use a ptr_to_unique which references something that could be deleted by another running thread. There are two ways to stay clear of this:
1 Make sure that everything to do with the ptr_to_unique and the unique_ptr it references happens in the same thread.
2 Allow them to be acted on by multiple threads but make sure that only one can act at a time.
The best I can do is to limit it to same thread use and throw if there is any deviation from this. This is a safe and practical solution for predominantly single thread end user application development which is where I have found its use cases. You get the simple use of ptr_to_unique and any deviation from the conditions that make it safe will be detected and throw.
But rejecting controlled use by multiple threads would give ptr_to_unique a new type of brittleness of use that will infect anything that uses it. It wouldn't work with mutex protected multithread access more typical in server side code. It also wouldn't be suitable for general purpose code that doesn't know how it will be called and that is an impediment to it sitting in the Standard Library as a general purpose smart pointer.
There is a bit of a dilemma here. For it to be a first class C++type (without any funny brittleness) it has to be presented with no defence against incorrect use. Yet having that defence is practical in the single thread setting where I most anticipate it being used. Maybe it needs a template parameter that selects between the the two – but which should be the default? Or perhaps it could be a modular setting so that application level code compiles with single thread protection and server side code compiles without it.
I think I have just convinced myself that the last one is the way to go. The code that you write with ptr_to_unique has to be able to work anywhere without modification and without putting up unusual or unexpected barriers. Same thread checking could be activated in selected cpp files by a declaration that precedes the ptr_to_unique header. It doesn't change the data structure so all cpp files will find everything in the same place.
I have a feeling that is it application developers like myself that are more likely to misuse ptr_to_unique (a 'clever' trick to allow a worker thread to see something in the main thread) and might need to be protected from it. Application code can also be fast changing and subject to desperate fix-ups that may not always be fully thought out. Same thread enforcement can be used here and will keep things safe.
I can't speak for the server side managing multithread clients but I imagine that if you work there, you would know better anyway. My guess is that you would know that ptr_to_unique is a single ownership thing and rather than use it to point into the activity of other threads, you will be protecting it with a mutex. Is there anything that might tempt you to misuse it? Or even use it at all?
It still has to compile in a server setting because it might sit inside a data type being hosted and that will have to be without single thread enforcement for it to work.
Thoughts on this would be appreciated.
Received on 2025-03-22 12:47:59