This file is indexed.

/usr/include/oce/OSD_Parallel.hxx is in liboce-foundation-dev 0.18.2-2build1.

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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
// Copyright (c) 2013-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.

#ifndef OSD_Parallel_HeaderFile
#define OSD_Parallel_HeaderFile

#include <OSD_Thread.hxx>
#include <Standard_Mutex.hxx>
#include <Standard_NotImplemented.hxx>
#include <Standard_Atomic.hxx>
#include <NCollection_Array1.hxx>

#ifdef HAVE_TBB
#include <tbb/parallel_for.h>
#include <tbb/parallel_for_each.h>
#include <tbb/blocked_range.h>
#endif

//! @class OSD_Parallel
//! @brief Simplifies code parallelization.
//!
//! The Class provides an interface of parallel processing "for" and "foreach" loops.
//! These primitives encapsulates complete logic for creating and managing parallel context of loops.
//! Moreover the primitives may be a wrapper for some primitives from 3rd-party library - TBB.
//! To use it is necessary to implement TBB like interface which is based on functors.
//!
//! @code
//! class Functor
//! {
//! public:
//!   void operator() ([proccesing instance]) const
//!   {
//!     //...
//!   }
//! };
//! @endcode
//!
//! In the body of the operator () should be implemented thread-safe logic of computations that can be performed in parallel context.
//! If parallelized loop iterates on the collections with direct access by index (such as Vector, Array),
//! it is more efficient to use the primitive ParallelFor (because it has no critical section).
class OSD_Parallel
{
  //! Auxiliary class which ensures exclusive
  //! access to iterators of processed data pool.
  template <typename Value>
  class Range
  {
  public: //! @name public methods

    typedef Value Iterator;

    //! Constructor
    Range(const Value& theBegin, const Value& theEnd)
    : myBegin(theBegin),
      myEnd  (theEnd),
      myIt   (theBegin)
    {
    }

    //! Returns const link on the first element.
    inline const Value& Begin() const
    {
      return myBegin;
    }

    //! Returns const link on the last element.
    inline const Value& End() const
    {
      return myEnd;
    }

    //! Returns first non processed element or end.
    //! Thread-safe method.
    inline Iterator It() const
    {
      Standard_Mutex::Sentry aMutex( myMutex );
      return ( myIt != myEnd ) ? myIt++ : myEnd;
    }

  private: //! @name private methods

    //! Empty copy constructor
    Range(const Range& theCopy);

    //! Empty copy operator.
    Range& operator=(const Range& theCopy);

  private: //! @name private fields

    const Value&           myBegin; //!< Fisrt element of range.
    const Value&           myEnd;   //!< Last element of range.
    mutable Value          myIt;    //!< First non processed element of range.
    mutable Standard_Mutex myMutex; //!< Access controller for the first non processed element.
  };

  //! Auxiliary wrapper class for thread function.
  template <typename Functor, typename InputIterator>
  class Task
  {
  public: //! @name public methods

    //! Constructor.
    Task(const Functor& thePerformer, Range<InputIterator>& theRange)
    : myPerformer(thePerformer),
      myRange    (theRange)
    {
    }

    //! Method is executed in the context of thread,
    //! so this method defines the main calculations.
    static Standard_Address RunWithIterator(Standard_Address theTask)
    {
      Task<Functor, InputIterator>& aTask =
        *( static_cast< Task<Functor, InputIterator>* >(theTask) );

      const Range<InputIterator>& aData( aTask.myRange );
      typename Range<InputIterator>::Iterator i = aData.It();

      for ( ; i != aData.End(); i = aData.It() )
      {
        aTask.myPerformer(*i);
      }

      return NULL;
    }

    //! Method is executed in the context of thread,
    //! so this method defines the main calculations.
    static Standard_Address RunWithIndex(Standard_Address theTask)
    {
      Task<Functor, InputIterator>& aTask =
        *( static_cast< Task<Functor, Standard_Integer>* >(theTask) );

      const Range<Standard_Integer>& aData( aTask.myRange );
      Standard_Integer i = aData.It();

      for ( ; i < aData.End(); i = aData.It())
      {
        aTask.myPerformer(i);
      }

      return NULL;
    }

  private: //! @name private methods

    //! Empty copy constructor.
    Task(const Task& theCopy);

