# HG changeset patch
# User John W. Eaton
# Date 1569448628 14400
# Wed Sep 25 17:57:08 2019 -0400
# Node ID 5785028d203288d27c4d8f31408fb11e3ee1f44f
# Parent 160930a3e5eed20b6daee5d82403b1dbcb388451
use std::atomic to implement refcount class
* oct-atomic.h, oct-atomic.c: New files.
* liboctave/util/module.mk: Update.
* dim-vector.h (dim_vector::increment_count,
dim_vector::decrement_count): New functions. Use them instead of
OCTAVE_ATOMIC_INCREMENT and OCTAVE_ATOMIC_DECREMENT macros.
* Array.h (Array::jit_ref_count): Return int, not pointer. Change
all uses.
* jit-typeinfo.h, jit-typeinfo.cc (jit_array::m_ref_count): Store
integer, not pointer. Change all uses.
* oct-refcount.h (OCTAVE_ATOMIC_INCREMENT, OCTAVE_ATOMIC_DECREMENT,
OCTAVE_ATOMIC_POST_INCREMENT, OCTAVE_ATOMIC_POST_DECREMENT):
Delete macros.
(refcount::m_count): Now std::atomic instead of T.
(class refcount): Provide assignment operator and copy constructor.
(refcount::operator++, refcount::operator--): Define using std::atomic
operators instead of increment macros.
(refcound::get): Delete.
diff --git a/libinterp/parse-tree/jit-typeinfo.cc b/libinterp/parse-tree/jit-typeinfo.cc
--- a/libinterp/parse-tree/jit-typeinfo.cc
+++ b/libinterp/parse-tree/jit-typeinfo.cc
@@ -298,7 +298,7 @@ namespace octave
bool done = false;
// optimize for the simple case (no resizing and no errors)
- if (*array->jit_ref_count () == 1
+ if (array->jit_ref_count () == 1
&& index->all_elements_are_ints ())
{
// this code is similar to idx_vector::fill, but we avoid allocating an
diff --git a/libinterp/parse-tree/jit-typeinfo.h b/libinterp/parse-tree/jit-typeinfo.h
--- a/libinterp/parse-tree/jit-typeinfo.h
+++ b/libinterp/parse-tree/jit-typeinfo.h
@@ -102,7 +102,7 @@ namespace octave
return *m_array;
}
- int *m_ref_count;
+ int m_ref_count;
U *m_slice_data;
octave_idx_type m_slice_len;
diff --git a/liboctave/array/Array.h b/liboctave/array/Array.h
--- a/liboctave/array/Array.h
+++ b/liboctave/array/Array.h
@@ -839,7 +839,7 @@ public:
//@{
//! WARNING: Only call these functions from jit
- int * jit_ref_count (void) { return rep->count.get (); }
+ int jit_ref_count (void) { return rep->count.value (); }
T * jit_slice_data (void) const { return slice_data; }
diff --git a/liboctave/array/dim-vector.h b/liboctave/array/dim-vector.h
--- a/liboctave/array/dim-vector.h
+++ b/liboctave/array/dim-vector.h
@@ -32,6 +32,7 @@ along with Octave; see the file COPYING.
#include
#include
+#include "oct-atomic.h"
#include "oct-refcount.h"
template class Array;
@@ -94,6 +95,16 @@ private:
octave_idx_type& count (void) const { return rep[-2]; }
+ octave_idx_type increment_count (void)
+ {
+ return octave_atomic_increment (&(count ()));
+ }
+
+ octave_idx_type decrement_count (void)
+ {
+ return octave_atomic_decrement (&(count ()));
+ }
+
//! Construct a new rep with count = 1 and ndims given.
static octave_idx_type * newrep (int ndims)
@@ -153,7 +164,7 @@ private:
{
octave_idx_type *new_rep = clonerep ();
- if (OCTAVE_ATOMIC_DECREMENT (&(count ())) == 0)
+ if (decrement_count () == 0)
freerep ();
rep = new_rep;
@@ -253,10 +264,10 @@ public:
static octave_idx_type dim_max (void);
explicit dim_vector (void) : rep (nil_rep ())
- { OCTAVE_ATOMIC_INCREMENT (&(count ())); }
+ { increment_count (); }
dim_vector (const dim_vector& dv) : rep (dv.rep)
- { OCTAVE_ATOMIC_INCREMENT (&(count ())); }
+ { increment_count (); }
dim_vector (dim_vector&& dv) : rep (dv.rep) { dv.rep = nullptr; }
@@ -272,11 +283,11 @@ public:
{
if (&dv != this)
{
- if (OCTAVE_ATOMIC_DECREMENT (&(count ())) == 0)
+ if (decrement_count () == 0)
freerep ();
rep = dv.rep;
- OCTAVE_ATOMIC_INCREMENT (&(count ()));
+ increment_count ();
}
return *this;
@@ -290,7 +301,7 @@ public:
// operator, rep may be a nullptr here. We should only need to
// protect the destructor in a similar way.
- if (rep && OCTAVE_ATOMIC_DECREMENT (&(count ())) == 0)
+ if (rep && decrement_count () == 0)
freerep ();
rep = dv.rep;
@@ -306,7 +317,7 @@ public:
// operator, rep may be a nullptr here. We should only need to
// protect the move assignment operator in a similar way.
- if (rep && OCTAVE_ATOMIC_DECREMENT (&(count ())) == 0)
+ if (rep && decrement_count () == 0)
freerep ();
}
@@ -339,7 +350,7 @@ public:
{
octave_idx_type *r = resizerep (n, fill_value);
- if (OCTAVE_ATOMIC_DECREMENT (&(count ())) == 0)
+ if (decrement_count () == 0)
freerep ();
rep = r;
diff --git a/liboctave/util/module.mk b/liboctave/util/module.mk
--- a/liboctave/util/module.mk
+++ b/liboctave/util/module.mk
@@ -19,6 +19,7 @@ UTIL_INC = \
%reldir%/lo-error.h \
%reldir%/octave-preserve-stream-state.h \
%reldir%/quit.h \
+ %reldir%/oct-atomic.h \
%reldir%/oct-base64.h \
%reldir%/oct-binmap.h \
%reldir%/oct-cmplx.h \
@@ -74,6 +75,7 @@ UTIL_SRC = \
%reldir%/lo-regexp.cc \
%reldir%/lo-utils.cc \
%reldir%/quit.cc \
+ %reldir%/oct-atomic.c \
%reldir%/oct-base64.cc \
%reldir%/oct-glob.cc \
%reldir%/oct-inttypes.cc \
diff --git a/liboctave/util/oct-atomic.c b/liboctave/util/oct-atomic.c
new file mode 100644
--- /dev/null
+++ b/liboctave/util/oct-atomic.c
@@ -0,0 +1,45 @@
+/*
+
+Copyright (C) 2019 John W. Eaton
+
+This file is part of Octave.
+
+Octave 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.
+
+Octave 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING. If not, see
+.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+# include "config.h"
+#endif
+
+#include "oct-atomic.h"
+
+#include
+
+octave_idx_type
+octave_atomic_increment (octave_idx_type *x)
+{
+ atomic_fetch_add (x, 1);
+
+ return *x;
+}
+
+octave_idx_type
+octave_atomic_decrement (octave_idx_type *x)
+{
+ atomic_fetch_sub (x, 1);
+
+ return *x;
+}
diff --git a/liboctave/util/oct-atomic.h b/liboctave/util/oct-atomic.h
new file mode 100644
--- /dev/null
+++ b/liboctave/util/oct-atomic.h
@@ -0,0 +1,40 @@
+/*
+
+Copyright (C) 2019 John W. Eaton
+
+This file is part of Octave.
+
+Octave 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.
+
+Octave 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING. If not, see
+.
+
+*/
+
+#if ! defined (octave_oct_atomic_h)
+#define octave_oct_atomic_h 1
+
+#include "octave-config.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+extern octave_idx_type octave_atomic_increment (octave_idx_type *x);
+
+ extern octave_idx_type octave_atomic_decrement (octave_idx_type *x);
+
+#if defined __cplusplus
+}
+#endif
+
+#endif
diff --git a/liboctave/util/oct-refcount.h b/liboctave/util/oct-refcount.h
--- a/liboctave/util/oct-refcount.h
+++ b/liboctave/util/oct-refcount.h
@@ -25,48 +25,10 @@ along with Octave; see the file COPYING.
#include "octave-config.h"
-#if (defined (OCTAVE_ENABLE_ATOMIC_REFCOUNT) \
- && (defined (__GNUC__) || defined (_MSC_VER)))
-
-# if defined (__GNUC__)
-
-# define OCTAVE_ATOMIC_INCREMENT(x) __sync_add_and_fetch (x, 1)
-# define OCTAVE_ATOMIC_DECREMENT(x) __sync_add_and_fetch (x, -1)
-# define OCTAVE_ATOMIC_POST_INCREMENT(x) __sync_fetch_and_add (x, 1)
-# define OCTAVE_ATOMIC_POST_DECREMENT(x) __sync_fetch_and_add (x, -1)
-
-# elif defined (_MSC_VER)
-
-# include
-
-# define OCTAVE_ATOMIC_INCREMENT(x) \
- _InterlockedIncrement (static_cast (x))
-
-# define OCTAVE_ATOMIC_DECREMENT(x) \
- _InterlockedDecrement (static_cast (x))
-
-# define OCTAVE_ATOMIC_POST_INCREMENT(x) \
- _InterlockedExchangeAdd (static_cast (x))
-
-# define OCTAVE_ATOMIC_POST_DECREMENT(x) \
- _InterlockedExchangeAdd (static_cast (x))
-
-# endif
-
-#else
-
-// Generic non-locking versions
-
-# define OCTAVE_ATOMIC_INCREMENT(x) ++(*(x))
-# define OCTAVE_ATOMIC_DECREMENT(x) --(*(x))
-# define OCTAVE_ATOMIC_POST_INCREMENT(x) (*(x))++
-# define OCTAVE_ATOMIC_POST_DECREMENT(x) (*(x))--
-
-#endif
+#include
namespace octave
{
-
// Encapsulates a reference counter.
template
@@ -80,30 +42,41 @@ namespace octave
: m_count (initial_count)
{ }
+ refcount (const refcount& count)
+ : m_count (count.value ())
+ { }
+
+ refcount& operator = (count_type value)
+ {
+ m_count.store (value);
+
+ return *this;
+ }
+
// Increment/Decrement. int is postfix.
count_type operator++ (void)
{
- return OCTAVE_ATOMIC_INCREMENT (&m_count);
+ return ++m_count;
}
count_type operator++ (int)
{
- return OCTAVE_ATOMIC_POST_INCREMENT (&m_count);
+ return m_count++;
}
count_type operator-- (void)
{
- return OCTAVE_ATOMIC_DECREMENT (&m_count);
+ return --m_count;
}
count_type operator-- (int)
{
- return OCTAVE_ATOMIC_POST_DECREMENT (&m_count);
+ return m_count--;
}
count_type value (void) const
{
- return static_cast (m_count);
+ return m_count.load ();
}
operator count_type (void) const
@@ -111,14 +84,9 @@ namespace octave
return value ();
}
- count_type * get (void)
- {
- return &m_count;
- }
-
private:
- count_type m_count;
+ std::atomic m_count;
};
}