From 04a53753d25f5dc591ba8d607e903c78b6cc016d Mon Sep 17 00:00:00 2001 From: "erg@google.com" Date: Wed, 29 Sep 2010 19:25:29 +0000 Subject: Mark common instantions of CancelableRequestConsumerTSimple as extern templates. This means that these template instantiations will be built once in cancelable_request.cc instead of in each of the 20 files that use it. The definitions have been moved to make them not inline (as explicit template instantiation only works with non-inline members). This cuts more than 4 megabytes off libbrowser.a in Debug mode. This patch does nothing when compiled with MSVC, due to compiler problems. BUG=none TEST=compiles smaller Review URL: http://codereview.chromium.org/3520001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60974 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/cancelable_request.h | 262 +++++++++++++++++++++++------------- 1 file changed, 170 insertions(+), 92 deletions(-) (limited to 'chrome/browser/cancelable_request.h') diff --git a/chrome/browser/cancelable_request.h b/chrome/browser/cancelable_request.h index d793398..3ad7261 100644 --- a/chrome/browser/cancelable_request.h +++ b/chrome/browser/cancelable_request.h @@ -99,6 +99,7 @@ #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/task.h" +#include "build/build_config.h" class CancelableRequestBase; class CancelableRequestConsumerBase; @@ -209,90 +210,48 @@ class CancelableRequestConsumerBase { template class CancelableRequestConsumerTSimple : public CancelableRequestConsumerBase { public: - CancelableRequestConsumerTSimple() { - } + CancelableRequestConsumerTSimple(); // Cancel any outstanding requests so that we do not get called back after we // are destroyed. As these requests are removed, the providers will call us // back on OnRequestRemoved, which will then update the list. To iterate // successfully while the list is changing out from under us, we make a copy. - virtual ~CancelableRequestConsumerTSimple() { - CancelAllRequests(); - } + virtual ~CancelableRequestConsumerTSimple(); // Associates some random data with a specified request. The request MUST be // outstanding, or it will assert. This is intended to be called immediately // after a request is issued. void SetClientData(CancelableRequestProvider* p, CancelableRequestProvider::Handle h, - T client_data) { - PendingRequest request(p, h); - DCHECK(pending_requests_.find(request) != pending_requests_.end()); - pending_requests_[request] = client_data; - } + T client_data); // Retrieves previously associated data for a specified request. The request // MUST be outstanding, or it will assert. This is intended to be called // during processing of a callback to retrieve extra data. T GetClientData(CancelableRequestProvider* p, - CancelableRequestProvider::Handle h) { - PendingRequest request(p, h); - DCHECK(pending_requests_.find(request) != pending_requests_.end()); - return pending_requests_[request]; - } + CancelableRequestProvider::Handle h); // Returns the data associated with the current request being processed. This // is only valid during the time a callback is being processed. - T GetClientDataForCurrentRequest() { - DCHECK(current_request_.is_valid()); - return GetClientData(current_request_.provider, current_request_.handle); - } + T GetClientDataForCurrentRequest(); // Returns true if there are any pending requests. - bool HasPendingRequests() const { - return !pending_requests_.empty(); - } + bool HasPendingRequests() const; // Returns the number of pending requests. - size_t PendingRequestCount() const { - return pending_requests_.size(); - } + size_t PendingRequestCount() const; // Cancels all requests outstanding. - void CancelAllRequests() { - PendingRequestList copied_requests(pending_requests_); - for (typename PendingRequestList::iterator i = copied_requests.begin(); - i != copied_requests.end(); ++i) - i->first.provider->CancelRequest(i->first.handle); - copied_requests.clear(); - - // That should have cleared all the pending items. - DCHECK(pending_requests_.empty()); - } + void CancelAllRequests(); // Returns the handle for the first request that has the specified client data // (in |handle|). Returns true if there is a request for the specified client // data, false otherwise. bool GetFirstHandleForClientData(T client_data, - CancelableRequestProvider::Handle* handle) { - for (typename PendingRequestList::const_iterator i = - pending_requests_.begin(); i != pending_requests_.end(); ++i) { - if (i->second == client_data) { - *handle = i->first.handle; - return true; - } - } - *handle = 0; - return false; - } + CancelableRequestProvider::Handle* handle); // Gets the client data for all pending requests. - void GetAllClientData(std::vector* data) { - DCHECK(data); - for (typename PendingRequestList::iterator i = pending_requests_.begin(); - i != pending_requests_.end(); ++i) - data->push_back(i->second); - } + void GetAllClientData(std::vector* data); protected: struct PendingRequest { @@ -317,38 +276,19 @@ class CancelableRequestConsumerTSimple : public CancelableRequestConsumerBase { }; typedef std::map PendingRequestList; - virtual T get_initial_t() const { - return 0; - } + virtual T get_initial_t() const; virtual void OnRequestAdded(CancelableRequestProvider* provider, - CancelableRequestProvider::Handle handle) { - DCHECK(pending_requests_.find(PendingRequest(provider, handle)) == - pending_requests_.end()); - pending_requests_[PendingRequest(provider, handle)] = get_initial_t(); - } + CancelableRequestProvider::Handle handle); virtual void OnRequestRemoved(CancelableRequestProvider* provider, - CancelableRequestProvider::Handle handle) { - typename PendingRequestList::iterator i = - pending_requests_.find(PendingRequest(provider, handle)); - if (i == pending_requests_.end()) { - NOTREACHED() << "Got a complete notification for a nonexistent request"; - return; - } - - pending_requests_.erase(i); - } + CancelableRequestProvider::Handle handle); virtual void WillExecute(CancelableRequestProvider* provider, - CancelableRequestProvider::Handle handle) { - current_request_ = PendingRequest(provider, handle); - } + CancelableRequestProvider::Handle handle); virtual void DidExecute(CancelableRequestProvider* provider, - CancelableRequestProvider::Handle handle) { - current_request_ = PendingRequest(); - } + CancelableRequestProvider::Handle handle); // Lists all outstanding requests. PendingRequestList pending_requests_; @@ -358,21 +298,169 @@ class CancelableRequestConsumerTSimple : public CancelableRequestConsumerBase { PendingRequest current_request_; }; +template +CancelableRequestConsumerTSimple::CancelableRequestConsumerTSimple() { +} + +template +CancelableRequestConsumerTSimple::~CancelableRequestConsumerTSimple() { + CancelAllRequests(); +} + +template +void CancelableRequestConsumerTSimple::SetClientData( + CancelableRequestProvider* p, + CancelableRequestProvider::Handle h, + T client_data) { + PendingRequest request(p, h); + DCHECK(pending_requests_.find(request) != pending_requests_.end()); + pending_requests_[request] = client_data; +} + +template +T CancelableRequestConsumerTSimple::GetClientData( + CancelableRequestProvider* p, + CancelableRequestProvider::Handle h) { + PendingRequest request(p, h); + DCHECK(pending_requests_.find(request) != pending_requests_.end()); + return pending_requests_[request]; +} + +template +T CancelableRequestConsumerTSimple::GetClientDataForCurrentRequest() { + DCHECK(current_request_.is_valid()); + return GetClientData(current_request_.provider, current_request_.handle); +} + +template +bool CancelableRequestConsumerTSimple::HasPendingRequests() const { + return !pending_requests_.empty(); +} + +template +size_t CancelableRequestConsumerTSimple::PendingRequestCount() const { + return pending_requests_.size(); +} + +template +void CancelableRequestConsumerTSimple::CancelAllRequests() { + PendingRequestList copied_requests(pending_requests_); + for (typename PendingRequestList::iterator i = copied_requests.begin(); + i != copied_requests.end(); ++i) + i->first.provider->CancelRequest(i->first.handle); + copied_requests.clear(); + + // That should have cleared all the pending items. + DCHECK(pending_requests_.empty()); +} + +template +bool CancelableRequestConsumerTSimple::GetFirstHandleForClientData( + T client_data, + CancelableRequestProvider::Handle* handle) { + for (typename PendingRequestList::const_iterator i = + pending_requests_.begin(); i != pending_requests_.end(); ++i) { + if (i->second == client_data) { + *handle = i->first.handle; + return true; + } + } + *handle = 0; + return false; +} + +template +void CancelableRequestConsumerTSimple::GetAllClientData( + std::vector* data) { + DCHECK(data); + for (typename PendingRequestList::iterator i = pending_requests_.begin(); + i != pending_requests_.end(); ++i) + data->push_back(i->second); +} + +template +T CancelableRequestConsumerTSimple::get_initial_t() const { + return 0; +} + +template +void CancelableRequestConsumerTSimple::OnRequestAdded( + CancelableRequestProvider* provider, + CancelableRequestProvider::Handle handle) { + DCHECK(pending_requests_.find(PendingRequest(provider, handle)) == + pending_requests_.end()); + pending_requests_[PendingRequest(provider, handle)] = get_initial_t(); +} + +template +void CancelableRequestConsumerTSimple::OnRequestRemoved( + CancelableRequestProvider* provider, + CancelableRequestProvider::Handle handle) { + typename PendingRequestList::iterator i = + pending_requests_.find(PendingRequest(provider, handle)); + if (i == pending_requests_.end()) { + NOTREACHED() << "Got a complete notification for a nonexistent request"; + return; + } + + pending_requests_.erase(i); +} + +template +void CancelableRequestConsumerTSimple::WillExecute( + CancelableRequestProvider* provider, + CancelableRequestProvider::Handle handle) { + current_request_ = PendingRequest(provider, handle); +} + +template +void CancelableRequestConsumerTSimple::DidExecute( + CancelableRequestProvider* provider, + CancelableRequestProvider::Handle handle) { + current_request_ = PendingRequest(); +} + // See CancelableRequestConsumerTSimple. The default value for T // is given in |initial_t|. template class CancelableRequestConsumerT : public CancelableRequestConsumerTSimple { + public: + CancelableRequestConsumerT(); + virtual ~CancelableRequestConsumerT(); + protected: - virtual T get_initial_t() const { - return initial_t; - } + virtual T get_initial_t() const; }; +template +CancelableRequestConsumerT::CancelableRequestConsumerT() { +} + +template +CancelableRequestConsumerT::~CancelableRequestConsumerT() { +} + +template +T CancelableRequestConsumerT::get_initial_t() const { + return initial_t; +} + // Some clients may not want to store data. Rather than do some complicated // thing with virtual functions to allow some consumers to store extra data and // some not to, we just define a default one that stores some dummy data. typedef CancelableRequestConsumerT CancelableRequestConsumer; +// MSVC doesn't like complex extern templates and DLLs. +#if !defined(COMPILER_MSVC) +// The vast majority of CancelableRequestConsumers are instantiated on , +// so prevent that template from being expanded in normal code. +extern template class CancelableRequestConsumerTSimple; + +// We'll also want to extern-template the most common, typedef-ed +// CancelableRequestConsumerT. +extern template class CancelableRequestConsumerT; +#endif + // CancelableRequest ---------------------------------------------------------- // // The request object that is used by a CancelableRequestProvider to send @@ -420,12 +508,7 @@ class CancelableRequestBase // // In addition, not all of the information (for example, the handle) is known // at construction time. - CancelableRequestBase() - : provider_(NULL), - consumer_(NULL), - handle_(0) { - callback_thread_ = MessageLoop::current(); - } + CancelableRequestBase(); CancelableRequestConsumerBase* consumer() const { return consumer_; @@ -447,18 +530,13 @@ class CancelableRequestBase protected: friend class base::RefCountedThreadSafe; - virtual ~CancelableRequestBase() {} + virtual ~CancelableRequestBase(); // Initializes the object with the particulars from the provider. It may only // be called once (it is called by the provider, which is a friend). void Init(CancelableRequestProvider* provider, CancelableRequestProvider::Handle handle, - CancelableRequestConsumerBase* consumer) { - DCHECK(handle_ == 0 && provider_ == NULL && consumer_ == NULL); - provider_ = provider; - consumer_ = consumer; - handle_ = handle; - } + CancelableRequestConsumerBase* consumer); // Tells the provider that the request is complete, which then tells the // consumer. -- cgit v1.1