|
Packit |
df99a1 |
/* -*- C -*-
|
|
Packit |
df99a1 |
// -------------------------------------------------------------------
|
|
Packit |
df99a1 |
// Atomic primitives
|
|
Packit |
df99a1 |
// Copyright (c) 2008 Leon Bottou. All rights reserved
|
|
Packit |
df99a1 |
//
|
|
Packit |
df99a1 |
// Permission is hereby granted, free of charge, to any person obtaining
|
|
Packit |
df99a1 |
// a copy of this software and associated documentation files (the
|
|
Packit |
df99a1 |
// "Software"), to deal in the Software without restriction, including
|
|
Packit |
df99a1 |
// without limitation the rights to use, copy, modify, merge, publish,
|
|
Packit |
df99a1 |
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
Packit |
df99a1 |
// permit persons to whom the Software is furnished to do so, subject to
|
|
Packit |
df99a1 |
// the following conditions:
|
|
Packit |
df99a1 |
//
|
|
Packit |
df99a1 |
// The above copyright notice and this permission notice shall be
|
|
Packit |
df99a1 |
// included in all copies or substantial portions of the Software.
|
|
Packit |
df99a1 |
//
|
|
Packit |
df99a1 |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
df99a1 |
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
df99a1 |
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
Packit |
df99a1 |
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
Packit |
df99a1 |
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
Packit |
df99a1 |
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
Packit |
df99a1 |
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Packit |
df99a1 |
//
|
|
Packit |
df99a1 |
// ------------------------------------------------------------------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#include "atomic.h"
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifndef ATOMIC_MACROS
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#if HAVE_PTHREAD
|
|
Packit |
df99a1 |
# include <pthread.h>
|
|
Packit |
df99a1 |
#elif HAVE_QTHREAD // never defined at the moment.
|
|
Packit |
df99a1 |
# include <QMutex>
|
|
Packit |
df99a1 |
# include <QWaitCondition>
|
|
Packit |
df99a1 |
#else
|
|
Packit |
df99a1 |
# include "GThreads.h"
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* Select synchronization primitives */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
# if defined(_WIN32) || defined(_WIN64)
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
namespace {
|
|
Packit |
df99a1 |
struct CS {
|
|
Packit |
df99a1 |
CRITICAL_SECTION cs;
|
|
Packit |
df99a1 |
CS() { InitializeCriticalSection(&cs); }
|
|
Packit |
df99a1 |
~CS() { DeleteCriticalSecton(&cs); } }; }
|
|
Packit |
df99a1 |
static CS globalCS;
|
|
Packit |
df99a1 |
# define MUTEX_LEAVE LeaveCriticalSection(&globalCS.cs)
|
|
Packit |
df99a1 |
# define MUTEX_ENTER EnterCriticalSection(&globalCS.cs);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
# elif defined (PTHREAD_MUTEX_INITIALIZER)
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static pthread_mutex_t ptm = PTHREAD_MUTEX_INITIALIZER;
|
|
Packit |
df99a1 |
# define MUTEX_ENTER pthread_mutex_lock(&ptm)
|
|
Packit |
df99a1 |
# define MUTEX_LEAVE pthread_mutex_unlock(&ptm)
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
# elif defined(__cplusplus) && defined(_GTHREADS_H_)
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static GMonitor m;
|
|
Packit |
df99a1 |
# define MUTEX_ENTER m.enter()
|
|
Packit |
df99a1 |
# define MUTEX_LEAVE m.leave()
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
# elif defined(__cplusplus) && defined(QMUTEX_H)
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static QMutex qtm;
|
|
Packit |
df99a1 |
# define MUTEX_ENTER qtm.lock()
|
|
Packit |
df99a1 |
# define MUTEX_LEAVE qtm.unlock()
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
# endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* atomic primitive emulation */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int
|
|
Packit |
df99a1 |
atomicIncrement(int volatile *var)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int res;
|
|
Packit |
df99a1 |
MUTEX_ENTER;
|
|
Packit |
df99a1 |
res = ++(*var);
|
|
Packit |
df99a1 |
MUTEX_LEAVE;
|
|
Packit |
df99a1 |
return res;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int
|
|
Packit |
df99a1 |
atomicDecrement(int volatile *var)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int res;
|
|
Packit |
df99a1 |
MUTEX_ENTER;
|
|
Packit |
df99a1 |
res = --(*var);
|
|
Packit |
df99a1 |
MUTEX_LEAVE;
|
|
Packit |
df99a1 |
return res;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int
|
|
Packit |
df99a1 |
atomicCompareAndSwap(int volatile *var, int oldval, int newval)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int ret;
|
|
Packit |
df99a1 |
MUTEX_ENTER;
|
|
Packit |
df99a1 |
ret = *var;
|
|
Packit |
df99a1 |
if (ret == oldval)
|
|
Packit |
df99a1 |
*var = newval;
|
|
Packit |
df99a1 |
MUTEX_LEAVE;
|
|
Packit |
df99a1 |
return ret;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int
|
|
Packit |
df99a1 |
atomicExchange(int volatile *var, int newval)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int ret;
|
|
Packit |
df99a1 |
MUTEX_ENTER;
|
|
Packit |
df99a1 |
ret = *var;
|
|
Packit |
df99a1 |
*var = newval;
|
|
Packit |
df99a1 |
MUTEX_LEAVE;
|
|
Packit |
df99a1 |
return ret;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void*
|
|
Packit |
df99a1 |
atomicExchangePointer(void* volatile *var, void* newval)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
void *ret;
|
|
Packit |
df99a1 |
MUTEX_ENTER;
|
|
Packit |
df99a1 |
ret = *var;
|
|
Packit |
df99a1 |
*var = newval;
|
|
Packit |
df99a1 |
MUTEX_LEAVE;
|
|
Packit |
df99a1 |
return ret;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|