Skip to content

File GCSynch.h

File List > include > SpinGenApi > GCSynch.h

Go to the documentation of this file

//=============================================================================
// Copyright (c) 2026 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved.
//
// This software is the confidential and proprietary information of FLIR
// Integrated Imaging Solutions, Inc. ("Confidential Information"). You
// shall not disclose such Confidential Information and shall use it only in
// accordance with the terms of the license agreement you entered into
// with FLIR Integrated Imaging Solutions, Inc. (FLIR).
//
// FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
// SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES
// SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
// THIS SOFTWARE OR ITS DERIVATIVES.
//=============================================================================

#ifndef SPINNAKER_GENAPI_GCSYNCH_H
#define SPINNAKER_GENAPI_GCSYNCH_H

#include "GCTypes.h"
#include "GCString.h"

#if defined(_WIN32)
#include <windows.h>
#include <winbase.h>
#elif defined(__GNUC__) && (defined(__linux__) || defined(__APPLE__))
#include <semaphore.h>
#include <pthread.h>
#include <errno.h>
#include <list>
#elif defined(VXWORKS)
#include <vxworks.h>
#include <taskLib.h>
#else
#error No/unknown platform thread support
#endif

namespace Spinnaker
{
    namespace GenICam
    {
        //-----------------------------------------------------------------
        // CLock
        //-----------------------------------------------------------------

        class SPINNAKER_API CLock
        {
          public:
            CLock();

            ~CLock();

            bool TryLock();

            void Lock();

            void Unlock();

          private:
            CLock(const CLock&);

            CLock& operator=(const CLock&);

          protected:
#if defined(_WIN32)
            CRITICAL_SECTION m_csObject;
#elif defined(__GNUC__) && (defined(__linux__) || defined(__APPLE__))
            pthread_mutex_t m_mtxObject;
#elif defined(VXWORKS)
            SEM_ID m_sem;
#else
#error No/unknown platform thread support
#endif
        };

        class SPINNAKER_API CLockEx : public CLock
        {
          public:
#if defined(_WIN32)
            int64_t GetLockCount();

            int64_t GetRecursionCount();

#elif defined(__GNUC__) && (defined(__linux__) || defined(__APPLE__) || defined(VXWORKS))
            // nothing implemented for Unix
#else
#error No/unknown platform support
#endif

          private:
            CLockEx(const CLockEx&);

            CLockEx& operator=(const CLockEx&);
        };

        //-----------------------------------------------------------------
        // AutoLock
        //-----------------------------------------------------------------
        class AutoLock
        {
            CLock& m_Lock;

          public:
            AutoLock(CLock& lock) : m_Lock(lock)
            {
                m_Lock.Lock();
            }

            ~AutoLock()
            {
                m_Lock.Unlock();
            }

          private:
            AutoLock& operator=(const AutoLock&);
            AutoLock(const AutoLock&);
        };

        //-----------------------------------------------------------------
        // template LockableObject<Object,ThreadingModel>
        //-----------------------------------------------------------------

        template <class Object> class LockableObject
        {
          public:
            mutable CLock m_Lock;

            class Lock;
            friend class Lock;

            class Lock
            {
                const LockableObject<Object>& m_Object;

              public:
                Lock(const LockableObject<Object>& obj) : m_Object(obj)
                {
                    m_Object.m_Lock.Lock();
                }

                ~Lock()
                {
                    m_Object.m_Lock.Unlock();
                }

              private:
                Lock& operator=(const Lock&);
            };

            Lock GetLock() const
            {
                return Lock(*this);
            }
        };

        class SPINNAKER_API CGlobalLock
        {
          public:
            explicit CGlobalLock(const char* pszName);
#if defined(_WIN32) && !defined(PHARLAP_WIN32)
            explicit CGlobalLock(const wchar_t* pszName);
#endif
            explicit CGlobalLock(const gcstring& strName);

            ~CGlobalLock();

          public:
            bool IsValid(void) const;

            bool Lock(unsigned int timeout_ms);

            bool TryLock(void);

            void Unlock(void);

#if defined(__GNUC__) && (defined(__linux__) || defined(__APPLE__))
            // creates a hashed name instead of the real name
            void HashSemName(const gcstring& strName);
#endif

          protected:
#if defined(_WIN32)
            HANDLE m_handle;
#elif defined(__GNUC__) && (defined(__linux__) || defined(__APPLE__))
            gcstring m_semName;
            sem_t* m_handle;
#elif VXWORKS
            // There are no named locks on VxWorks. While we could use a single global lock, we
            // will just rely on the caller to add their own locking in
#else
#error No/unknown platform thread support
#endif

            // This is for debugging/assertions only
            // the d'tor check whether this is 0 in debug builds
            // in release builds this is always 0
            mutable long m_DebugCount;

          private:
            // not copyable
            CGlobalLock(const CGlobalLock&);
            CGlobalLock& operator=(const CGlobalLock&);
        };

        //-----------------------------------------------------------------
        // unlocks the global lock object on destruction
        // this is for automatic UNLOCKING only.
        // we can't do automatic locking here since we don't get a returnvalue from the c'tor
        //-----------------------------------------------------------------
        class SPINNAKER_API CGlobalLockUnlocker
        {
          protected:
            CGlobalLock& m_Lock;
            bool m_enabled;

          public:
            CGlobalLockUnlocker(CGlobalLock& lock)
                : m_Lock(lock),
                  m_enabled(true) // this allows the auto unlock to be turned off for messy code structures
            {
                // explicitly don't lock the object here since we want to do this manually and handle the return value
                // properly
            }

            ~CGlobalLockUnlocker()
            {
                UnlockEarly();
            }

            void UnlockEarly(void)
            {
                if (m_enabled)
                {
                    m_enabled = false;
                    m_Lock.Unlock();
                }
            }

          private:
            CGlobalLockUnlocker& operator=(const CGlobalLockUnlocker&);
            CGlobalLockUnlocker(const CGlobalLockUnlocker&);
        };

    } // namespace GenICam
} // namespace Spinnaker

#endif // SPINNAKER_GENAPI_GCSYNCH_H