This file is indexed.

/usr/include/osgEarth/ThreadingUtils is in libosgearth-dev 2.9.0+dfsg-1.

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
/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
 * Copyright 2016 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
#ifndef OSGEARTH_THREADING_UTILS_H
#define OSGEARTH_THREADING_UTILS_H 1

#include <osgEarth/Common>
#include <OpenThreads/Condition>
#include <OpenThreads/Mutex>
#include <OpenThreads/Thread>
#include <osg/ref_ptr>
#include <set>
#include <map>

#define USE_CUSTOM_READ_WRITE_LOCK 1

namespace osgEarth { namespace Threading
{   
    typedef OpenThreads::Mutex Mutex;
    typedef OpenThreads::ScopedLock<OpenThreads::Mutex> ScopedMutexLock;
    typedef OpenThreads::Thread Thread;

    /**
     * Gets the unique ID of the running thread. Use this instead of
     * OpenThreads::Thread::CurrentThread, which only works reliably on
     * threads created with the OpenThreads framework
     */
    extern OSGEARTH_EXPORT unsigned getCurrentThreadId();



    /**
     * Event with a binary signaled state, for multi-threaded sychronization.
     *
     * The event has two states:
     *  "set" means that a call to wait() will not block;
     *  "unset" means that calls to wait() will block until another thread calls set().
     *
     * The event starts out unset. 
     *
     * Typical usage: Thread A creates Thread B to run asynchronous code. Thread A
     * then calls wait(), which blocks Thread A. When Thread B is finished, it calls
     * set(). Thread A then wakes up and continues execution.
     */
    class OSGEARTH_EXPORT Event 
    {
    public:
        //! Construct a new event
        Event();

        //! DTOR
        ~Event();

        //! Block until the event is set, then return true if set, false on error.
        bool wait();

        //! Like wait(), but also returns false on timeout.
        bool wait(unsigned timeout_ms);

        //! Like wait(), but resets the state before returning.
        bool waitAndReset();

        //! Set the event state, causing any waiters to unblock.
        void set();

        //! Reset (unset) the event state; new waiters will block until set() is called.
        void reset();

        //! Whether the event state is set (waiters will not block).
        inline bool isSet() const { return _set; }

    protected:
        OpenThreads::Mutex _m;
        OpenThreads::Condition _cond;
        bool _set;
    };

    /** Wraps an Event in a Referenced. */
    class OSGEARTH_EXPORT RefEvent : public Event, public osg::Referenced
    {
    };

    /**
     * Same as Event, but set() must be called N times before unblocking
     * waiting thread(s).
     */
    class OSGEARTH_EXPORT MultiEvent 
    {
    public:
        //! Construct a multi-event with the number of setters.
        MultiEvent(int num =1);

        //! DTOR
        ~MultiEvent();

        //! Block the calling thread until all N set()s are called.
        bool wait();

        //! Same as wait(), but resets the state after returning.
        bool waitAndReset();

        //! Adds one signal to the event; when all signals are set, waiters will unblock.
        void set();
        void notify() { set(); }

        //! Resets the state.
        void reset();

    protected:
        OpenThreads::Mutex _m;
        OpenThreads::Condition _cond;
        int _set, _num;
    };

    /**
     * Future is the consumer-side interface to an asynchronous operation.
     *
     * Usage: 
     *   Producer (usually an asynchronous function call) creates a Promise<Object>
     *   and immediately returns promise.getFuture(). The Consumer then performs other
     *   work, and eventually (or immediately) called Future.get() or Future.release().
     *   Either call will block until the asynchronous operation is complete and the
     *   result in Future is available.
     */
    template<typename T>
    class Future
    {
    private:
        // internal structure to track referenced to the result
        struct RefPtrRef : public osg::Referenced {
            RefPtrRef(T* obj = 0L) : _obj(obj) { }
            osg::ref_ptr<T> _obj;
        };

    public:
        //! Blank CTOR
        Future() {
            _ev = new RefEvent();
            _objRef = new RefPtrRef();
        }

