Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / content / child / shared_memory_received_data_factory.cc
blob7e9f9d9ee8256f4e7959b5a08c65220148d6bb43
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/child/shared_memory_received_data_factory.h"
7 #include <algorithm>
9 #include "content/common/resource_messages.h"
10 #include "ipc/ipc_sender.h"
12 namespace content {
14 class SharedMemoryReceivedDataFactory::SharedMemoryReceivedData final
15 : public RequestPeer::ReceivedData {
16 public:
17 SharedMemoryReceivedData(
18 const char* payload,
19 int length,
20 int encoded_length,
21 scoped_refptr<SharedMemoryReceivedDataFactory> factory,
22 SharedMemoryReceivedDataFactory::TicketId id)
23 : payload_(payload),
24 length_(length),
25 encoded_length_(encoded_length),
26 factory_(factory),
27 id_(id) {}
29 ~SharedMemoryReceivedData() override { factory_->Reclaim(id_); }
31 const char* payload() const override { return payload_; }
32 int length() const override { return length_; }
33 int encoded_length() const override { return encoded_length_; }
35 private:
36 const char* const payload_;
37 const int length_;
38 const int encoded_length_;
40 scoped_refptr<SharedMemoryReceivedDataFactory> factory_;
41 SharedMemoryReceivedDataFactory::TicketId id_;
43 DISALLOW_COPY_AND_ASSIGN(SharedMemoryReceivedData);
46 SharedMemoryReceivedDataFactory::SharedMemoryReceivedDataFactory(
47 IPC::Sender* message_sender,
48 int request_id,
49 linked_ptr<base::SharedMemory> memory)
50 : id_(0),
51 oldest_(0),
52 message_sender_(message_sender),
53 request_id_(request_id),
54 is_stopped_(false),
55 memory_(memory) {
58 SharedMemoryReceivedDataFactory::~SharedMemoryReceivedDataFactory() {
59 if (!is_stopped_)
60 SendAck(released_tickets_.size());
63 scoped_ptr<RequestPeer::ReceivedData> SharedMemoryReceivedDataFactory::Create(
64 int offset,
65 int length,
66 int encoded_length) {
67 const char* start = static_cast<char*>(memory_->memory());
68 const char* payload = start + offset;
69 TicketId id = id_++;
71 return make_scoped_ptr(
72 new SharedMemoryReceivedData(payload, length, encoded_length, this, id));
75 void SharedMemoryReceivedDataFactory::Stop() {
76 is_stopped_ = true;
77 released_tickets_.clear();
78 message_sender_ = nullptr;
81 class SharedMemoryReceivedDataFactory::TicketComparator final {
82 public:
83 explicit TicketComparator(TicketId oldest) : oldest_(oldest) {}
84 bool operator()(TicketId x, TicketId y) const {
85 if ((oldest_ <= x) == (oldest_ <= y))
86 return x <= y;
88 return (oldest_ <= x);
91 private:
92 TicketId oldest_;
95 void SharedMemoryReceivedDataFactory::Reclaim(TicketId id) {
96 if (is_stopped_)
97 return;
98 if (oldest_ != id) {
99 released_tickets_.push_back(id);
100 return;
103 ++oldest_;
104 SendAck(1);
105 if (released_tickets_.empty()) {
106 // Fast path: (hopefully) the most typical case.
107 return;
109 std::sort(released_tickets_.begin(), released_tickets_.end(),
110 TicketComparator(oldest_));
111 size_t count = 0;
112 for (size_t i = 0;; ++i) {
113 if (i == released_tickets_.size() ||
114 released_tickets_[i] != static_cast<TicketId>(id + i + 1)) {
115 count = i;
116 break;
119 released_tickets_.erase(released_tickets_.begin(),
120 released_tickets_.begin() + count);
121 oldest_ += count;
122 SendAck(count);
125 void SharedMemoryReceivedDataFactory::SendAck(size_t count) {
126 for (size_t i = 0; i < count; ++i) {
127 message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id_));
131 } // namespace content