    //! Empty copy operator.
    Task& operator=(const Task& theCopy);

  private: //! @name private fields

    const Functor&              myPerformer; //!< Link on functor.
    const Range<InputIterator>& myRange;     //!< Link on processed data block.
  };

public: //! @name public methods

  //! Returns number of logical proccesrs.
  Standard_EXPORT static Standard_Integer NbLogicalProcessors();

  //! Simple primitive for parallelization of "foreach" loops.
  template <typename InputIterator, typename Functor>
  static void ForEach( InputIterator  theBegin,
                       InputIterator  theEnd,
                       const Functor& theFunctor,
                       const Standard_Boolean isForceSingleThreadExecution
                         = Standard_False );

  //! Simple primitive for parallelization of "for" loops.
  template <typename Functor>
  static void For( const Standard_Integer theBegin,
                   const Standard_Integer theEnd,
                   const Functor&         theFunctor,
                   const Standard_Boolean isForceSingleThreadExecution
                     = Standard_False );
};

//=======================================================================
//function : OSD_Parallel::Range::It
//purpose  : Template concretization.
//=======================================================================
template<> inline Standard_Integer OSD_Parallel::Range<Standard_Integer>::It() const
{
  return Standard_Atomic_Increment( reinterpret_cast<volatile int*>(&myIt) ) - 1;
}

//=======================================================================
//function : ParallelForEach
//purpose  : 
//=======================================================================
template <typename InputIterator, typename Functor>
void OSD_Parallel::ForEach( InputIterator          theBegin,
                            InputIterator          theEnd,
                            const Functor&         theFunctor,
                            const Standard_Boolean isForceSingleThreadExecution )
{
  if ( isForceSingleThreadExecution )
  {
    for ( InputIterator it(theBegin); it != theEnd; it++ )
      theFunctor(*it);

    return;
  }
  #ifdef HAVE_TBB
  {
    try
    {
      tbb::parallel_for_each(theBegin, theEnd, theFunctor);
    }
    catch ( tbb::captured_exception& anException )
    {
      Standard_NotImplemented::Raise(anException.what());
    }
  }
  #else
  {
    Range<InputIterator> aData(theBegin, theEnd);
    Task<Functor, InputIterator> aTask(theFunctor, aData);

    const Standard_Integer aNbThreads = OSD_Parallel::NbLogicalProcessors();
    NCollection_Array1<OSD_Thread> aThreads(0, aNbThreads - 1);

    for ( Standard_Integer i = 0; i < aNbThreads; ++i )
    {
      OSD_Thread& aThread = aThreads(i);
      aThread.SetFunction(&Task<Functor, InputIterator>::RunWithIterator);
      aThread.Run(&aTask);
    }

    for ( Standard_Integer i = 0; i < aNbThreads; ++i )
      aThreads(i).Wait();
  }
  #endif
}

//=======================================================================
//function : ParallelFor
//purpose  : 
//=======================================================================
template <typename Functor>
void OSD_Parallel::For( const Standard_Integer theBegin,
                        const Standard_Integer theEnd,
                        const Functor&         theFunctor,
                        const Standard_Boolean isForceSingleThreadExecution )
{
  if ( isForceSingleThreadExecution )
  {
    for ( Standard_Integer i = theBegin; i < theEnd; ++i )
      theFunctor(i);

    return;
  }
  #ifdef HAVE_TBB
  {
    try
    {
      tbb::parallel_for( theBegin, theEnd, theFunctor );
    }
    catch ( tbb::captured_exception& anException )
    {
      Standard_NotImplemented::Raise(anException.what());
    }
  }
  #else
  {
    Range<Standard_Integer> aData(theBegin, theEnd);
    Task<Functor, Standard_Integer> aTask(theFunctor, aData);

    const Standard_Integer aNbThreads = OSD_Parallel::NbLogicalProcessors();
    NCollection_Array1<OSD_Thread> aThreads(0, aNbThreads - 1);

    for ( Standard_Integer i = 0; i < aNbThreads; ++i )
    {
      OSD_Thread& aThread = aThreads(i);
      aThread.SetFunction(&Task<Functor, Standard_Integer>::RunWithIndex);
      aThread.Run(&aTask);
    }

    for ( Standard_Integer i = 0; i < aNbThreads; ++i )
      aThreads(i).Wait();
  }
  #endif
}

#endif