Boost logo

Boost :

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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk