Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: src/IceThreading.h

Issue 1804133002: Subzero. Uses unique_ptrs in the emit queue. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceGlobalContext.cpp ('k') | src/IceThreading.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceThreading.h - Threading functions ---------*- C++ -*-===// 1 //===- subzero/src/IceThreading.h - Threading functions ---------*- C++ -*-===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
11 /// \brief Declares threading-related functions. 11 /// \brief Declares threading-related functions.
12 /// 12 ///
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #ifndef SUBZERO_SRC_ICETHREADING_H 15 #ifndef SUBZERO_SRC_ICETHREADING_H
16 #define SUBZERO_SRC_ICETHREADING_H 16 #define SUBZERO_SRC_ICETHREADING_H
17 17
18 #include "IceDefs.h" 18 #include "IceDefs.h"
19 19
20 #include <condition_variable> 20 #include <condition_variable>
21 #include <memory>
21 #include <mutex> 22 #include <mutex>
23 #include <utility>
22 24
23 namespace Ice { 25 namespace Ice {
24 26
25 /// BoundedProducerConsumerQueue is a work queue that allows multiple producers 27 /// BoundedProducerConsumerQueue is a work queue that allows multiple producers
26 /// and multiple consumers. A producer adds entries using blockingPush(), and 28 /// and multiple consumers. A producer adds entries using blockingPush(), and
27 /// may block if the queue is "full". A producer uses notifyEnd() to indicate 29 /// may block if the queue is "full". A producer uses notifyEnd() to indicate
28 /// that no more entries will be added. A consumer removes an item using 30 /// that no more entries will be added. A consumer removes an item using
29 /// blockingPop(), which will return nullptr if notifyEnd() has been called and 31 /// blockingPop(), which will return nullptr if notifyEnd() has been called and
30 /// the queue is empty (it never returns nullptr if the queue contained any 32 /// the queue is empty (it never returns nullptr if the queue contained any
31 /// items). 33 /// items).
(...skipping 16 matching lines...) Expand all
48 template <typename T, size_t MaxStaticSize = 128> 50 template <typename T, size_t MaxStaticSize = 128>
49 class BoundedProducerConsumerQueue { 51 class BoundedProducerConsumerQueue {
50 BoundedProducerConsumerQueue() = delete; 52 BoundedProducerConsumerQueue() = delete;
51 BoundedProducerConsumerQueue(const BoundedProducerConsumerQueue &) = delete; 53 BoundedProducerConsumerQueue(const BoundedProducerConsumerQueue &) = delete;
52 BoundedProducerConsumerQueue & 54 BoundedProducerConsumerQueue &
53 operator=(const BoundedProducerConsumerQueue &) = delete; 55 operator=(const BoundedProducerConsumerQueue &) = delete;
54 56
55 public: 57 public:
56 BoundedProducerConsumerQueue(bool Sequential, size_t MaxSize = MaxStaticSize) 58 BoundedProducerConsumerQueue(bool Sequential, size_t MaxSize = MaxStaticSize)
57 : MaxSize(std::min(MaxSize, MaxStaticSize)), Sequential(Sequential) {} 59 : MaxSize(std::min(MaxSize, MaxStaticSize)), Sequential(Sequential) {}
58 void blockingPush(T *Item) { 60 void blockingPush(std::unique_ptr<T> Item) {
59 { 61 {
60 std::unique_lock<GlobalLockType> L(Lock); 62 std::unique_lock<GlobalLockType> L(Lock);
61 // If the work queue is already "full", wait for a consumer to grab an 63 // If the work queue is already "full", wait for a consumer to grab an
62 // element and shrink the queue. 64 // element and shrink the queue.
63 Shrunk.wait(L, [this] { return size() < MaxSize || Sequential; }); 65 Shrunk.wait(L, [this] { return size() < MaxSize || Sequential; });
64 push(Item); 66 push(std::move(Item));
65 } 67 }
66 GrewOrEnded.notify_one(); 68 GrewOrEnded.notify_one();
67 } 69 }
68 T *blockingPop() { 70 std::unique_ptr<T> blockingPop() {
69 T *Item = nullptr; 71 std::unique_ptr<T> Item;
70 bool ShouldNotifyProducer = false; 72 bool ShouldNotifyProducer = false;
71 { 73 {
72 std::unique_lock<GlobalLockType> L(Lock); 74 std::unique_lock<GlobalLockType> L(Lock);
73 GrewOrEnded.wait(L, [this] { return IsEnded || !empty() || Sequential; }); 75 GrewOrEnded.wait(L, [this] { return IsEnded || !empty() || Sequential; });
74 if (!empty()) { 76 if (!empty()) {
75 Item = pop(); 77 Item = pop();
76 ShouldNotifyProducer = !IsEnded; 78 ShouldNotifyProducer = !IsEnded;
77 } 79 }
78 } 80 }
79 if (ShouldNotifyProducer) 81 if (ShouldNotifyProducer)
80 Shrunk.notify_one(); 82 Shrunk.notify_one();
81 return Item; 83 return Item;
82 } 84 }
83 void notifyEnd() { 85 void notifyEnd() {
84 { 86 {
85 std::lock_guard<GlobalLockType> L(Lock); 87 std::lock_guard<GlobalLockType> L(Lock);
86 IsEnded = true; 88 IsEnded = true;
87 } 89 }
88 GrewOrEnded.notify_all(); 90 GrewOrEnded.notify_all();
89 } 91 }
90 92
91 private: 93 private:
92 const static size_t MaxStaticSizeMask = MaxStaticSize - 1; 94 const static size_t MaxStaticSizeMask = MaxStaticSize - 1;
93 static_assert(!(MaxStaticSize & (MaxStaticSize - 1)), 95 static_assert(!(MaxStaticSize & (MaxStaticSize - 1)),
94 "MaxStaticSize must be a power of 2"); 96 "MaxStaticSize must be a power of 2");
95 97
96 ICE_CACHELINE_BOUNDARY; 98 ICE_CACHELINE_BOUNDARY;
97 /// WorkItems and Lock are read/written by all. 99 /// WorkItems and Lock are read/written by all.
98 T *WorkItems[MaxStaticSize]; 100 std::unique_ptr<T> WorkItems[MaxStaticSize];
99 ICE_CACHELINE_BOUNDARY; 101 ICE_CACHELINE_BOUNDARY;
100 /// Lock guards access to WorkItems, Front, Back, and IsEnded. 102 /// Lock guards access to WorkItems, Front, Back, and IsEnded.
101 GlobalLockType Lock; 103 GlobalLockType Lock;
102 104
103 ICE_CACHELINE_BOUNDARY; 105 ICE_CACHELINE_BOUNDARY;
104 /// GrewOrEnded is written by the producers and read by the consumers. It is 106 /// GrewOrEnded is written by the producers and read by the consumers. It is
105 /// notified (by the producer) when something is added to the queue, in case 107 /// notified (by the producer) when something is added to the queue, in case
106 /// consumers are waiting for a non-empty queue. 108 /// consumers are waiting for a non-empty queue.
107 std::condition_variable GrewOrEnded; 109 std::condition_variable GrewOrEnded;
108 /// Back is the index into WorkItems[] of where the next element will be 110 /// Back is the index into WorkItems[] of where the next element will be
(...skipping 15 matching lines...) Expand all
124 126
125 /// MaxSize and Sequential are read by all and written by none. 127 /// MaxSize and Sequential are read by all and written by none.
126 const size_t MaxSize; 128 const size_t MaxSize;
127 const bool Sequential; 129 const bool Sequential;
128 /// IsEnded is read by the consumers, and only written once by the producer. 130 /// IsEnded is read by the consumers, and only written once by the producer.
129 bool IsEnded = false; 131 bool IsEnded = false;
130 132
131 /// The lock must be held when the following methods are called. 133 /// The lock must be held when the following methods are called.
132 bool empty() const { return Front == Back; } 134 bool empty() const { return Front == Back; }
133 size_t size() const { return Back - Front; } 135 size_t size() const { return Back - Front; }
134 void push(T *Item) { 136 void push(std::unique_ptr<T> Item) {
135 WorkItems[Back++ & MaxStaticSizeMask] = Item; 137 WorkItems[Back++ & MaxStaticSizeMask] = std::move(Item);
136 assert(size() <= MaxStaticSize); 138 assert(size() <= MaxStaticSize);
137 } 139 }
138 T *pop() { 140 std::unique_ptr<T> pop() {
139 assert(!empty()); 141 assert(!empty());
140 return WorkItems[Front++ & MaxStaticSizeMask]; 142 return std::move(WorkItems[Front++ & MaxStaticSizeMask]);
141 } 143 }
142 }; 144 };
143 145
144 /// EmitterWorkItem is a simple wrapper around a pointer that represents a work 146 /// EmitterWorkItem is a simple wrapper around a pointer that represents a work
145 /// item to be emitted, i.e. a function or a set of global declarations and 147 /// item to be emitted, i.e. a function or a set of global declarations and
146 /// initializers, and it includes a sequence number so that work items can be 148 /// initializers, and it includes a sequence number so that work items can be
147 /// emitted in a particular order for deterministic output. It acts like an 149 /// emitted in a particular order for deterministic output. It acts like an
148 /// interface class, but instead of making the classes of interest inherit from 150 /// interface class, but instead of making the classes of interest inherit from
149 /// EmitterWorkItem, it wraps pointers to these classes. Some space is wasted 151 /// EmitterWorkItem, it wraps pointers to these classes. Some space is wasted
150 /// compared to storing the pointers in a union, but not too much due to the 152 /// compared to storing the pointers in a union, but not too much due to the
(...skipping 16 matching lines...) Expand all
167 /// deleted (to recover lots of memory). 169 /// deleted (to recover lots of memory).
168 /// 170 ///
169 /// WI_Cfg: A Cfg that has not yet had emit() or emitIAS() called on it. This 171 /// WI_Cfg: A Cfg that has not yet had emit() or emitIAS() called on it. This
170 /// is only used as a debugging configuration when we want to emit "readable" 172 /// is only used as a debugging configuration when we want to emit "readable"
171 /// assembly code, possibly annotated with liveness and other information only 173 /// assembly code, possibly annotated with liveness and other information only
172 /// available in the Cfg and not in the Assembler buffer. 174 /// available in the Cfg and not in the Assembler buffer.
173 enum ItemKind { WI_Nop, WI_GlobalInits, WI_Asm, WI_Cfg }; 175 enum ItemKind { WI_Nop, WI_GlobalInits, WI_Asm, WI_Cfg };
174 /// Constructor for a WI_Nop work item. 176 /// Constructor for a WI_Nop work item.
175 explicit EmitterWorkItem(uint32_t Seq); 177 explicit EmitterWorkItem(uint32_t Seq);
176 /// Constructor for a WI_GlobalInits work item. 178 /// Constructor for a WI_GlobalInits work item.
177 EmitterWorkItem(uint32_t Seq, VariableDeclarationList *D); 179 EmitterWorkItem(uint32_t Seq, std::unique_ptr<VariableDeclarationList> D);
178 /// Constructor for a WI_Asm work item. 180 /// Constructor for a WI_Asm work item.
179 EmitterWorkItem(uint32_t Seq, Assembler *A); 181 EmitterWorkItem(uint32_t Seq, std::unique_ptr<Assembler> A);
180 /// Constructor for a WI_Cfg work item. 182 /// Constructor for a WI_Cfg work item.
181 EmitterWorkItem(uint32_t Seq, Cfg *F); 183 EmitterWorkItem(uint32_t Seq, std::unique_ptr<Cfg> F);
182 uint32_t getSequenceNumber() const { return Sequence; } 184 uint32_t getSequenceNumber() const { return Sequence; }
183 ItemKind getKind() const { return Kind; } 185 ItemKind getKind() const { return Kind; }
184 void setGlobalInits(std::unique_ptr<VariableDeclarationList> GloblInits); 186 void setGlobalInits(std::unique_ptr<VariableDeclarationList> GloblInits);
185 std::unique_ptr<VariableDeclarationList> getGlobalInits(); 187 std::unique_ptr<VariableDeclarationList> getGlobalInits();
186 std::unique_ptr<Assembler> getAsm(); 188 std::unique_ptr<Assembler> getAsm();
187 std::unique_ptr<Cfg> getCfg(); 189 std::unique_ptr<Cfg> getCfg();
188 190
189 private: 191 private:
190 const uint32_t Sequence; 192 const uint32_t Sequence;
191 const ItemKind Kind; 193 const ItemKind Kind;
192 std::unique_ptr<VariableDeclarationList> GlobalInits; 194 std::unique_ptr<VariableDeclarationList> GlobalInits;
193 std::unique_ptr<Assembler> Function; 195 std::unique_ptr<Assembler> Function;
194 std::unique_ptr<Cfg> RawFunc; 196 std::unique_ptr<Cfg> RawFunc;
195 }; 197 };
196 198
197 } // end of namespace Ice 199 } // end of namespace Ice
198 200
199 #endif // SUBZERO_SRC_ICETHREADING_H 201 #endif // SUBZERO_SRC_ICETHREADING_H
OLDNEW
« no previous file with comments | « src/IceGlobalContext.cpp ('k') | src/IceThreading.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698