root/core/rw_locking.hpp

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. lock
  2. decay
  3. lock
  4. try_lock

   1 #ifndef libjmmcg_core_rw_locking_hpp
   2 #define libjmmcg_core_rw_locking_hpp
   3 
   4 /******************************************************************************
   5 ** $Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/core/rw_locking.hpp 2265 2018-03-10 22:10:38Z jmmcg $
   6 **
   7 ** Copyright © 2011 by J.M.McGuiness, coder@hussar.me.uk
   8 **
   9 ** This library is free software; you can redistribute it and/or
  10 ** modify it under the terms of the GNU Lesser General Public
  11 ** License as published by the Free Software Foundation; either
  12 ** version 2.1 of the License, or (at your option) any later version.
  13 **
  14 ** This library is distributed in the hope that it will be useful,
  15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17 ** Lesser General Public License for more details.
  18 **
  19 ** You should have received a copy of the GNU Lesser General Public
  20 ** License along with this library; if not, write to the Free Software
  21 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22 */
  23 
  24 #include "atomic_counter.hpp"
  25 #include "locking.hpp"
  26 
  27 namespace jmmcg { namespace ppd { namespace lock { namespace rw {
  28 
  29                 template<class T> class locker;
  30 
  31                 template<class L>
  32                 class decaying_write_impl {
  33                 public:
  34                         typedef L atomic_t;
  35                         typedef typename atomic_t::lock_traits lock_traits;
  36                         typedef typename lock_traits::atomic_state_type atomic_state_type;
  37                         typedef typename lock_traits::timeout_type timeout_type;
  38 
  39                         /**
  40                                 To assist in allowing compile-time computation of the algorithmic order of the threading model.
  41                         */
  42                         static constexpr ppd::generic_traits::memory_access_modes memory_access_mode=atomic_t::memory_access_mode;
  43 
  44                 private:
  45                         atomic_t &rw_lk;
  46 
  47                 public:
  48                         explicit constexpr __stdcall decaying_write_impl(atomic_t &l) noexcept(true) FORCE_INLINE;
  49 
  50                         /**
  51                                 Note that this is the write-lock interface.
  52                         */
  53                         atomic_state_type __fastcall lock() noexcept(noexcept(rw_lk.lock())) FORCE_INLINE {
  54                                 return rw_lk.lock();
  55                         }
  56                         /**
  57                                 Note that this is the write-lock interface. Also note that the timeout is ignored, the lock waits indefinitely.
  58                         */
  59                         atomic_state_type __fastcall lock(const timeout_type) noexcept(false) FORCE_INLINE;
  60                         /**
  61                                 Note that this is the write-lock interface.
  62                         */
  63                         atomic_state_type __fastcall unlock() noexcept(true) FORCE_INLINE;
  64                         /// Atomically convert the writer lock to a read lock.
  65                         void decay() noexcept(true) FORCE_INLINE;
  66                 };
  67                 /// A class that allows a write lock to optionally, atomically decay to a read lock.
  68                 /**
  69                         Only taken if there are no other readers nor any writers. If multiple writers attempt to gain the lock, only one will succeed, the choice is undefined. If at least one read lock is held, then any write locks will block until there are no read locks.
  70 
  71                         \see rw
  72                         \see read
  73                         \see write
  74                 */
  75                 template<class T>
  76                 class decaying_write_impl<locker<T> > {
  77                 public:
  78                         typedef locker<T> atomic_t;
  79                         typedef typename atomic_t::lock_traits lock_traits;
  80                         typedef typename lock_traits::atomic_state_type atomic_state_type;
  81                         typedef typename lock_traits::timeout_type timeout_type;
  82 
  83                         /**
  84                                 To assist in allowing compile-time computation of the algorithmic order of the threading model.
  85                         */
  86                         static constexpr ppd::generic_traits::memory_access_modes memory_access_mode=atomic_t::memory_access_mode;
  87 
  88                         explicit constexpr __stdcall decaying_write_impl(atomic_t &l) noexcept(true) FORCE_INLINE;
  89 
  90                         /**
  91                                 Note that this is the write-lock interface.
  92                         */
  93                         atomic_state_type __fastcall lock() noexcept(false) FORCE_INLINE;
  94                         /**
  95                                 Note that this is the write-lock interface. Also note that the timeout is ignored, the lock waits indefinitely.
  96                         */
  97                         atomic_state_type __fastcall lock(const timeout_type) noexcept(false) FORCE_INLINE;
  98                         /**
  99                                 Note that this is the write-lock interface.
 100                         */
 101                         atomic_state_type __fastcall unlock() noexcept(true) FORCE_INLINE;
 102                         /// Atomically convert the writer lock to a read lock.
 103                         void decay() noexcept(true) FORCE_INLINE;
 104 
 105                 private:
 106                         atomic_t &rw_lk;
 107                         typename atomic_t::writer_atomic_t &exclusive_w_lk;
 108                         bool decayed;
 109                 };
 110 
 111                 /// A readers-writer lock to control a resource.
 112                 /**
 113                         The classic lock that allows many readers, but only one writer to occupy the lock at any one time.
 114                         The order of writers vs. readers is implementation defined.
 115                         This allows CREW implementations.
 116 
 117                         \see read
 118                         \see write
 119                         \see decaying_write
 120                 */
 121                 template<
 122                         class T ///< The lock traits.
 123                 >
 124                 class locker : public lockable<T>, protected non_copyable {
 125                 public:
 126                         typedef typename lockable<T>::lock_traits lock_traits;
 127                         typedef typename lock_traits::atomic_state_type atomic_state_type;
 128                         typedef typename lock_traits::timeout_type timeout_type;
 129                         /**
 130                                 To assist in allowing compile-time computation of the algorithmic order of the threading model.
 131                         */
 132                         static constexpr generic_traits::memory_access_modes memory_access_mode=generic_traits::memory_access_modes::crew_memory_access;
 133 
 134                         /// Take a shared read lock on the resource, using RAII.
 135                         /**
 136                                 If a writer has acquired the resource, then this will block until no writers have the resource. If multiple writers and readers are waiting for the resource, then the order in which readers and writers acquire the resource is undefined.
 137 
 138                                 \see rw
 139                                 \see write
 140                         */
 141                         class read_lock_type : protected non_copyable {
 142                         public:
 143                                 typedef locker atomic_t;
 144                                 typedef typename atomic_t::lock_traits lock_traits;
 145                                 typedef typename lock_traits::timeout_type timeout_type;
 146 
 147                                 /**
 148                                         To assist in allowing compile-time computation of the algorithmic order of the threading model.
 149                                 */
 150                                 static constexpr ppd::generic_traits::memory_access_modes memory_access_mode=atomic_t::memory_access_mode;
 151 
 152                                 /**
 153                                         Note that the time-out is ignored, the lock waits indefinitely.
 154                                 */
 155                                 __stdcall read_lock_type(atomic_t &l, const timeout_type) noexcept(false) FORCE_INLINE;
 156                                 __stdcall ~read_lock_type() noexcept(true) FORCE_INLINE;
 157 
 158                         private:
 159                                 atomic_t &lk;
 160                         };
 161 
 162                         /// Take an exclusive write-lock on the resource, using RAII.
 163                         /**
 164                                 Only taken if there are no other readers nor any writers. If multiple writers attempt to gain the lock, only one will succeed, the choice is undefined. If at least one read lock is held, then any write locks will block until there are no read locks.
 165 
 166                                 \see rw
 167                                 \see read_lock_type
 168                                 \see decaying_write
 169                         */
 170                         class write_lock_type : protected non_copyable {
 171                         public:
 172                                 typedef locker atomic_t;
 173                                 typedef typename atomic_t::lock_traits lock_traits;
 174                                 typedef typename lock_traits::timeout_type timeout_type;
 175 
 176                                 /**
 177                                         To assist in allowing compile-time computation of the algorithmic order of the threading model.
 178                                 */
 179                                 static constexpr ppd::generic_traits::memory_access_modes memory_access_mode=atomic_t::memory_access_mode;
 180 
 181                                 /**
 182                                         Note that the timeout is ignored, the lock waits indefinitely.
 183                                 */
 184                                 __stdcall write_lock_type(atomic_t &l, const timeout_type) noexcept(false) FORCE_INLINE;
 185                                 __stdcall ~write_lock_type() noexcept(true) FORCE_INLINE;
 186 
 187                                 /**
 188                                         Does nothing, just to make the interface the same.
 189                                 */
 190                                 constexpr void decay() const noexcept(true) FORCE_INLINE {}
 191 
 192                         private:
 193                                 const typename atomic_t::writer_lk_t exclusive_w_lk;
 194                                 atomic_t &rw_lk;
 195                         };
 196 
 197                         /// A class that allows a write lock to optionally, atomically decay to a read lock, using RAII.
 198                         /**
 199                                 \see decaying_write_impl
 200                         */
 201                         class decaying_write_lock_type final : protected decaying_write_impl<locker<T> > {
 202                         public:
 203                                 typedef decaying_write_impl<locker<T> > base_t;
 204                                 typedef typename base_t::atomic_t atomic_t;
 205                                 typedef typename atomic_t::lock_traits lock_traits;
 206                                 typedef typename lock_traits::timeout_type timeout_type;
 207                                 using base_t::memory_access_mode;
 208 
 209                                 /**
 210                                         Note that the timeout is ignored, the lock waits indefinitely.
 211                                 */
 212                                 __stdcall decaying_write_lock_type(atomic_t &l, const timeout_type) noexcept(false) FORCE_INLINE;
 213                                 __stdcall ~decaying_write_lock_type() noexcept(true) FORCE_INLINE;
 214 
 215                                 void operator=(decaying_write_lock_type const &)=delete;
 216                                 void operator=(decaying_write_lock_type &&)=delete;
 217 
 218                                 /// Atomically convert the writer lock to a read lock.
 219                                 void decay() noexcept(true) FORCE_INLINE;
 220                         };
 221 
 222                         __stdcall locker() noexcept(false) FORCE_INLINE;
 223 
 224                         locker(locker const &)=delete;
 225                         locker(locker &&)=delete;
 226                         void operator=(locker const &)=delete;
 227                         void operator=(locker &&)=delete;
 228 
 229                         /**
 230                                 Note that this is the read-lock interface.
 231                         */
 232                         atomic_state_type __fastcall lock() noexcept(false) FORCE_INLINE;
 233                         /**
 234                                 Note that this is the read-lock interface.
 235                         */
 236                         atomic_state_type __fastcall lock(const timeout_type) noexcept(false) FORCE_INLINE {
 237                                 return this->lock();
 238                         }
 239                         /**
 240                                 Note that this is the read-lock interface.
 241                         */
 242                         atomic_state_type __fastcall unlock() noexcept(true) FORCE_INLINE;
 243 
 244 ///\todo G++ issues:            private:
 245                         typedef typename lock_traits::critical_section_type writer_atomic_t;
 246                         typedef typename writer_atomic_t::write_unlockable_type writer_lk_t;
 247                         typedef typename lock_traits::anon_event_type readers_free_t;
 248                         typedef typename lock_traits::template atomic_counter_type<long> atomic_counter_type;
 249                         friend class write;
 250                         friend class decaying_write;
 251 
 252                         atomic_counter_type readers;
 253                         readers_free_t readers_free;
 254                         writer_atomic_t writer_lk;
 255 
 256                 private:
 257                         atomic_state_type __fastcall try_lock() noexcept(true) FORCE_INLINE {
 258                                 return lock_traits::atom_unset;
 259                         }
 260                 };
 261 
 262 } } } }
 263 
 264 #include "rw_locking_impl.hpp"
 265 
 266 #endif

/* [<][>][^][v][top][bottom][index][help] */