    // Copyright (C) 2005  Davis E. King (davis@dlib.net)
    // License: Boost Software License   See LICENSE.txt for the full license.
    #undef DLIB_RMUTEX_EXTENSIOn_ABSTRACT_
    #ifdef DLIB_RMUTEX_EXTENSIOn_ABSTRACT_

    #include "threads_kernel_abstract.h"

    namespace dlib
    {

    // ----------------------------------------------------------------------------------------

        class rmutex
        {
            /*!
                INITIAL VALUE
                    rmutex is in the unlocked state

                WHAT THIS OBJECT REPRESENTS
                    This object represents a recursive mutex intended to be used for synchronous
                    thread control of shared data. When a thread wants to access some
                    shared data it locks out other threads by calling lock() and calls
                    unlock() when it is finished.

                    The difference between this and the normal mutex object is that it is safe to
                    call lock() from a thread that already has a lock on this mutex.  Doing
                    so just increments a counter but otherwise has no effect on the mutex.
                    Note that unlock() must be called for each call to lock() to release the
                    mutex.
            !*/
        public:

            rmutex (
            );
            /*!
                ensures
                    - #*this is properly initialized
                throws
                    - dlib::thread_error
                        the constructor may throw this exception if there is a problem
                        gathering resources to create the rmutex.
            !*/

            ~rmutex (
            );
            /*!
                requires
                    - *this is not locked
                ensures
                    - all resources allocated by *this have been freed
            !*/

            unsigned long lock_count (
            ) const;
            /*!
                requires
                    - the calling thread has a lock on this mutex
                ensures
                    - returns the number of times the thread has called lock()
            !*/

            void lock (
                unsigned long times = 1
            ) const;
            /*!
                ensures
                    - if (*this is currently locked by another thread) then
                        - the thread that called lock() on *this is put to sleep until
                          it becomes available.
                        - #lock_count() == times
                    - if (*this is currently unlocked) then
                        - #*this becomes locked and the current thread is NOT put to sleep
                          but now "owns" #*this
                        - #lock_count() == times
                    - if (*this is locked and owned by the current thread) then
                        - the calling thread retains its lock on *this and isn't put to sleep.
                        - #lock_count() == lock_count() + times
            !*/

            void unlock (
                unsigned long times = 1
            ) const;
            /*!
                ensures
                    - if (*this is currently locked and owned by the thread calling unlock) then
                        - if (lock_count() <= times ) then
                            - #*this is unlocked (i.e. other threads may now lock this object)
                        - else
                            - #*this will remain locked
                            - #lock_count() == lock_count() - times
                    - else
                        - the call to unlock() has no effect
            !*/

        private:
            // restricted functions
            rmutex(rmutex&);        // copy constructor
            rmutex& operator=(rmutex&);    // assignment operator
        };

    // ----------------------------------------------------------------------------------------

    }

    #endif // DLIB_RMUTEX_EXTENSIOn_ABSTRACT_