libzmq master
The Intelligent Transport Layer

atomic_ptr.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright (c) 2009-2011 250bpm s.r.o.
00003     Copyright (c) 2007-2009 iMatix Corporation
00004     Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
00005 
00006     This file is part of 0MQ.
00007 
00008     0MQ is free software; you can redistribute it and/or modify it under
00009     the terms of the GNU Lesser General Public License as published by
00010     the Free Software Foundation; either version 3 of the License, or
00011     (at your option) any later version.
00012 
00013     0MQ is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU Lesser General Public License for more details.
00017 
00018     You should have received a copy of the GNU Lesser General Public License
00019     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020 */
00021 
00022 #ifndef __ZMQ_ATOMIC_PTR_HPP_INCLUDED__
00023 #define __ZMQ_ATOMIC_PTR_HPP_INCLUDED__
00024 
00025 #include "platform.hpp"
00026 
00027 #if defined ZMQ_FORCE_MUTEXES
00028 #define ZMQ_ATOMIC_PTR_MUTEX
00029 #elif (defined __i386__ || defined __x86_64__) && defined __GNUC__
00030 #define ZMQ_ATOMIC_PTR_X86
00031 #elif defined ZMQ_HAVE_WINDOWS
00032 #define ZMQ_ATOMIC_PTR_WINDOWS
00033 #elif (defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_NETBSD)
00034 #define ZMQ_ATOMIC_PTR_ATOMIC_H
00035 #else
00036 #define ZMQ_ATOMIC_PTR_MUTEX
00037 #endif
00038 
00039 #if defined ZMQ_ATOMIC_PTR_MUTEX
00040 #include "mutex.hpp"
00041 #elif defined ZMQ_ATOMIC_PTR_WINDOWS
00042 #include "windows.hpp"
00043 #elif defined ZMQ_ATOMIC_PTR_ATOMIC_H
00044 #include <atomic.h>
00045 #endif
00046 
00047 namespace zmq
00048 {
00049 
00050     //  This class encapsulates several atomic operations on pointers.
00051 
00052     template <typename T> class atomic_ptr_t
00053     {
00054     public:
00055 
00056         //  Initialise atomic pointer
00057         inline atomic_ptr_t ()
00058         {
00059             ptr = NULL;
00060         }
00061 
00062         //  Destroy atomic pointer
00063         inline ~atomic_ptr_t ()
00064         {
00065         }
00066 
00067         //  Set value of atomic pointer in a non-threadsafe way
00068         //  Use this function only when you are sure that at most one
00069         //  thread is accessing the pointer at the moment.
00070         inline void set (T *ptr_)
00071         {
00072             this->ptr = ptr_;
00073         }
00074 
00075         //  Perform atomic 'exchange pointers' operation. Pointer is set
00076         //  to the 'val' value. Old value is returned.
00077         inline T *xchg (T *val_)
00078         {
00079 #if defined ZMQ_ATOMIC_PTR_WINDOWS
00080             return (T*) InterlockedExchangePointer ((PVOID*) &ptr, val_);
00081 #elif defined ZMQ_ATOMIC_PTR_ATOMIC_H
00082             return (T*) atomic_swap_ptr (&ptr, val_);
00083 #elif defined ZMQ_ATOMIC_PTR_X86
00084             T *old;
00085             __asm__ volatile (
00086                 "lock; xchg %0, %2"
00087                 : "=r" (old), "=m" (ptr)
00088                 : "m" (ptr), "0" (val_));
00089             return old;
00090 #elif defined ZMQ_ATOMIC_PTR_MUTEX
00091             sync.lock ();
00092             T *old = (T*) ptr;
00093             ptr = val_;
00094             sync.unlock ();
00095             return old;
00096 #else
00097 #error atomic_ptr is not implemented for this platform
00098 #endif
00099         }
00100 
00101         //  Perform atomic 'compare and swap' operation on the pointer.
00102         //  The pointer is compared to 'cmp' argument and if they are
00103         //  equal, its value is set to 'val'. Old value of the pointer
00104         //  is returned.
00105         inline T *cas (T *cmp_, T *val_)
00106         {
00107 #if defined ZMQ_ATOMIC_PTR_WINDOWS
00108             return (T*) InterlockedCompareExchangePointer (
00109                 (volatile PVOID*) &ptr, val_, cmp_);
00110 #elif defined ZMQ_ATOMIC_PTR_ATOMIC_H
00111             return (T*) atomic_cas_ptr (&ptr, cmp_, val_);
00112 #elif defined ZMQ_ATOMIC_PTR_X86
00113             T *old;
00114             __asm__ volatile (
00115                 "lock; cmpxchg %2, %3"
00116                 : "=a" (old), "=m" (ptr)
00117                 : "r" (val_), "m" (ptr), "0" (cmp_)
00118                 : "cc");
00119             return old;
00120 #elif defined ZMQ_ATOMIC_PTR_MUTEX
00121             sync.lock ();
00122             T *old = (T*) ptr;
00123             if (ptr == cmp_)
00124                 ptr = val_;
00125             sync.unlock ();
00126             return old;
00127 #else
00128 #error atomic_ptr is not implemented for this platform
00129 #endif
00130         }
00131 
00132     private:
00133 
00134         volatile T *ptr;
00135 #if defined ZMQ_ATOMIC_PTR_MUTEX
00136         mutex_t sync;
00137 #endif
00138 
00139         atomic_ptr_t (const atomic_ptr_t&);
00140         const atomic_ptr_t &operator = (const atomic_ptr_t&);
00141     };
00142 
00143 }
00144 
00145 //  Remove macros local to this file.
00146 #if defined ZMQ_ATOMIC_PTR_WINDOWS
00147 #undef ZMQ_ATOMIC_PTR_WINDOWS
00148 #endif
00149 #if defined ZMQ_ATOMIC_PTR_ATOMIC_H
00150 #undef ZMQ_ATOMIC_PTR_ATOMIC_H
00151 #endif
00152 #if defined ZMQ_ATOMIC_PTR_X86
00153 #undef ZMQ_ATOMIC_PTR_X86
00154 #endif
00155 #if defined ZMQ_ATOMIC_PTR_MUTEX
00156 #undef ZMQ_ATOMIC_PTR_MUTEX
00157 #endif
00158 
00159 #endif
00160 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines