| // Copyright 2010 Google Inc. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // Author: jmarantz@google.com (Joshua Marantz) |
| // lsong@google.com (Libo Song) |
| |
| #include "net/instaweb/http/public/sync_fetcher_adapter_callback.h" |
| |
| #include "base/logging.h" |
| #include "pagespeed/kernel/base/abstract_mutex.h" |
| #include "pagespeed/kernel/base/basictypes.h" |
| #include "pagespeed/kernel/base/condvar.h" |
| #include "pagespeed/kernel/base/string_util.h" |
| #include "pagespeed/kernel/base/thread_system.h" |
| #include "pagespeed/kernel/base/writer.h" |
| |
| namespace net_instaweb { |
| |
| class MessageHandler; |
| |
| bool SyncFetcherAdapterCallback::ProtectedWriter::Write( |
| const StringPiece& buf, MessageHandler* handler) { |
| bool ret = true; |
| |
| // If the callback has not timed out and been released, then pass |
| // the data through. |
| if (callback_->LockIfNotReleased()) { |
| ret = orig_writer_->Write(buf, handler); |
| callback_->Unlock(); |
| } |
| return ret; |
| } |
| |
| bool SyncFetcherAdapterCallback::ProtectedWriter::Flush( |
| MessageHandler* handler) { |
| bool ret = true; |
| |
| // If the callback has not timed out and been released, then pass |
| // the flush through. |
| if (callback_->LockIfNotReleased()) { |
| ret = orig_writer_->Flush(handler); |
| callback_->Unlock(); |
| } |
| return ret; |
| } |
| |
| SyncFetcherAdapterCallback::SyncFetcherAdapterCallback( |
| ThreadSystem* thread_system, Writer* writer, |
| const RequestContextPtr& request_context) |
| : AsyncFetch(request_context), |
| mutex_(thread_system->NewMutex()), |
| cond_(mutex_->NewCondvar()), |
| done_(false), |
| success_(false), |
| released_(false), |
| writer_(new ProtectedWriter(this, writer)) { |
| } |
| |
| SyncFetcherAdapterCallback::~SyncFetcherAdapterCallback() { |
| } |
| |
| void SyncFetcherAdapterCallback::HandleDone(bool success) { |
| mutex_->Lock(); |
| done_ = true; |
| success_ = success; |
| if (released_) { |
| mutex_->Unlock(); |
| delete this; |
| } else { |
| cond_->Signal(); |
| mutex_->Unlock(); |
| } |
| } |
| |
| void SyncFetcherAdapterCallback::Release() { |
| mutex_->Lock(); |
| DCHECK(!released_); |
| released_ = true; |
| if (done_) { |
| mutex_->Unlock(); |
| delete this; |
| } else { |
| mutex_->Unlock(); |
| } |
| } |
| |
| bool SyncFetcherAdapterCallback::IsDone() const { |
| ScopedMutex hold_lock(mutex_.get()); |
| return done_; |
| } |
| |
| bool SyncFetcherAdapterCallback::IsDoneLockHeld() const { |
| mutex_->DCheckLocked(); |
| return done_; |
| } |
| |
| bool SyncFetcherAdapterCallback::success() const { |
| ScopedMutex hold_lock(mutex_.get()); |
| return success_; |
| } |
| |
| bool SyncFetcherAdapterCallback::released() const { |
| ScopedMutex hold_lock(mutex_.get()); |
| return released_; |
| } |
| |
| bool SyncFetcherAdapterCallback::LockIfNotReleased() { |
| mutex_->Lock(); |
| if (!released_) { |
| return true; |
| } else { |
| mutex_->Unlock(); |
| return false; |
| } |
| } |
| |
| void SyncFetcherAdapterCallback::Unlock() { |
| mutex_->Unlock(); |
| } |
| |
| void SyncFetcherAdapterCallback::TimedWait(int64 timeout_ms) { |
| mutex_->DCheckLocked(); |
| DCHECK(!released_); |
| cond_->TimedWait(timeout_ms); |
| } |
| |
| } // namespace net_instaweb |