• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_BASE_DATAGRAM_BUFFER_H_
6 #define NET_BASE_DATAGRAM_BUFFER_H_
7 
8 #include <list>
9 
10 #include "base/memory/weak_ptr.h"
11 #include "net/base/net_export.h"
12 
13 namespace net {
14 
15 // An IO buffer, (at least initially) specifically for use with the
16 // new DatagramClientSocket::WriteAsync method, with the following key
17 // features:
18 //
19 //   1) Meant to be easily batched when that improves efficiency. The
20 //      primary goal of WriteAsync is to enable enlisting an
21 //      additional cpu core for the kernel part of socket write.
22 //   2) Uses unique_ptr (with std::move) rather than reference
23 //      counting as in IOBuffers.  The benefit is safer cancellation
24 //      semantics, IOBuffer used reference count to enforce unique
25 //      ownership in an idiomatic fashion.  unique_ptr is ligher weight
26 //      as it doesn't use thread safe primitives as
27 //      RefCountedThreadSafe does.
28 //   3) Provides a pooling allocator, which for datagram buffers is
29 //      much cheaper than using fully general allocator (e.g. malloc
30 //      etc.).  The implementation takes advantage of
31 //      std::list::splice so that costs associated with allocations
32 //      and copies of pool metadata quickly amortize to zero, and all
33 //      common operations are O(1).
34 
35 class DatagramBuffer;
36 
37 // Batches of DatagramBuffers are treated as a FIFO queue, implemented
38 // by |std::list|.  Note that |std::list::splice()| is attractive for
39 // this use case because it keeps most operations to O(1) and
40 // minimizes allocations/frees and copies.
41 typedef std::list<std::unique_ptr<DatagramBuffer>> DatagramBuffers;
42 
43 class NET_EXPORT_PRIVATE DatagramBufferPool {
44  public:
45   // |max_buffer_size| must be >= largest |buf_len| provided to
46   // ||New()|.
47   explicit DatagramBufferPool(size_t max_buffer_size);
48   DatagramBufferPool(const DatagramBufferPool&) = delete;
49   DatagramBufferPool& operator=(const DatagramBufferPool&) = delete;
50   virtual ~DatagramBufferPool();
51   // Insert a new element (drawn from the pool) containing a copy of
52   // |buffer| to |buffers|. Caller retains owenership of |buffers| and |buffer|.
53   void Enqueue(const char* buffer, size_t buf_len, DatagramBuffers* buffers);
54   // Return all elements of |buffers| to the pool.  Caller retains
55   // ownership of |buffers|.
56   void Dequeue(DatagramBuffers* buffers);
57 
max_buffer_size()58   size_t max_buffer_size() { return max_buffer_size_; }
59 
60  private:
61   const size_t max_buffer_size_;
62   DatagramBuffers free_list_;
63 };
64 
65 // |DatagramBuffer|s can only be created via
66 // |DatagramBufferPool::Enqueue()|.
67 //
68 
69 // |DatagramBuffer|s should be recycled via
70 // |DatagramBufferPool::Dequeue|.  Care must be taken when a
71 // |DatagramBuffer| is moved to another thread via
72 // |PostTask|. |Dequeue| is not expected to be thread-safe, so it
73 // is preferred to move the |DatagramBuffer|s back to the thread where
74 // the pool lives (e.g. using |PostTaskAndReturnWithResult|) and
75 // dequeuing them from there.  In the exception of pathalogical
76 // cancellation (e.g. due to thread tear-down), the destructor will
77 // release its memory permanently rather than returning to the pool.
78 class NET_EXPORT_PRIVATE DatagramBuffer {
79  public:
80   DatagramBuffer() = delete;
81   DatagramBuffer(const DatagramBuffer&) = delete;
82   DatagramBuffer& operator=(const DatagramBuffer&) = delete;
83   ~DatagramBuffer();
84 
85   char* data() const;
86   size_t length() const;
87 
88  protected:
89   explicit DatagramBuffer(size_t max_packet_size);
90 
91  private:
92   friend class DatagramBufferPool;
93 
94   void Set(const char* buffer, size_t buf_len);
95 
96   std::unique_ptr<char[]> data_;
97   size_t length_ = 0;
98 };
99 
100 }  // namespace net
101 
102 #endif  // NET_BASE_DATAGRAM_BUFFER_H_
103