Skip to content

Commit 72961b8

Browse files
committed
Update comments to clarify the approach with two maps better
Signed-off-by: Mikhail Krinkin <[email protected]>
1 parent 25c2323 commit 72961b8

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

test/integration/fake_upstream.h

+20-8
Original file line numberDiff line numberDiff line change
@@ -263,21 +263,31 @@ class FakeStream : public Http::RequestDecoder,
263263

264264
protected:
265265
absl::Mutex lock_;
266-
// headers get updated in decodeHeaders() and accessed in headers() methods. Those methods can
267-
// be called from different threads, but we can rely on a few assumptions here:
266+
// Headers get updated in decodeHeaders() and accessed in headers() methods. Those methods can
267+
// be called from different threads, but we can rely on a few assumptions:
268268
//
269269
// 1. headers() method is only called from a single thread, which may or may not be different
270-
// from the thread that calls decodeHeaders
270+
// from the thread that calls decodeHeaders()
271271
// 2. headers can only be replaced completely - they are never modified in place.
272272
//
273273
// With those two assumptions, we can use a synchronization pattern with two header maps, that
274274
// allows us to return an unprotected reference to the clients from the headers() method. The
275-
// reason why we want to return an unprotected reference is because historically that's what the
276-
// interface of the FakeStream was, and over time we accumulated quite a few tests that rely on
277-
// that.
275+
// approach works as follows:
278276
//
279-
// With that in mind we made a decision to preserve the interface and avoid migrating multiple
280-
// tests to a new interface when we addressed Clang thread sanitizer warnings.
277+
// 1. When headers are updated in decodeHeaders(), we store them in the internal headers_ map
278+
// 2. When headers() is called, we check if the internal headers_ and external client_headers_
279+
// map point to different places, and if so, we update client_headers_ map to point to the
280+
// same map as internal headers_.
281+
//
282+
// Because both internal headers_ and client_headers_ are shared pointers, the map will stay
283+
// around as long as at least one of those pointers keeps a reference to the map and thus
284+
// the returned reference stay valid as well. And because headers() is only called from a single
285+
// thread, it's safe to return a reference to client_headers_ from headers() call.
286+
//
287+
// The reason why we want to return an unprotected reference is because historically that's what
288+
// the interface of the FakeStream::headers() was, and over time we accumulated quite a few tests
289+
// that rely on that. Changing the interface would require updating all the tests and we decided
290+
// not to do that.
281291
//
282292
// That's why we have both headers_ and client_headers_ map below.
283293
Http::RequestHeaderMapSharedPtr headers_ ABSL_GUARDED_BY(lock_);
@@ -286,6 +296,8 @@ class FakeStream : public Http::RequestDecoder,
286296

287297
private:
288298
Http::ResponseEncoder& encoder_;
299+
// See the comment for headers_ above that explains why we need both headers_ and
300+
// client_headers_.
289301
Http::RequestHeaderMapSharedPtr client_headers_;
290302
Http::RequestTrailerMapSharedPtr trailers_ ABSL_GUARDED_BY(lock_);
291303
bool end_stream_ ABSL_GUARDED_BY(lock_){};

0 commit comments

Comments
 (0)