![]() |
libzmq master
The Intelligent Transport Layer
|
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