Re: Method that only one other class type may access
On Oct 3, 9:01 pm, Ian Collins <ian-n...@hotmail.com> wrote:
On 10/ 4/11 09:49 AM, Jorgen Grahn wrote:
On Mon, 2011-10-03, Ian Collins wrote:
On 10/ 2/11 09:32 AM, Christopher wrote:
I know I need some sort of friend, but I don't want to friend the
entire class.
I've got a TcpConnection class and it has a state member.
I've got a TcpListener class that accepts connections and creates a
TcpConnectionClass.
The TcpListener class needs to be able to change the state member of
the TcpConnection class, but I don't want anyone else to be able to.
How do I go about that?
If a design doesn't fit the problem, the design is flawed. It looks=
to
me like you are over engineering what is a very simple (and common)
task. Don't fret though, I see this all the time! Socket related
activities simply don't fit well within an OO approach.
It is not clear to me what you mean with that last sentence, but I was
going to say something similar:
Trying to use things like connection and listener classes!
I see no great benefits of wrapping the BSD socket API in lots of stuff=
..
If you wrap them a bit to get:
- file descriptors which aren't convertible to and from ints
- RAII
then the API is pretty usable as it is. Bonus: anyone who knows the
API doesn't have to relearn another one.
Agreed.
--
Ian Collins- Hide quoted text -
- Show quoted text -
Yes, I am coming to realize the sockets just don't fit OO.
The concept that a listener creates an accepted connection, but the
accepted connection does the communicating is a pain in my butt.
I've done many socket implementations before and didn't have such a
problem with this, the added restrictions of how boost::asio::ip::tcp
works is really adding headaches.
Any operation gets posted for completion and calls back a given method
when it completes. that is enforced by boost::asio::ip::tcp
asynchronous calls.
Well Ok, so the listener gets notified when an accept has occured.
boo.
Now the state of the new connection needs to change and do the things
it does when it gets connected!
So, either
1) The listener has to tell the accepted connection, "you are alive
now" or
2) We change the callback to the connection itself, who has to tell
the listener, "Hey, I'm alive now, do stuff with me or hand me off to
someone"
Either way there is a circular dependancy.
----
Forward declarations to get rid of this circular dependency do not
seem to work, because of another restriction that is a side effect
from using boost::asio::ip::tcp.
I must make sure that every object in my inheritance tree that will
post an operation for io-completion, gets instantiated as a
shared_ptr, such that the object is guarenteed to stay alive between
the times of posting an operation and the time it completes.
So, when it comes into the code:
class Listener;
Connection::Accepted(/*stuff*/)
{
// Snip
listenerPtr->OnAccepted(shared_from_this());
}
The compiler has to see the declaration of Listener::OnAccepted, the
Listener::SmartPtr, etc.
----------
So what I've decided to do....and I hate doing it...it deriving a
ServerSideConnection class that has the accept, onaccept methods, etc.
and takes, upon its construction, a whole bunch of boost::functions
that can be called back. Then when the connection gets notified of
something, it in turn notifies the listener...This is ugly because
I've got callback everywhere, its debugging hell, and I've got quite a
number of connection implementations that do nothing but get notified
and notify the listener...yuck!
I don't see a way around it.
---------
I suppose when I get time, I'll try and write up a visible and
simplified example explaining my problems on my website and then point
people to it for comment. It might just be too big and complex of a
thing...and off topic...to get into the details here.