Robert,

On Monday 23 June 2008 11:50, Robert Osfield wrote:
> I haven't done the background work on CMake/Config files so I have to
> defer to your experience with this.  In terms of what makes sense as a
> layman, to me having headers lists as headers along with the rest of
> the headers seems logical.  Having extra headers "automagically" be
> added to the header list is less intuitive.
Well, these are not traditional headers in the source file sense. Because of 
this files not being available at configure time. Files  not available at 
configuration time are usually treated in a different way. You can observe 
this with most build/configuration systems.
So, special needs  - special treatment ...

> As a test I've put a # in front of the INSTALL_FILES directive for the
> two Config files, this works fine, removing the double install.  I've
> now checked in this tweak.
>
> The open question for me, is does the config setup code automatically
> put the headers into the OpenThreads_PUBLIC_HEADERS and
> LIB_PUBLIC_HEADERS?  If it does then my own additions would break
> this, but I kinda doubt this is happening as otherwise the
> INSTALL_FILES directive you added wouldn't have been required.

Hmm, Ok, I begin to see what you are aiming to.
Sorry, I should have read better what you write.
Additionally I have looked into the win32/win64 stuff we had offlist today 
morning, changes attached.

IMO, this config file should *not* appear in any IDE project source file list, 
even if it is included by many files it is not a source file that should be 
changed. The source of what is in there is the cmake configured stuff in 
cmake's cache.

- Having that file in the project file list would make me assume that I can 
edit this file. Ok, I *can* edit, but I cannot rely on such changes to be 
persistent, since cmake might overwrite that file at the next time cmake 
runs...
So, I believe that it is better to not present that file by default to an IDE 
user ...
If you want to have this config file changed in a persistent way, you need to 
run cmake or ccmake - don't point a user to the wrong config file.

- Setting the include path is sufficient to make the compiler find this file - 
you do not need a source file entry in the IDE project file for that.
... At least for msvc. Is this true for oither ide's too?

Open questions:
I do not know what happens with build dependencies, but I hope and still 
assume that these are found by an other mechanism than specifying them by 
hand.
I also do not know what happens with apples build system here.

BTW: I believe we sould add some
// Automatically created by cmake - do not edit ... [and so on]
to that Config.in files to warn the user that this file should not be changed 
directly.

I still believe that it's better to do what I have provided. But leave it the 
way it is if you want to - it appears to work.

Anyway, different topic: fixed win32/win64 configure check and win32/win64 
atomic related compile failures with msvs2005. Attached changes to make win32 
really use the atomic stuff. There are pointer typecast problems and some 
historic alignment restrictions that I just took from a previous similar 
implementation of mine without looking deep enough. Change is on top of rev 
8487.

Other compile fixes for win32 pending ...

GReetings
 Mathias

-- 
Dr. Mathias Fröhlich, science + computing ag, Software Solutions
Hagellocher Weg 71-75, D-72070 Tuebingen, Germany
Phone: +49 7071 9457-268, Fax: +49 7071 9457-511
-- 
Vorstand/Board of Management:
Dr. Bernd Finkbeiner, Dr. Florian Geyer,
Dr. Roland Niemeier, Dr. Arno Steitz, Dr. Ingrid Zech
Vorsitzender des Aufsichtsrats/
Chairman of the Supervisory Board:
Prof. Dr. Hanns Ruder
Sitz/Registered Office: Tuebingen
Registergericht/Registration Court: Stuttgart
Registernummer/Commercial Register No.: HRB 382196 

# Check for availability of atomic operations 
# This module defines
# OPENTHREADS_HAVE_ATOMIC_OPS

INCLUDE(CheckCXXSourceRuns)

