#ifndef COUNT_SEMAPHORE_HXX_ #define COUNT_SEMAPHORE_HXX_ /* ==================================================================== * The Vovida Software License, Version 1.0 * * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The names "VOCAL", "Vovida Open Communication Application Library", * and "Vovida Open Communication Application Library (VOCAL)" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor * may "VOCAL" appear in their name, without prior written * permission of Vovida Networks, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * ==================================================================== * * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc. For more information on Vovida Networks, Inc., please see * . * */ static const char* const CountSemaphore_hxx_Version = "$Id: CountSemaphore.hxx,v 1.20 2002/07/12 18:37:08 veer Exp $"; #include "VMutex.h" #include "global.h" #include #if (defined(i386) && defined(__GNUC__)) || defined(__INTEL_COMPILER) #define USE_VMUTEX_LOCKING 0 #else #define USE_VMUTEX_LOCKING 1 #endif #if USE_VMUTEX_LOCKING // these macros define the appropriate operators if using VMutex as the basis for // the reference counting. #define VLOCK() mutex.lock() #define VUNLOCK() mutex.unlock() #define INC(x) ++x #define DEC(x) --x #define DEC_AND_CMP(x,r) --x,r = (x == 0) #define EXCHANGE(ptr,val) void* tmp; tmp = *ptr,*ptr = val, val = tmp #else // these macros define the appropriate operators if using i386 assembly for // the reference counting. #define VLOCK() #define VUNLOCK() #define INC(x) \ { \ asm volatile ("lock; incl %0" : : "m" (x) ); \ } #define DEC(x) \ { \ asm volatile ("lock; decl %0" : : "m" (x) ); \ } #define DEC_AND_CMP(x,r) \ { \ asm volatile ("lock; decl %1; sete %0 " : "=m" (r) : "m" (x) ); \ } #define EXCHANGE(ptr,val) \ { \ asm volatile ("lock; xchg %0,%1" : "=r" (val), "=m" (*ptr) : "m" (*ptr) , "0" (val) ); \ } #endif #define INLINE_ inline /* TODO: fix the name. It should be called ReferenceCount or something like that. figure out why the count is volatile. change decrement() to decrementAndCompare() . */ /** A thread safe reference count. The implementation is designed to * use either VMutex or inline assembly when using GCC (for * efficiency). */ class CountSemaphore { public: /// constructor INLINE_ explicit CountSemaphore(int value=0) : #if USE_VMUTEX_LOCKING mutex(), #endif count(value) {} /** compares the current value in the reference count to * value. returns true if equal. * @param value integer to compare against. */ INLINE_ bool compare(int value) { bool retVal = false; VLOCK(); if (value == count) retVal = true; VUNLOCK(); return retVal; } /** increment the reference count by one. This operation is atomic. */ INLINE_ void increment() { VLOCK(); INC(count); VUNLOCK(); } /** decrement the reference count by one. This operation is * atomic. If the reference count now equals 0, decrement * returns true. */ INLINE_ bool decrement() { bool retVal; VLOCK(); assert(count > 0); DEC_AND_CMP(count, retVal); VUNLOCK(); return retVal; } INLINE_ void exchange(void** ptr, void** val) { VLOCK(); EXCHANGE(ptr, *val); VUNLOCK(); } INLINE_ int getCount() { return count; } bool operator==(int value) const { return (value == count); } void lock() { VLOCK(); } void unlock() { VUNLOCK(); } private: /// suppress copying CountSemaphore(const CountSemaphore&); /// suppress copying const CountSemaphore& operator=(const CountSemaphore&); /// suppress comparison bool operator==(const CountSemaphore&); #if USE_VMUTEX_LOCKING VMutex mutex; #endif volatile int count; // why is this volatile ? }; #endif