changeset 27447:396996f1dad0

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<T>::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<T> instead of T. (refcount::operator++, refcount::operator--): Define using std::atomic operators instead of increment macros. (refcount::get): Delete. (class refcount): Explicitly delete assignment operator and copy constructor. Explicitly use default destructor. Eliminate all uses of assignment as directly setting the reference count value apart from initialization should not be needed.
author John W. Eaton <jwe@octave.org>
date Wed, 25 Sep 2019 17:57:08 -0400
parents c23aee2104de
children b47705865de7
files libinterp/corefcn/oct-stream.cc libinterp/corefcn/oct-stream.h libinterp/parse-tree/jit-typeinfo.cc libinterp/parse-tree/jit-typeinfo.h liboctave/array/Array.h liboctave/array/dim-vector.h liboctave/numeric/sparse-qr.cc liboctave/util/module.mk liboctave/util/oct-atomic.c liboctave/util/oct-atomic.h liboctave/util/oct-refcount.h
diffstat 11 files changed, 124 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/oct-stream.cc	Thu Sep 26 11:32:52 2019 -0400
+++ b/libinterp/corefcn/oct-stream.cc	Wed Sep 25 17:57:08 2019 -0400
@@ -6043,10 +6043,7 @@
 
   stream::stream (base_stream *bs)
     : m_rep (bs)
-  {
-    if (m_rep)
-      m_rep->m_count = 1;
-  }
+  { }
 
   stream::~stream (void)
   {
--- a/libinterp/corefcn/oct-stream.h	Thu Sep 26 11:32:52 2019 -0400
+++ b/libinterp/corefcn/oct-stream.h	Wed Sep 25 17:57:08 2019 -0400
@@ -69,7 +69,7 @@
     base_stream (std::ios::openmode arg_md = std::ios::in | std::ios::out,
                  mach_info::float_format ff = mach_info::native_float_format (),
                  const std::string& encoding = "utf-8")
-      : m_count (0), m_mode (arg_md), m_flt_fmt (ff), m_encoding (encoding),
+      : m_count (1), m_mode (arg_md), m_flt_fmt (ff), m_encoding (encoding),
         m_fail (false), m_open_state (true), m_errmsg ()
     { }
 
--- a/libinterp/parse-tree/jit-typeinfo.cc	Thu Sep 26 11:32:52 2019 -0400
+++ b/libinterp/parse-tree/jit-typeinfo.cc	Wed Sep 25 17:57:08 2019 -0400
@@ -298,7 +298,7 @@
     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
--- a/libinterp/parse-tree/jit-typeinfo.h	Thu Sep 26 11:32:52 2019 -0400
+++ b/libinterp/parse-tree/jit-typeinfo.h	Wed Sep 25 17:57:08 2019 -0400
@@ -102,7 +102,7 @@
       return *m_array;
     }
 
-    int *m_ref_count;
+    int m_ref_count;
 
     U *m_slice_data;
     octave_idx_type m_slice_len;
--- a/liboctave/array/Array.h	Thu Sep 26 11:32:52 2019 -0400
+++ b/liboctave/array/Array.h	Wed Sep 25 17:57:08 2019 -0400
@@ -839,7 +839,7 @@
   //@{
   //! 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; }
 
--- a/liboctave/array/dim-vector.h	Thu Sep 26 11:32:52 2019 -0400
+++ b/liboctave/array/dim-vector.h	Wed Sep 25 17:57:08 2019 -0400
@@ -32,6 +32,7 @@
 #include <initializer_list>
 #include <string>
 
+#include "oct-atomic.h"
 #include "oct-refcount.h"
 
 template <typename T> class Array;
@@ -94,6 +95,16 @@
 
   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 @@
       {
         octave_idx_type *new_rep = clonerep ();
 
-        if (OCTAVE_ATOMIC_DECREMENT (&(count ())) == 0)
+        if (decrement_count () == 0)
           freerep ();
 
         rep = new_rep;
@@ -253,10 +264,10 @@
   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 @@
   {
     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 @@
         // 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 @@
     // 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 @@
       {
         octave_idx_type *r = resizerep (n, fill_value);
 
-        if (OCTAVE_ATOMIC_DECREMENT (&(count ())) == 0)
+        if (decrement_count () == 0)
           freerep ();
 
         rep = r;
--- a/liboctave/numeric/sparse-qr.cc	Thu Sep 26 11:32:52 2019 -0400
+++ b/liboctave/numeric/sparse-qr.cc	Wed Sep 25 17:57:08 2019 -0400
@@ -208,8 +208,6 @@
         (*current_liboctave_error_handler)
           ("sparse_qr: sparse matrix QR factorization filled");
 
-      count = 1;
-
 #else
 
       octave_unused_parameter (order);
@@ -979,8 +977,6 @@
         (*current_liboctave_error_handler)
           ("sparse_qr: sparse matrix QR factorization filled");
 
-      count = 1;
-
 #else
 
       octave_unused_parameter (order);
--- a/liboctave/util/module.mk	Thu Sep 26 11:32:52 2019 -0400
+++ b/liboctave/util/module.mk	Wed Sep 25 17:57:08 2019 -0400
@@ -19,6 +19,7 @@
   %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 @@
   %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 \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/util/oct-atomic.c	Wed Sep 25 17:57:08 2019 -0400
@@ -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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "oct-atomic.h"
+
+#include <stdatomic.h>
+
+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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/util/oct-atomic.h	Wed Sep 25 17:57:08 2019 -0400
@@ -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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#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
--- a/liboctave/util/oct-refcount.h	Thu Sep 26 11:32:52 2019 -0400
+++ b/liboctave/util/oct-refcount.h	Wed Sep 25 17:57:08 2019 -0400
@@ -25,48 +25,10 @@
 
 #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 <intrin.h>
-
-#    define OCTAVE_ATOMIC_INCREMENT(x)                  \
-  _InterlockedIncrement (static_cast<long *> (x))
-
-#    define OCTAVE_ATOMIC_DECREMENT(x)                  \
-  _InterlockedDecrement (static_cast<long *> (x))
-
-#    define OCTAVE_ATOMIC_POST_INCREMENT(x)             \
-  _InterlockedExchangeAdd (static_cast<long *> (x))
-
-#    define OCTAVE_ATOMIC_POST_DECREMENT(x)             \
-  _InterlockedExchangeAdd (static_cast<long *> (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 <atomic>
 
 namespace octave
 {
-
   // Encapsulates a reference counter.
 
   template <typename T>
@@ -80,30 +42,36 @@
       : m_count (initial_count)
     { }
 
+    refcount (const refcount&) = delete;
+
+    refcount& operator = (const refcount&) = delete;
+
+    ~refcount (void) = default;
+
     // 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<count_type const volatile&> (m_count);
+      return m_count.load ();
     }
 
     operator count_type (void) const
@@ -111,14 +79,9 @@
       return value ();
     }
 
-    count_type * get (void)
-    {
-      return &m_count;
-    }
-
   private:
 
-    count_type m_count;
+    std::atomic<T> m_count;
   };
 }