乐趣区

关于c++:linux-gcc-下-没有c11-时的智能指针实现-参考POCO

AtomicCounter.h 线程平安的原子援用计数 实现

//
// AtomicCounter.h
//
// Library: Foundation
// Package: Core
// Module:  AtomicCounter
//
// Definition of the AtomicCounter class.
//
// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier:    BSL-1.0
//

#ifndef Foundation_AtomicCounter_INCLUDED
#define Foundation_AtomicCounter_INCLUDED

namespace Poco {

class AtomicCounter
/// This class implements a simple counter, which
/// provides atomic operations that are safe to
/// use in a multithreaded environment.
///
/// Typical usage of AtomicCounter is for implementing
/// reference counting and similar things.
///
/// On some platforms, the implementation of AtomicCounter
/// is based on atomic primitives specific to the platform
/// (such as InterlockedIncrement, etc. on Windows), and
/// thus very efficient. On platforms that do not support
/// atomic primitives, operations are guarded by a FastMutex.
///
/// The following platforms currently have atomic
/// primitives:
///   - Windows
///   - Mac OS X
///   - GCC 4.1+ (Intel platforms only)
{
public:
  typedef int ValueType; /// The underlying integer type.

  AtomicCounter();
  /// Creates a new AtomicCounter and initializes it to zero.

  explicit AtomicCounter(ValueType initialValue);
  /// Creates a new AtomicCounter and initializes it with
  /// the given value.

  AtomicCounter(const AtomicCounter &counter);
  /// Creates the counter by copying another one.

  ~AtomicCounter();
  /// Destroys the AtomicCounter.

  AtomicCounter &operator=(const AtomicCounter &counter);
  /// Assigns the value of another AtomicCounter.

  AtomicCounter &operator=(ValueType value);
  /// Assigns a value to the counter.

  operator ValueType() const;
  /// Returns the value of the counter.

  ValueType value() const;
  /// Returns the value of the counter.

  ValueType operator++(); // prefix
                          /// Increments the counter and returns the result.

  ValueType
  operator++(int); // postfix
                   /// Increments the counter and returns the previous value.

  ValueType operator--(); // prefix
                          /// Decrements the counter and returns the result.

  ValueType
  operator--(int); // postfix
                   /// Decrements the counter and returns the previous value.

  bool operator!() const;
  /// Returns true if the counter is zero, false otherwise.

private:
  typedef int ImplType;
  ImplType _counter;
};

AtomicCounter::AtomicCounter() : _counter(0) {}

AtomicCounter::AtomicCounter(AtomicCounter::ValueType initialValue)
    : _counter(initialValue) {}

AtomicCounter::AtomicCounter(const AtomicCounter &counter)
    : _counter(counter.value()) {}

AtomicCounter::~AtomicCounter() {}

//
// GCC 4.1+ atomic builtins.
//
inline AtomicCounter::operator AtomicCounter::ValueType() const {return _counter;}

inline AtomicCounter::ValueType AtomicCounter::value() const {return _counter;}

inline AtomicCounter::ValueType AtomicCounter::operator++() // prefix
{return __sync_add_and_fetch(&_counter, 1);
}

inline AtomicCounter::ValueType AtomicCounter::operator++(int) // postfix
{return __sync_fetch_and_add(&_counter, 1);
}

inline AtomicCounter::ValueType AtomicCounter::operator--() // prefix
{return __sync_sub_and_fetch(&_counter, 1);
}

inline AtomicCounter::ValueType AtomicCounter::operator--(int) // postfix
{return __sync_fetch_and_sub(&_counter, 1);
}

inline bool AtomicCounter::operator!() const { return _counter == 0;}

} // namespace Poco

#endif // Foundation_AtomicCounter_INCLUDED

SharedPtr 智能指针的实现

//
// SharedPtr.h
//
// Library: Foundation
// Package: Core
// Module:  SharedPtr
//
// Definition of the SharedPtr template class.
//
// Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier:    BSL-1.0
//

