/** * Copyright (c) 2011 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects * for all of the code used other than as permitted herein. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you do not * wish to do so, delete this exception statement from your version. If you * delete this exception statement from all source files in the program, * then also delete it in the license file. */ #pragma once #include #include #include "mongo/base/disallow_copying.h" #include "mongo/base/string_data.h" #include "mongo/platform/atomic_word.h" #include "mongo/util/allocator.h" namespace mongo { /// This is an alternative base class to the above ones (will replace them eventually) class RefCountable { MONGO_DISALLOW_COPYING(RefCountable); public: /// If false you have exclusive access to this object. This is useful for implementing COW. bool isShared() const { // TODO: switch to unfenced read method after SERVER-6973 return reinterpret_cast(_count) > 1; } friend void intrusive_ptr_add_ref(const RefCountable* ptr) { ptr->_count.addAndFetch(1); }; friend void intrusive_ptr_release(const RefCountable* ptr) { if (ptr->_count.subtractAndFetch(1) == 0) { delete ptr; // uses subclass destructor and operator delete } }; protected: RefCountable() {} virtual ~RefCountable() {} private: mutable AtomicUInt32 _count; // default initialized to 0 }; /// This is an immutable reference-counted string class RCString : public RefCountable { public: const char* c_str() const { return reinterpret_cast(this) + sizeof(RCString); } int size() const { return _size; } StringData stringData() const { return StringData(c_str(), _size); } static boost::intrusive_ptr create(StringData s); // MSVC: C4291: 'declaration' : no matching operator delete found; memory will not be freed if // initialization throws an exception // We simply rely on the default global placement delete since a local placement delete would be // ambiguous for some compilers #pragma warning(push) #pragma warning(disable : 4291) void operator delete(void* ptr) { free(ptr); } #pragma warning(pop) private: // these can only be created by calling create() RCString(){}; void* operator new(size_t objSize, size_t realSize) { return mongoMalloc(realSize); } int _size; // does NOT include trailing NUL byte. // char[_size+1] array allocated past end of class }; } // namespace mongo