1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #ifndef SQUID_BASE_HERE_H
10 #define SQUID_BASE_HERE_H
11 
12 #include <iosfwd>
13 
14 /// source code location of the caller
15 #define Here() SourceLocation(__FUNCTION__, __FILE__, __LINE__)
16 
17 /// semi-uniquely identifies a source code location; stable across Squid runs
18 typedef uint32_t SourceLocationId;
19 
20 /// returns a hash of a file name
21 typedef SourceLocationId FileNameHasher(const char *fileName);
22 
23 /// a caching proxy for `hasher` results
24 typedef SourceLocationId FileNameHashCacher(const char *fileName, FileNameHasher hasher);
25 
26 static FileNameHashCacher UnitFileNameHashCacher;
27 
28 /// a source code location that is cheap to create, copy, and store
29 class SourceLocation
30 {
31 public:
SourceLocation(const char * aContext,const char * aFileName,const int aLineNo)32     SourceLocation(const char *aContext, const char *aFileName, const int aLineNo):
33         context(aContext),
34         fileName(aFileName),
35         lineNo(aLineNo),
36         fileNameHashCacher(&UnitFileNameHashCacher)
37     {}
38 
39     /// \returns our location identifier
40     SourceLocationId id() const;
41 
42     /// describes location using a compact but human-friendly format
43     std::ostream &print(std::ostream &os) const;
44 
45     const char *context; ///< line-independent location description
46     const char *fileName; ///< source file name, often relative to build path
47     int lineNo; ///< line number inside the source file name (if positive)
48 
49 private:
50     SourceLocationId calculateId(FileNameHasher) const;
51     FileNameHashCacher *fileNameHashCacher;
52 };
53 
54 inline std::ostream &
55 operator <<(std::ostream &os, const SourceLocation &location)
56 {
57     return location.print(os);
58 }
59 
60 /// SourceLocation::id() speed optimization hack: Caches `hasher` results. The
61 /// cache capacity is one filename hash. Each translation unit gets one cache.
62 static SourceLocationId
UnitFileNameHashCacher(const char * fileName,FileNameHasher hasher)63 UnitFileNameHashCacher(const char *fileName, FileNameHasher hasher)
64 {
65     static SourceLocationId cachedHash = 0;
66     static const char *hashedFilename = 0;
67     // Each file #included in a translation unit has its own __FILE__ value.
68     // Keep the cache fresh (and the result correct).
69     if (hashedFilename != fileName) { // cheap pointer comparison
70         hashedFilename = fileName;
71         cachedHash = hasher(fileName);
72     }
73     return cachedHash;
74 }
75 
76 #endif
77 
78