        //! Copy CTOR
        Future(const Future& rhs) : _ev(rhs._ev), _objRef(rhs._objRef.get()) { }

        //! True if the promise was resolved and a result if available.
        bool isAvailable() const {
            return _ev->isSet();
        }

        //! True if the Promise that generated this Future no longer exists.
        bool isAbandoned() const {
            return _objRef->referenceCount() == 1;
        }

        //! The result value; blocks until it is available (or abandonded) and then returns it.
        T* get() {
            while(!_ev->wait(1000u))
                if (isAbandoned()) return 0L;
            return _objRef->_obj.get();
        }

        //! The result value; blocks until available (or abandoned) and returns it; then resets to initial state.
        T* release() {
            while(!_ev->wait(1000u))
                if (isAbandoned()) return 0L;
            T* out = _objRef->_obj.release();
            _ev->reset();
            return out;
        }

    private:
        osg::ref_ptr<RefEvent> _ev;
        osg::ref_ptr<RefPtrRef> _objRef;
        template<typename U> friend class Promise;
    };
    
    /**
     * Promise is the producer-side interface to an asynchronous operation.
     *
     * Usage: The code that initiates an asychronous operation creates a Promise
     *   object, dispatches the asynchronous code, and immediately returns 
     *   Promise.getFuture(). The caller can then call future.get() to block until
     *   the result is available.
     */
    template<typename T>
    class Promise
    {
    public:
        //! This promise's future result.
        const Future<T> getFuture() const { return _future; }

        //! Resolve (fulfill) the promise with the provided result value.
        void resolve(T* value) {
            _future._objRef->_obj = value;
            _future._ev->set();
        }

        //! True if the promise is resolved and the Future holds a valid result.
        bool isResolved() const {
            return _future._ev->isSet();
        }

        //! True is there are no Future objects waiting on this Promise.
        bool isAbandoned() const {
            return _future._objRef->referenceCount() == 1;
        }

    private:
        Future<T> _future;
    };
    
#ifdef USE_CUSTOM_READ_WRITE_LOCK

    /**
     * Custom read/write lock. The read/write lock in OSG can unlock mutexes from a different
     * thread than the one that locked them - this can hang the thread in Windows.
     *
     * Adapted from:
     * http://www.codeproject.com/KB/threads/ReadWriteLock.aspx
     */
    class OSGEARTH_EXPORT ReadWriteMutex
    {
    public:
        //! Construct a read/write mutex.
        ReadWriteMutex();

        //! Lock for reading. Multiple threads can take a read lock simultaneously.
        void readLock();

        //! Unlock for reading.
        void readUnlock();

        //! Lock for writing. This is exclusive; no other read OR write locks may be taken.
        void writeLock();

        //! Release a write lock.
        void writeUnlock();

    protected:

        void incrementReaderCount();
        void decrementReaderCount();

    private:
        int    _readerCount;
        Mutex  _lockWriterMutex;
        Mutex  _readerCountMutex;
        Event  _noWriterEvent;
        Event  _noReadersEvent;
    };


    struct ScopedWriteLock
    {
        ScopedWriteLock( ReadWriteMutex& lock ) : _lock(lock) { _lock.writeLock(); }
        ~ScopedWriteLock() { _lock.writeUnlock(); }
    protected:
        ReadWriteMutex& _lock;
    };

    struct ScopedReadLock
    {
        ScopedReadLock( ReadWriteMutex& lock ) : _lock(lock) { _lock.readLock(); }
        ~ScopedReadLock() { _lock.readUnlock(); }
    protected:
        ReadWriteMutex& _lock;
    };

#else

    typedef OpenThreads::ReadWriteMutex  ReadWriteMutex;
    typedef OpenThreads::ScopedWriteLock ScopedWriteLock;
    typedef OpenThreads::ScopedReadLock  ScopedReadLock;

#endif

} } // namepsace osgEarth::Threading


#endif // OSGEARTH_THREADING_UTILS_H