// bslmt_muteximpl_pthread.h                                          -*-C++-*-
#ifndef INCLUDED_BSLMT_MUTEXIMPL_PTHREAD
#define INCLUDED_BSLMT_MUTEXIMPL_PTHREAD

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide a POSIX implementation of `bslmt::Mutex`.
//
//@CLASSES:
//  bslmt::MutexImpl<Platform::PosixThreads>: POSIX specialization
//
//@SEE_ALSO: bslmt_mutex
//
//@DESCRIPTION: This component provides an implementation of `bslmt::Mutex` for
// POSIX threads ("pthreads"), `bslmt::MutexImpl<Platform::PosixThreads>`, via
// the template specialization:
// ```
// bslmt::MutexImpl<Platform::PosixThreads>
// ```
// This template class should not be used (directly) by client code.  Clients
// should instead use `bslmt::Mutex`.
//
///Usage
///-----
// This component is an implementation detail of `bslmt` and is *not* intended
// for direct client use.  It is subject to change without notice.  As such, a
// usage example is not provided.

#include <bslscm_version.h>

#include <bslmt_platform.h>

#ifdef BSLMT_PLATFORM_POSIX_THREADS

// Platform-specific implementation starts here.

#include <bsls_assert.h>

#include <bsl_cstring.h>

#include <pthread.h>

namespace BloombergLP {
namespace bslmt {

template <class THREAD_POLICY>
class MutexImpl;

                 // =======================================
                 // class MutexImpl<Platform::PosixThreads>
                 // =======================================

/// This class provides a full specialization of `MutexImpl` for pthreads.
/// It provides a efficient proxy for the `pthread_mutex_t` pthreads type,
/// and related operations.  Note that the mutex implemented in this class
/// is *not* error checking, and is non-recursive.
template <>
class MutexImpl<Platform::PosixThreads> {

    // DATA
    pthread_mutex_t d_lock;  // TBD doc

    // NOT IMPLEMENTED
    MutexImpl(const MutexImpl&);
    MutexImpl& operator=(const MutexImpl&);

  public:
    // PUBLIC TYPES

    /// The underlying OS-level type.  Exposed so that other `bslmt`
    /// components can operate directly on this mutex.
    typedef pthread_mutex_t NativeType;

    // CREATORS

    /// Create a mutex initialized to an unlocked state.  This method does
    /// not return normally unless there are sufficient system resources to
    /// construct the object.
    MutexImpl();

    /// Destroy this mutex object.  The behavior is undefined if the mutex
    /// is in a locked state.
    ~MutexImpl();

    // MANIPULATORS

    /// Acquire a lock on this mutex object.  If this object is currently
    /// locked, then suspend execution of the current thread until a lock
    /// can be acquired.  Note that the behavior is undefined if the calling
    /// thread already owns the lock on this mutex, and will likely result
    /// in a deadlock.
    void lock();

    /// Return a reference to the modifiable OS-level mutex underlying this
    /// object.  This method is intended only to support other `bslmt`
    /// components that must operate directly on this mutex.
    NativeType& nativeMutex();

    /// Attempt to acquire a lock on this mutex object.  Return 0 on
    /// success, and a non-zero value of this object is already locked, or
    /// if an error occurs.
    int tryLock();

    /// Release a lock on this mutex that was previously acquired through a
    /// successful call to `lock`, or `tryLock`.  The behavior is undefined,
    /// unless the calling thread currently owns the lock on this mutex.
    void unlock();
};

// ============================================================================
//                             INLINE DEFINITIONS
// ============================================================================

                 // ---------------------------------------
                 // class MutexImpl<Platform::PosixThreads>
                 // ---------------------------------------

// CREATORS
inline
MutexImpl<bslmt::Platform::PosixThreads>::MutexImpl()
{
    const int status = pthread_mutex_init(&d_lock, 0);
    if (status) {
        BSLS_ASSERT_INVOKE_NORETURN("'pthread_mutex_init' failed");
    }
}

// MANIPULATORS
inline
void MutexImpl<bslmt::Platform::PosixThreads>::lock()
{
    BSLS_ASSERT_SAFE(0xdeadbeef !=
                                 *reinterpret_cast<const unsigned *>(&d_lock));

    const int status = pthread_mutex_lock(&d_lock);
    (void) status;
    BSLS_ASSERT_SAFE(0 == status);
}

inline
int MutexImpl<bslmt::Platform::PosixThreads>::tryLock()
{
    BSLS_ASSERT_SAFE(0xdeadbeef !=
                                 *reinterpret_cast<const unsigned *>(&d_lock));

    return pthread_mutex_trylock(&d_lock);
}

inline
void MutexImpl<bslmt::Platform::PosixThreads>::unlock()
{
    BSLS_ASSERT_SAFE(0xdeadbeef !=
                                 *reinterpret_cast<const unsigned *>(&d_lock));

    const int status = pthread_mutex_unlock(&d_lock);
    (void) status;
    BSLS_ASSERT_SAFE(0 == status);
}

inline
MutexImpl<bslmt::Platform::PosixThreads>::NativeType&
MutexImpl<bslmt::Platform::PosixThreads>::nativeMutex()
{
    return d_lock;
}

}  // close package namespace
}  // close enterprise namespace

#endif  // BSLMT_PLATFORM_POSIX_THREADS

#endif

// ----------------------------------------------------------------------------
// Copyright 2023 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