#ifndef Foundation_SharedPtr_INCLUDED
#define Foundation_SharedPtr_INCLUDED

#include "AtomicCounter.h"
#include <algorithm>
#include <cassert>
#include <exception>
#include <stdexcept>

namespace Poco {

class ReferenceCounter
/// Simple ReferenceCounter object, does not delete itself when count reaches 0.
{
public:
  ReferenceCounter() : _cnt(1) {}

  void duplicate() { ++_cnt;}

  int release() { return --_cnt;}

  int referenceCount() const { return _cnt.value(); }

private:
  AtomicCounter _cnt;
};

template <class C>
class ReleasePolicy
/// The default release policy for SharedPtr, which
/// simply uses the delete operator to delete an object.
{
public:
  static void release(C *pObj)
  /// Delete the object.
  /// Note that pObj can be 0.
  {delete pObj;}
};

template <class C>
class ReleaseArrayPolicy
/// The release policy for SharedPtr holding arrays.
{
public:
  static void release(C *pObj)
  /// Delete the object.
  /// Note that pObj can be 0.
  {delete[] pObj;
  }
};

template <class C, class RC = ReferenceCounter, class RP = ReleasePolicy<C> >
class SharedPtr
/// SharedPtr is a "smart" pointer for classes implementing
/// reference counting based garbage collection.
/// SharedPtr is thus similar to AutoPtr. Unlike the
/// AutoPtr template, which can only be used with
/// classes that support reference counting, SharedPtr
/// can be used with any class. For this to work, a
/// SharedPtr manages a reference count for the object
/// it manages.
///
/// SharedPtr works in the following way:
/// If an SharedPtr is assigned an ordinary pointer to
/// an object (via the constructor or the assignment operator),
/// it takes ownership of the object and the object's reference
/// count is initialized to one.
/// If the SharedPtr is assigned another SharedPtr, the
/// object's reference count is incremented by one.
/// The destructor of SharedPtr decrements the object's
/// reference count by one and deletes the object if the
/// reference count reaches zero.
/// SharedPtr supports dereferencing with both the ->
/// and the * operator. An attempt to dereference a null
/// SharedPtr results in a NullPointerException being thrown.
/// SharedPtr also implements all relational operators and
/// a cast operator in case dynamic casting of the encapsulated data types
/// is required.
{
public:
  SharedPtr() : _pCounter(new RC), _ptr(0) {}

  SharedPtr(C *ptr) try : _pCounter(new RC), _ptr(ptr) {} catch (...) {RP::release(ptr);
  }

  template <class Other, class OtherRP>
  SharedPtr(const SharedPtr<Other, RC, OtherRP> &ptr)
      : _pCounter(ptr._pCounter), _ptr(const_cast<Other *>(ptr.get())) {_pCounter->duplicate();
  }

  SharedPtr(const SharedPtr &ptr) : _pCounter(ptr._pCounter), _ptr(ptr._ptr) {_pCounter->duplicate();
  }

  ~SharedPtr() {
    try {release();
    } catch (...) {assert(0);
    }
  }

  SharedPtr &assign(C *ptr) {if (get() != ptr) {SharedPtr tmp(ptr);
      swap(tmp);
    }
    return *this;
  }

  SharedPtr &assign(const SharedPtr &ptr) {if (&ptr != this) {SharedPtr tmp(ptr);
      swap(tmp);
    }
    return *this;
  }

  template <class Other, class OtherRP>
  SharedPtr &assign(const SharedPtr<Other, RC, OtherRP> &ptr) {if (ptr.get() != _ptr) {SharedPtr tmp(ptr);
      swap(tmp);
    }
    return *this;
  }

  SharedPtr &operator=(C *ptr) {return assign(ptr); }

  SharedPtr &operator=(const SharedPtr &ptr) {return assign(ptr); }

  template <class Other, class OtherRP>
  SharedPtr &operator=(const SharedPtr<Other, RC, OtherRP> &ptr) {return assign<Other>(ptr);
  }

  void swap(SharedPtr &ptr) {std::swap(_ptr, ptr._ptr);
    std::swap(_pCounter, ptr._pCounter);
  }

  template <class Other>
  SharedPtr<Other, RC, RP> cast() const
  /// Casts the SharedPtr via a dynamic cast to the given type.
  /// Returns an SharedPtr containing NULL if the cast fails.
  /// Example: (assume class Sub: public Super)
  ///    SharedPtr<Super> super(new Sub());
  ///    SharedPtr<Sub> sub = super.cast<Sub>();
  ///    poco_assert (sub.get());
  {Other *pOther = dynamic_cast<Other *>(_ptr);
    if (pOther)
      return SharedPtr<Other, RC, RP>(_pCounter, pOther);
    return SharedPtr<Other, RC, RP>();}

  template <class Other>
  SharedPtr<Other, RC, RP> unsafeCast() const
  /// Casts the SharedPtr via a static cast to the given type.
  /// Example: (assume class Sub: public Super)
  ///    SharedPtr<Super> super(new Sub());
  ///    SharedPtr<Sub> sub = super.unsafeCast<Sub>();
  ///    poco_assert (sub.get());
  {Other *pOther = static_cast<Other *>(_ptr);
    return SharedPtr<Other, RC, RP>(_pCounter, pOther);
  }

  C *operator->() { return deref(); }

  const C *operator->() const { return deref(); }

  C &operator*() { return *deref(); }

  const C &operator*() const { return *deref(); }

  C *get() { return _ptr;}

  const C *get() const { return _ptr;}

  operator C *() { return _ptr;}

  operator const C *() const { return _ptr;}

  bool operator!() const { return _ptr == 0;}

  bool isNull() const { return _ptr == 0;}

  bool operator==(const SharedPtr &ptr) const {return get() == ptr.get();}

  bool operator==(const C *ptr) const {return get() == ptr; }

  bool operator==(C *ptr) const {return get() == ptr; }

  bool operator!=(const SharedPtr &ptr) const {return get() != ptr.get();}

  bool operator!=(const C *ptr) const {return get() != ptr; }

  bool operator!=(C *ptr) const {return get() != ptr; }

  bool operator<(const SharedPtr &ptr) const {return get() < ptr.get();}

  bool operator<(const C *ptr) const {return get() < ptr; }

  bool operator<(C *ptr) const {return get() < ptr; }

  bool operator<=(const SharedPtr &ptr) const {return get() <= ptr.get();}

  bool operator<=(const C *ptr) const {return get() <= ptr; }

  bool operator<=(C *ptr) const {return get() <= ptr; }

  bool operator>(const SharedPtr &ptr) const {return get() > ptr.get();}

  bool operator>(const C *ptr) const {return get() > ptr; }

  bool operator>(C *ptr) const {return get() > ptr; }

  bool operator>=(const SharedPtr &ptr) const {return get() >= ptr.get();}

  bool operator>=(const C *ptr) const {return get() >= ptr; }

  bool operator>=(C *ptr) const {return get() >= ptr; }

  int referenceCount() const { return _pCounter->referenceCount(); }

protected:
  C *deref() const {if (!_ptr)
      throw std::exception();

    return _ptr;
  }

  void release() {assert(_pCounter);
    int i = _pCounter->release();
    if (i == 0) {RP::release(_ptr);
      _ptr = 0;

      delete _pCounter;
      _pCounter = 0;
    }
  }

  SharedPtr(RC *pCounter, C *ptr)
      : _pCounter(pCounter), _ptr(ptr)
  /// for cast operation
  {poco_assert_dbg(_pCounter);
    _pCounter->duplicate();}

protected:
  RC *_pCounter;
  C *_ptr;

  template <class OtherC, class OtherRC, class OtherRP> friend class SharedPtr;
};

template <class C, class RC, class RP>
inline void swap(SharedPtr<C, RC, RP> &p1, SharedPtr<C, RC, RP> &p2) {p1.swap(p2);
}

} // namespace Poco

#endif // Foundation_SharedPtr_INCLUDED
退出移动版