Subject: Re: [boost] Formal Review Request: TypeErasure
From: Hite, Christopher (Christopher.Hite_at_[hidden])
Date: 2012-06-20 12:03:33


 Dave Abrahams wrote:
> > "Deferred Callable Object"
> > http://www.boost.org/doc/libs/1_49_0/libs/fusion/doc/html/fusion/functional/concepts/def_callable.html
> Sorry, I don't follow any of this. When you say "functors," what do you mean?
You're the boost guy; I think the ontology in fusion is more than enough.

Perhaps it's abuse of the term, but I use "functor" to mean callable, usually copyable object (including function pointer).

> That word has a formal meaning in computer science that is probably not what you mean, and an informal meaning in C++ (just another word for "function object") that doesn't /seem/ to be what you mean.
http://en.wikipedia.org/wiki/Functor
        "For functors as a synonym of 'function objects'"

 I think we're talking about the same thing. Would you perfer I use "function object"?

>> > Consider this big monster object with this interface. It's not
>> > movable/copyable (maybe it has its own threads).
>> > I think you'd find something like this acceptable.
>> >
>> > struct monster : noncopyable{
>> > typedef signal<void ()>::slot_type slot;
>> >
>> > connection subscribeA(slot);
>> > connection subscribeB(slot);
>> > connection subscribeC(slot);
>> > ...
>> > };

> > It's got threads, io_service, mutexes, signal2, containers, sockets,
> > etc inside it that don't like being moved/copied and don't need to be.
> > What would you do Dave?

> I wouldn't write a monster in the first place.
You believe in OOP encapsulation (separation of problems), right? I think if you had this kind of problem, you'd also try to hide the details behind some minimal interface. I can understand you proposing a better interface.

I can't imagine you saying "C++ programmers shouldn't do network programming".

So imagine a good C++ programmer like has yucky details to encapsulate:
* networking protocol
* TCP sockets - to multiple servers
* UDP/multicast sockets - which should join/leave when needed
* containers for subscriptions - say B's have ids
* unsubscribe - optionally lazy
* threads - single or pool of threads

All the users care about is subscribing and getting updates. What should the interface look like? Was I that far off? Did I try to hide too much?

> Would you prefer to put all of monster's guts in a shared_ptr-ed
> pimple so monster can be copied?
>
> This is an honest question. I may be a couple steps behind on best
> practices of C++. I'd probably give the user of monster an object he
> can't move/copy. Is that generally bad? Do you think all objects be
> copy/movable?

> I think it's 99.9% reasonable to make all objects movable, and maybe 75% reasonable to make all objects copyable. You can do either or both of these, the difference is a matter of degree: just how uncompromising do you have to be to build a world that makes sense?
A good candidate for the 25% is any object that is supposed to represent and external resource. Example: a TCP session with some other process. It makes sense to have a non-copyable object which exclusively owns that session whose deconstructor logs out and disconnects. You can copy the fd. You could connect a second time. You probably can not tell the server on the other side to copy all the state from associated with one session to another.

Here's the 0.1% case I tend to have, but maybe you think it's bad form. If an object has members which are needed for synchronization with a private thread, it can't be moved. Say I've got an class that has a private member mutex and thread it uses. I can't safely just move the mutex. A move constructor would have to
* tell the worker thread to go park itself and wait for instructions from some temporary synchronization object
* wait until it's parked
* move the inards of my object including mutexes
* tell the thread to continue using the new location
That seems hard and error prone. So I'd never implement it unless there was a need.

It might be done easliy by smart_ptr<> pimple but that costs something too. It's also something a user of an object can do. Let the user decide how ownership should work. Anyway such a pimple type though private would still be a 0.1% type.

Here's a nice example: boost::asio::io_service isn't movable. Should it be?

I wouldn't call asio legacy code. To me it appears to be the latest style of interface.

Chris