blob: 486f10748fdee9a68af978a2d6f1724d49f1c6c8 [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_CIRCULAR_QUEUE_H_
29#define V8_CIRCULAR_QUEUE_H_
30
31namespace v8 {
32namespace internal {
33
34
35// Lock-based blocking circular queue for small records. Intended for
36// transfer of small records between a single producer and a single
37// consumer. Blocks on enqueue operation if the queue is full.
38template<typename Record>
39class CircularQueue {
40 public:
41 inline explicit CircularQueue(int desired_buffer_size_in_bytes);
42 inline ~CircularQueue();
43
44 INLINE(void Dequeue(Record* rec));
45 INLINE(void Enqueue(const Record& rec));
46 INLINE(bool IsEmpty()) { return enqueue_pos_ == dequeue_pos_; }
47
48 private:
49 INLINE(Record* Next(Record* curr));
50
51 Record* buffer_;
52 Record* const buffer_end_;
53 Semaphore* enqueue_semaphore_;
54 Record* enqueue_pos_;
55 Record* dequeue_pos_;
56
57 DISALLOW_COPY_AND_ASSIGN(CircularQueue);
58};
59
60
61// Lock-free cache-friendly sampling circular queue for large
62// records. Intended for fast transfer of large records between a
63// single producer and a single consumer. If the queue is full,
64// previous unread records are overwritten. The queue is designed with
65// a goal in mind to evade cache lines thrashing by preventing
66// simultaneous reads and writes to adjanced memory locations.
67//
68// IMPORTANT: as a producer never checks for chunks cleanness, it is
69// possible that it can catch up and overwrite a chunk that a consumer
70// is currently reading, resulting in a corrupt record being read.
71class SamplingCircularQueue {
72 public:
73 // Executed on the application thread.
74 SamplingCircularQueue(int record_size_in_bytes,
75 int desired_chunk_size_in_bytes,
76 int buffer_size_in_chunks);
77 ~SamplingCircularQueue();
78
79 // Enqueue returns a pointer to a memory location for storing the next
80 // record.
81 INLINE(void* Enqueue());
82
83 // Executed on the consumer (analyzer) thread.
84 // StartDequeue returns a pointer to a memory location for retrieving
85 // the next record. After the record had been read by a consumer,
86 // FinishDequeue must be called. Until that moment, subsequent calls
87 // to StartDequeue will return the same pointer.
88 void* StartDequeue();
89 void FinishDequeue();
90 // Due to a presence of slipping between the producer and the consumer,
91 // the queue must be notified whether producing has been finished in order
92 // to process remaining records from the buffer.
93 void FlushResidualRecords();
94
95 typedef AtomicWord Cell;
96 // Reserved values for the first cell of a record.
97 static const Cell kClear = 0; // Marks clean (processed) chunks.
98 static const Cell kEnd = -1; // Marks the end of the buffer.
99
100 private:
101 struct ProducerPosition {
102 Cell* enqueue_pos;
103 };
104 struct ConsumerPosition {
105 Cell* dequeue_chunk_pos;
106 Cell* dequeue_chunk_poll_pos;
107 Cell* dequeue_pos;
108 Cell* dequeue_end_pos;
109 };
110
111 INLINE(void WrapPositionIfNeeded(Cell** pos));
112
113 const int record_size_;
114 const int chunk_size_in_bytes_;
115 const int chunk_size_;
116 const int buffer_size_;
117 const int producer_consumer_distance_;
118 Cell* buffer_;
119 byte* positions_;
120 ProducerPosition* producer_pos_;
121 ConsumerPosition* consumer_pos_;
122
123 DISALLOW_COPY_AND_ASSIGN(SamplingCircularQueue);
124};
125
126
127} } // namespace v8::internal
128
129#endif // V8_CIRCULAR_QUEUE_H_