mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Use commit 0e1e780fd6f18ce93119061e36a4fca9711bc020 Excluded multibuild folder, as this caused git issues
184 lines
4.8 KiB
C
184 lines
4.8 KiB
C
/*
|
||
Copyright (C) 2011 Equinor ASA, Norway.
|
||
|
||
The file 'atomic.h' is part of ERT - Ensemble based Reservoir Tool.
|
||
|
||
ERT is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
ERT 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 GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||
for more details.
|
||
*/
|
||
|
||
/*
|
||
This whole file was something I found on the internet - it was
|
||
posted as beeing in the public domain. The essential functions
|
||
__sync_add_and_fetch() and do on are (as I understand it) built in
|
||
gcc functions. Only available in reasonably new gcc versions
|
||
(4.1???).
|
||
*/
|
||
|
||
#ifndef _ATOMIC_H
|
||
#define _ATOMIC_H
|
||
|
||
|
||
|
||
/**
|
||
<EFBFBD>* Atomic type.
|
||
<EFBFBD>*/
|
||
|
||
typedef struct {
|
||
volatile int counter;
|
||
} atomic_t;
|
||
|
||
#define ATOMIC_INIT(i) <20>{ (i) }
|
||
|
||
/**
|
||
<EFBFBD>* Read atomic variable
|
||
<EFBFBD>* @param v pointer of type atomic_t
|
||
<EFBFBD>*
|
||
<EFBFBD>* Atomically reads the value of @v.
|
||
<EFBFBD>*/
|
||
#define atomic_read(v) ((v)->counter)
|
||
|
||
/**
|
||
<EFBFBD>* Set atomic variable
|
||
<EFBFBD>* @param v pointer of type atomic_t
|
||
<EFBFBD>* @param i required value
|
||
<EFBFBD>*/
|
||
#define atomic_set(v,i) (((v)->counter) = (i))
|
||
|
||
/**
|
||
<EFBFBD>* Add to the atomic variable
|
||
<EFBFBD>* @param i integer value to add
|
||
<EFBFBD>* @param v pointer of type atomic_t
|
||
<EFBFBD>*/
|
||
static inline void atomic_add( int i, atomic_t *v )
|
||
{
|
||
(void)__sync_add_and_fetch(&v->counter, i);
|
||
}
|
||
|
||
/**
|
||
<EFBFBD>* Subtract the atomic variable
|
||
<EFBFBD>* @param i integer value to subtract
|
||
<EFBFBD>* @param v pointer of type atomic_t
|
||
<EFBFBD>*
|
||
<EFBFBD>* Atomically subtracts @i from @v.
|
||
<EFBFBD>*/
|
||
static inline void atomic_sub( int i, atomic_t *v )
|
||
{
|
||
(void)__sync_sub_and_fetch(&v->counter, i);
|
||
}
|
||
|
||
/**
|
||
<EFBFBD>* Subtract value from variable and test result
|
||
<EFBFBD>* @param i integer value to subtract
|
||
<EFBFBD>* @param v pointer of type atomic_t
|
||
<EFBFBD>*
|
||
<EFBFBD>* Atomically subtracts @i from @v and returns
|
||
<EFBFBD>* true if the result is zero, or false for all
|
||
<EFBFBD>* other cases.
|
||
<EFBFBD>*/
|
||
static inline int atomic_sub_and_test( int i, atomic_t *v )
|
||
{
|
||
return !(__sync_sub_and_fetch(&v->counter, i));
|
||
}
|
||
|
||
/**
|
||
<EFBFBD>* Increment atomic variable
|
||
<EFBFBD>* @param v pointer of type atomic_t
|
||
<EFBFBD>*
|
||
<EFBFBD>* Atomically increments @v by 1.
|
||
<EFBFBD>*/
|
||
static inline void atomic_inc( atomic_t *v )
|
||
{
|
||
(void)__sync_fetch_and_add(&v->counter, 1);
|
||
}
|
||
|
||
/**
|
||
<EFBFBD>* @brief decrement atomic variable
|
||
<EFBFBD>* @param v: pointer of type atomic_t
|
||
<EFBFBD>*
|
||
<EFBFBD>* Atomically decrements @v by 1. <20>Note that the guaranteed
|
||
<EFBFBD>* useful range of an atomic_t is only 24 bits.
|
||
<EFBFBD>*/
|
||
static inline void atomic_dec( atomic_t *v )
|
||
{
|
||
(void)__sync_fetch_and_sub(&v->counter, 1);
|
||
}
|
||
|
||
/**
|
||
<EFBFBD>* @brief Decrement and test
|
||
<EFBFBD>* @param v pointer of type atomic_t
|
||
<EFBFBD>*
|
||
<EFBFBD>* Atomically decrements @v by 1 and
|
||
<EFBFBD>* returns true if the result is 0, or false for all other
|
||
<EFBFBD>* cases.
|
||
<EFBFBD>*/
|
||
static inline int atomic_dec_and_test( atomic_t *v )
|
||
{
|
||
return !(__sync_sub_and_fetch(&v->counter, 1));
|
||
}
|
||
|
||
/**
|
||
<EFBFBD>* @brief Increment and test
|
||
<EFBFBD>* @param v pointer of type atomic_t
|
||
<EFBFBD>*
|
||
<EFBFBD>* Atomically increments @v by 1
|
||
<EFBFBD>* and returns true if the result is zero, or false for all
|
||
<EFBFBD>* other cases.
|
||
<EFBFBD>*/
|
||
static inline int atomic_inc_and_test( atomic_t *v )
|
||
{
|
||
return !(__sync_add_and_fetch(&v->counter, 1));
|
||
}
|
||
|
||
/**
|
||
<EFBFBD>* @brief add and test if negative
|
||
<EFBFBD>* @param v pointer of type atomic_t
|
||
<EFBFBD>* @param i integer value to add
|
||
<EFBFBD>*
|
||
<EFBFBD>* Atomically adds @i to @v and returns true
|
||
<EFBFBD>* if the result is negative, or false when
|
||
<EFBFBD>* result is greater than or equal to zero.
|
||
<EFBFBD>*/
|
||
static inline int atomic_add_negative( int i, atomic_t *v )
|
||
{
|
||
return (__sync_add_and_fetch(&v->counter, i) < 0);
|
||
}
|
||
|
||
#endif
|
||
|
||
/*****************************************************************/
|
||
/*****************************************************************/
|
||
/*****************************************************************/
|
||
|
||
///* ALternative implementations: */
|
||
////Pretty straight forward isn't it? It could be even more powerful and simpler if you don't need precise compatibility with atomic.h. For example, atomic_add could easily return the result values:
|
||
//static inline int atomic_add( int i, atomic_t *v )
|
||
//{
|
||
// return __sync_add_and_fetch(&v->counter, i);
|
||
//}
|
||
//
|
||
////As a second example, consider a compare and swap operation, frequently used in lock-free algorithms. Once again, it's trivially:
|
||
///**
|
||
//<2F>* @brief compare and swap
|
||
//<2F>* @param v pointer of type atomic_t
|
||
//<2F>*
|
||
//<2F>* If the current value of @b v is @b oldval,
|
||
//<2F>* then write @b newval into @b v. Returns #TRUE if
|
||
//<2F>* the comparison is successful and @b newval was
|
||
//<2F>* written.
|
||
//<2F>*/
|
||
//static inline int atomic_cas( atomic_t *v, int oldval, int newval )
|
||
//{
|
||
// return __sync_bool_compare_and_swap(&v->counter, oldval, newval);
|
||
//}
|
||
|