
Don G wrote:
Under the address-centric model, the form of the address determines the network to use. The library is free to maintain several network objects under the hood, ...
There is the question of what network types does an application need. It is not likely they need all of them. So, the app must pre-register the types it wants and only those address forms will work.
I would prefer for a fixed set of networks (mainly ip/ipv6 to be available from start maybe lazily created on first reference). And registering a network creation function to the registry would let the registry use weak references to networks and all objects spawned from a network holds strong references in that way the network is destroyed when the last object spawned from it goes away. The network creation function could be passed along with an address so an address could be used across dll boundaries where each dll has its own registry.
For the record, I've never needed such a map. There are so few places that accept or connect, and then, so few different network objects, that it just hasn't happened. For example:
void tcp_tab_page::on_click_go () { net::address_ptr addr = tcp_->new_address(url); session_mgr->start(addr); }
The method existed in a "TCP" page of a tabbed dialog, which of course knows that connections proceed over TCP. It created an address object and called into network-agnostic code to proceed.
Wouldn't you need to store the settings and then start the applications from the stored settings and isn't the map needed then?
The "self contained address as a string" model also has another advantage: it allows you to take a legacy design such as std::fopen and enhance it with network capability in a backward-compatible way.
While I still agree with the jist of your argument, I am not so sure everyone would appreciate their apps growing by sizeof(http_lib) + sizeof(ftp_lib) + sizeof(uucp_lib) + sizeof(gopher_lib) + ... to support this approach. :)
They could be dynamically loaded.
Why I prefer tcp:/host:port instead of scheme://host? Let's get back to enhancing std::fopen in a backward- compatible way. I'd expect fopen on http://www.example.com to return the data stream obtained by the corresponding GET query, for obvious reasons.
I'm not sure I understand the difference you are drawing between ":/" and "://". The way I read the URL/I syntax, many options will work. Here is one that would be unambiguous
- ipv4:tcp:http://www.boost.org ipv4 denotes network choice; scheme-specifics follow: tcp denotes stream as opposed to datagram, and again, details follow http denotes how to talk say vs. HTTPS or FTP
- ipv4:http://www.boost.org:80 tcp can be assumed as long as protocol doesn't have udp as well (like echo or discard<g>).
I think the syntax of the address should be kept simple to use, explain and parse and having several ways of expressing the same thing in general isn't a good idea. And in that case we also would need canonicalization to be able to compare the addresses. Ie ipv4:tcp:http://www.boost.org shold be equal to ipv4:http://www.boost.org:80. But i guess they both could be canonicalized to something like tcp:/66.35.250.210:80.
I'm not sure. net::poll is specifically intended to preserve the internal structure of your library. You only need to defer dispatching the callbacks until net::poll is called (unless net::async_poll is in effect.)
I am not sure I understand your async_poll suggestion (sorry about that<g>).
As I understood it async_poll would start up a reasonable set of threads starting doing net::poll and dispatching events for the library in its own thread pool without the user having control over the pool.
I agree that net::poll() would fit with a common desire to have single threaded network programs, but might complicate things where the program is a GUI. Integrating with the GUI loop is a study in compromise (at least for Windows).
I see no reason whatso ever to have a windows gui program using the library to be single threaded. It would be easy enough to spawn a single io thread polling and handling the notifications and posting results to be processed by the gui. I have only gotten into trouble trying to integrate this kind of polling in the eventloop of a gui application and always moved to an simple thread model posting notifications to the gui thread.
I like the idea of net::poll() for some uses, but it doesn't fit what I often need (GUI integration). It does fit with select/epoll especially on platforms where the number of objects that can go in an fd_set is > 64.
There still is some arbitrary limit albeit higher isn't there. The FD_SETSIZE can be set to a large value before including winsock (althoug some lsp makes presumptions about the size).
I agree, but others don't. Some folks don't want any background threads; just a single thread doing one uber select/epoll call (again, for platforms that can handle it). The only way I can see to accommodate that is a different concrete network object. The ones I would write initially would probably not fit this desire, but again, the interface and behavior contract probably can.
I don't really get why that couldn't that be accomodated whitout another network class?
Passing NULL is good enough for async_read, but the same can't be used with async_write to choose between copy/trust-the-buffer-will-be-there semantics.
A buffer lifetime flag for the read case?
I would be happy to entertain ideas on how to provide both kinds of buffer management, especially if there is a way to eliminate as much cost as possible (in terms of "if checks" and code linkage) when automatic is never used.
I really don't see how some if checks and linking against std::vector<char> could bear any costs in terms of performance of a network library. /Michel