Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Method that only one other class type may access

Reply
Thread Tools

Method that only one other class type may access

 
 
Ian Collins
Guest
Posts: n/a
 
      10-04-2011
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
 
Reply With Quote
 
 
 
 
Christopher
Guest
Posts: n/a
 
      10-04-2011
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 looksto
> >> 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.

















 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      10-04-2011
On 10/ 5/11 10:21 AM, Christopher wrote:
>
> 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.


Just use the native interface. On one of my projects we had a long
discussion about this topic and that was our conclusion: KISS!

--
Ian Collins
 
Reply With Quote
 
Werner
Guest
Posts: n/a
 
      10-05-2011
On Oct 1, 10:32*pm, Christopher <cp...@austin.rr.com> 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?


This is how I did it:


TcpSvrConnectionListener:

void subscribeForConnections( IfToSvr& ifToSvr );
void unsubscribeForConnections( IfToSvr& ifToSvr );

IfToSvr was nested...
class TcpSvrConnectionListener::IfToSvr
{
public:
virtual void connectedEvt( SOCKET acceptDescriptor ) = 0;
unsigned getPortNum() const{ return portNum_; }
const std::string& getIpAddr() const { return ipAddr_; }

protected: //Operations
//Derivitives to specify the port number
IfToSvr(): portNum_( 0 ), ipAddr_( "" ){ }
IfToSvr( unsigned portNum, const std::string& ipAddr )
: portNum_( portNum ), ipAddr_( ipAddr )
{
}

//won't be deleted through this interface
virtual ~IfToSvr(){}
void setPortNum( unsigned portNum ){ portNum_ = portNum; }
void setIpAddr( const std::string& ipAddr ){ ipAddr_ = ipAddr; }

private:
unsigned portNum_;
std::string ipAddr_;
};

TcpSvrConnectionListener ran in it's own thread (listening),
and subscription routines had to be synchronized, as well
as connectedEvt...

The server itself, well, it just needs to implement the
interface and subscribe. Turned out that I separated
the actual server from connections. The server was, on
connectedEvt, responsible for realizing the actual
connection. The server then used the subject observer
pattern to dispatch the connection to all sockets
interested. The first socket accepting the connection
would take ownership of it, and on it being accepted,
the server would relinquish ownership of the connection.

Connections not accepted within a certain amount of time
was destroyed.

All reading was done by a service class (similar
to what boost does) that monitors for data in a
single thread and dispatches data to the applicable
registrant associated with the socket on which the data
was received (also via interface, the TcpSvrConnection
deriving from it...).

Contrary to what Ian Collins says, in my opinion especially
using blocking sockets complicate user code. KISS, but not
at the expense of usage. I haven't looked at boost sockets
much yet, but I've looked at their usage of IO Completion
Ports, and I like the idea of having a "service" responsible
for listening and connecting(for clients), a "service"
responsible for reading, as not having such a service
complicates user code IMHO. Obviously the service class
will be more complicated, but it has a well defined
responsibility and usage is simple, if not opaque.

You (as user) just create a server, associate a socket. Hookup the
appropriate callbacks to receive data (sending is synchronous), and
wholla. In our implementation, the service class has to exist
prior to this, but enabling of the service classes are done
from a central location. One could instantiate the service classes
when needed. We kept that part simple and opted for explicit
creation upfront.

We've created interfaces to break dependencies and to communicate
responsibilities of classes in terms of each other.

Good luck ,

Kind regards,

Werner





































 
Reply With Quote
 
Jorgen Grahn
Guest
Posts: n/a
 
      10-05-2011
On Tue, 2011-10-04, Ian Collins wrote:
> On 10/ 5/11 10:21 AM, Christopher wrote:
>>
>> 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.

>
> Just use the native interface. On one of my projects we had a long
> discussion about this topic and that was our conclusion: KISS!


I'm repeating myself, but an anecdote:

A few years back I decided to write The One True C++ Wrapper For BSD
Sockets. I wanted type safety: distinct types for UDP sockets, TCP
listening sockets, "normal" TCP sockets ... with the type system
preventing mistakes such as doing listen() on an UDP socket or setting
UDP-specific socket options on a TCP socket. But at the same time I
didn't want to invent a brand new interface to learn.

After a while I realized that (a) this was hard work and (b) it was
for the most part not useful work. Any half-decent design in your
application makes most of the mistakes I wanted to eliminate
- unlikely to happen, because you tend to keep different kinds of
sockets apart
- likely to be found quickly if they /did/ happen

So I threw most of it away. I just kept some read/write buffering code
which had proven useful in real life.

(Disclaimer: I have no experience with Boost.asio; perhaps it forces you
in another direction.)

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      10-05-2011
On 10/ 5/11 09:19 PM, Jorgen Grahn wrote:
> On Tue, 2011-10-04, Ian Collins wrote:
>>
>> Just use the native interface. On one of my projects we had a long
>> discussion about this topic and that was our conclusion: KISS!

>
> I'm repeating myself, but an anecdote:
>
> A few years back I decided to write The One True C++ Wrapper For BSD
> Sockets. I wanted type safety: distinct types for UDP sockets, TCP
> listening sockets, "normal" TCP sockets ... with the type system
> preventing mistakes such as doing listen() on an UDP socket or setting
> UDP-specific socket options on a TCP socket. But at the same time I
> didn't want to invent a brand new interface to learn.
>
> After a while I realized that (a) this was hard work and (b) it was
> for the most part not useful work. Any half-decent design in your
> application makes most of the mistakes I wanted to eliminate
> - unlikely to happen, because you tend to keep different kinds of
> sockets apart
> - likely to be found quickly if they /did/ happen
>
> So I threw most of it away. I just kept some read/write buffering code
> which had proven useful in real life.


At least you had the good sense to give up after only one attempt. I
had three goes, over 15 years before realising the error of my ways.

> (Disclaimer: I have no experience with Boost.asio; perhaps it forces you
> in another direction.)


I've only ever seen it end in tears.

--
Ian Collins
 
Reply With Quote
 
Miles Bader
Guest
Posts: n/a
 
      10-05-2011
Ian Collins <ian-> writes:
>> So I threw most of it away. I just kept some read/write buffering code
>> which had proven useful in real life.

>
> At least you had the good sense to give up after only one attempt. I
> had three goes, over 15 years before realising the error of my ways.


Ah well, such things tend to be a learning experience, at least ...

-miles

--
"Whatever you do will be insignificant, but it is very important that
you do it." Mahatma Gandhi
 
Reply With Quote
 
Jorgen Grahn
Guest
Posts: n/a
 
      10-05-2011
On Wed, 2011-10-05, Ian Collins wrote:
> On 10/ 5/11 09:19 PM, Jorgen Grahn wrote:

....
>> So I threw most of it away. I just kept some read/write buffering code
>> which had proven useful in real life.

>
> At least you had the good sense to give up after only one attempt. I
> had three goes, over 15 years before realising the error of my ways.


Well, ask me again 15 years from now

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
 
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
problem in running a basic code in python 3.3.0 that includes HTML file Satabdi Mukherjee Python 1 04-04-2013 07:48 PM
why a class can't access protected method from another class in thesame package,the method is interited from the ohtner class from differntpackage? junzhang1983@gmail.com Java 3 01-28-2008 02:09 AM
Error - Only one WebServiceBinding attribute may be specified on type Pankaj Garg ASP .Net Web Services 1 02-24-2005 05:39 AM
Re: How do I access another type's method from one type's method Howard C++ 2 07-04-2003 12:08 PM
Re: How do I access another type's method from one type's method Rolf Magnus C++ 1 07-04-2003 02:38 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57