This file is indexed.

/usr/include/NTL/Lazy.h is in libntl-dev 10.5.0-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/***************************************************************************


Lazy<T>: template class for lazy initialization of objects whose
values do not change after initialization.
In a multi-threaded environment, this makes use of "double checked locking"
for an efficient, thread-safe solution.

Usage:

   Lazy<T> obj; // declaration of the lazy object

    ...

   do {
      Lazy<T>::Builder builder(obj);
      if (!builder()) break; // if we are not building, the break out

      UniquePtr<T> p;        // create a pointer 

         ...

      builder.move(p);       // move p into the object to complete the initialization
                             // We can then complete the initialization process.
   } while(0);               // When this scope closes, the object is fully initialized.
                             // subsequent attempts to build the object will yield
                             // !builder.built()


   T objCopy = *obj;         // *obj returns a read-only reference
                             // one can also use -> operator

It is important to follow this recipe carefully.  In particular,
the builder must be enclosed in a scope, as it's destructor
plays a crucial role in finalizing the initialization.

NOTE: if p is null in builder.move(p), the object is still considered
built.


template<class T>
class Lazy {
public:
   Lazy();

   Lazy(const Lazy&);             // "deep" copies
   Lazy& operator=(const Lazy&);

   const T& operator*()  const;     // pointer access
   const T* operator->() const;
   const T* get() const;
   operator fake_null_type() const; // test for null pointer
   
   ~Lazy();

   kill();  // destroy and reset

   bool built() const; // test if already built




   class Builder {
      Builder(const Lazy&); 
     ~Builder()

      bool operator()() const; // test if we are building
      void move(UniquePtr<T>&);

   };
   


****************************************************************************/

#ifndef NTL_Lazy__H
#define NTL_Lazy__H


#include <NTL/tools.h>
#include <NTL/SmartPtr.h>
#include <NTL/thread.h>


NTL_OPEN_NNS



// NOTE: For more on double-checked locking, see
// http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/

// NOTE: when compiled with the NTL_THREADS option, the Lazy
// class may contain data members from the standard library
// that may not satisfy the requirements of the Vec class
// (i.e., relocatability).  One can wrap it in a pointer 
// class (e.g., OptionalVal) to deal with this.

template<class T, class P=DefaultDeleterPolicy>
class Lazy {
private:
   /* we make data members mutable so that Lazy members of
      other classes don't have to be. */

   mutable AtomicBool initialized; 
   mutable MutexProxy mtx;

   mutable UniquePtr<T, P> data;


   class Dummy { };
   typedef void (Lazy::*fake_null_type)(Dummy) const;
   void fake_null_function(Dummy) const {}


public:
   Lazy() : initialized(false) { }

   // EXCEPTIONS: This always succeeds in killing the object
   void kill() 
   { 
      UniquePtr<T, P> tmp;
      tmp.swap(data);
      initialized = false;  
   }

   // This is provided for convenience for some legacy code.
   // It us up to the client code to ensure there are no race conditions.

   // EXCEPTIONS: strong ES 
   Lazy& operator=(const Lazy& other) 
   {
      if (this == &other) return *this;

      if (other.initialized) {
         UniquePtr<T, P> p;
         if (other.data) p.make(*other.data);
         p.swap(data);
         initialized = true;
      }
      else
         kill();

      return *this;
   }
   
   Lazy(const Lazy& other) : initialized(false)
   {
      *this = other;
   }

   const T& operator*()  const { return *data; }
   const T* operator->() const { return data.operator->(); }
   const T* get() const { return data.get(); }

   bool built()  const { return initialized; }

   operator fake_null_type() const 
   {
      return data ?  &Lazy::fake_null_function : 0;
   }


   class Builder {
   private:
      bool building;
      bool moved;
      const Lazy& ref;
      GuardProxy guard;

      Builder(const Builder&); // disabled
      void operator=(const Builder&); // disabled



   public:
      Builder(const Lazy& _ref) : building(false), moved(false),
                                  ref(_ref), guard(_ref.mtx)
      {
         // Double-checked locking
         if (ref.initialized || (guard.lock(), ref.initialized)) 
            return;

         building = true; // we set this to true after we lock the mutex
                          // and see the the object is still uninitialized
      }

      ~Builder() { if (moved) ref.initialized = true; }

      void move(UniquePtr<T, P>& p) 
      {
         if (!building || moved) LogicError("Lazy::Builder illegal call to move");
         ref.data.move(p); 
         moved = true; 
      }

      bool operator()()  const { return building; }
   };
};

// NOTE: Lazy's are non-relocatable


NTL_CLOSE_NNS


#endif