# Do step by step checking, 
CHECK_CXX_SOURCE_RUNS("
#include <cstdlib>

int main()
{
#ifdef __i386__
   // Bad, gcc behaves dependent on the compilers -march=... flags.
   // Since the osg::Referenced stuff is code distributed in headers, it is
   // unclear if we will have this feature available at compile time of the
   // headers. So just do not use this feature for 32 bit code.
   // May be we can implement around that limitation at some time..
   return EXIT_FAILURE;
#else
   unsigned value = 0;
   void* ptr = &value;
   __sync_add_and_fetch(&value, 1);
   __sync_synchronize();
   __sync_sub_and_fetch(&value, 1);
   if (!__sync_bool_compare_and_swap(&value, 0, 1))
      return EXIT_FAILURE;
   
   if (!__sync_bool_compare_and_swap(&ptr, ptr, ptr))
      return EXIT_FAILURE;

   return EXIT_SUCCESS;
#endif
}
" _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)

CHECK_CXX_SOURCE_RUNS("
#include <cstdlib>

int main(int, const char**)
{
   unsigned value = 0;
   void* ptr = &value;
   __add_and_fetch(&value, 1);
   __synchronize(value);
   __sub_and_fetch(&value, 1);
   if (!__sync_compare_and_swap(&value, 0, 1))
      return EXIT_FAILURE;
   
   if (!__sync_compare_and_swap(&ptr, ptr, ptr))
      return EXIT_FAILURE;

   return EXIT_SUCCESS;
}
" _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)

CHECK_CXX_SOURCE_RUNS("
#include <atomic.h>
#include <cstdlib>

int main(int, const char**)
{
   uint_t value = 0;
   void* ptr = &value;
   atomic_inc_uint_nv(&value);
   membar_consumer();
   atomic_dec_uint_nv(&value);
   if (0 != atomic_cas_uint(&value, 0, 1))
      return EXIT_FAILURE;
   
   if (ptr != atomic_cas_ptr(&ptr, ptr, ptr))
      return EXIT_FAILURE;

   return EXIT_SUCCESS;
}
" _OPENTHREADS_ATOMIC_USE_SUN)

CHECK_CXX_SOURCE_RUNS("
#include <windows.h>
#include <cstdlib>

int main(int, const char**)
{
   volatile long value = 0;
   long data = 0;
   long* volatile ptr = &data;

   InterlockedIncrement(&value);
   InterlockedDecrement(&value);

   if (0 != InterlockedCompareExchange(&value, 1, 0))
      return EXIT_FAILURE;

   if (ptr != InterlockedCompareExchangePointer((PVOID volatile*)&ptr, (PVOID)ptr, (PVOID)ptr))
      return EXIT_FAILURE;

   return EXIT_SUCCESS;
}
" _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)

IF(NOT _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_SUN AND NOT _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
  SET(_OPENTHREADS_ATOMIC_USE_MUTEX)
ENDIF(NOT _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_SUN AND NOT _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
/* -*-c++-*- OpenThreads library, Copyright (C) 2008  The Open Thread Group
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library 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 
 * OpenSceneGraph Public License for more details.
*/

#ifndef _OPENTHREADS_ATOMIC_
#define _OPENTHREADS_ATOMIC_

#include <OpenThreads/Config>

#if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
# include <windows.h>
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
# include <atomic.h>
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
# include "Mutex"
# include "ScopedLock"
#endif

namespace OpenThreads {

/**
 *  @class Atomic
 *  @brief  This class provides an atomic increment and decrement operation.
 */
class Atomic {
 public:
    Atomic(unsigned value = 0) : _value(value)
    { }
    unsigned operator++()
    {
#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
        return __sync_add_and_fetch(&_value, 1);
#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
        return __add_and_fetch(&_value, 1);
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
        return atomic_inc_uint_nv(&_value);
#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
        return InterlockedIncrement(&_value);
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
        ScopedLock<Mutex> lock(_mutex);
        return ++_value;
#else
        return ++_value;
#endif
    }
    unsigned operator--()
    {
#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
        return __sync_sub_and_fetch(&_value, 1);
#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
        return __sub_and_fetch(&_value, 1);
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
        return atomic_dec_uint_nv(&_value);
#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
        return InterlockedDecrement(&_value);
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
        ScopedLock<Mutex> lock(_mutex);
        return --_value;
#else
        return --_value;
#endif
    }
    operator unsigned() const
    {
#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
        __sync_synchronize();
        return _value;
#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
        __synchronize(_value);
        return _value;
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
        membar_consumer(); // Hmm, do we need???
        return _value;
#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
        return static_cast<unsigned const volatile &>(_value);
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
        ScopedLock<Mutex> lock(_mutex);
        return _value;
#else
        return _value;
#endif
    }
    
 private:

    Atomic(const Atomic&);
    Atomic& operator=(const Atomic&);
    
#if defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
    mutable Mutex _mutex;
#endif
#if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
    volatile long _value;
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
    volatile uint_t _value;
#else
    volatile unsigned _value;
#endif
};

/**
 *  @class AtomicPtr
 *  @brief  This class provides an atomic pointer assignment using cas operations.
 */
template<typename T>
class AtomicPtr {
public:
    AtomicPtr(T* ptr = 0) : _ptr(ptr)
    { }
    ~AtomicPtr()
    { _ptr = 0; }

    // assigns a new pointer
    bool assign(T* ptrNew, const T* const ptrOld)
    {
#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
        return __sync_bool_compare_and_swap(&_ptr, ptrOld, ptrNew);
#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
        return __compare_and_swap(&_ptr, ptrOld, ptrNew);
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
        return ptrOld == atomic_cas_ptr(&_ptr, ptrOld, ptrNew);
#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
        return ptrOld == InterlockedCompareExchangePointer((PVOID volatile*)&_ptr, (PVOID)ptrNew, (PVOID)ptrOld);
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
        ScopedLock<Mutex> lock(_mutex);
        if (_ptr != ptrOld)
            return false;
        _ptr = ptrNew;
        return true;
#else
        if (_ptr != ptrOld)
            return false;
        _ptr = ptrNew;
        return true;
#endif
    }

    T* get() const
    {
#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
        __sync_synchronize();
        return _ptr;
#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
        __synchronize(_ptr);
        return _ptr;
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
        membar_consumer(); // Hmm, do we need???
        return _ptr;
#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
        return _ptr;
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
        ScopedLock<Mutex> lock(_mutex);
        return _ptr;
#else
        return _ptr;
#endif
    }

private:
    AtomicPtr(const AtomicPtr&);
    AtomicPtr& operator=(const AtomicPtr&);

#if defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
    mutable Mutex _mutex;
#endif
    T* volatile _ptr;
};

}

#endif // _OPENTHREADS_ATOMIC_
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to