Logo Search packages:      
Sourcecode: ocropus version File versions  Download package

smartptr.h

Go to the documentation of this file.
// -*- C++ -*-

// Copyright 2006 Deutsches Forschungszentrum fuer Kuenstliche Intelligenz 
// or its licensors, as applicable.
// Copyright 1995-2005 Thomas M. Breuel
// 
// You may not use this file except under the terms of the accompanying license.
// 
// Licensed under the Apache License, Version 2.0 (the "License"); you
// may not use this file except in compliance with the License. You may
// obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// Project: iupr common header files
// File: smartptr.h
// Purpose: smart pointers--automatically deallocate objects when they go out of scope
// Responsible: tmb
// Reviewer: 
// Primary Repository: 
// Web Sites: www.iupr.org, www.dfki.de

/// \file smartptr.h
/// \brief Smart pointers

#ifndef h_smartptr_
#define h_smartptr_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "checks.h"

namespace colib {

    /// \brief General class for remembering cleanup actions (e.g., for pointers).
    ///
    /// Declare a cleanup function as
    ///
    /// JpegImage *image = jpeg_open(...);
    /// cleanup image_cleanup(jpeg_close,image);
    ///
    /// If you don't want the cleanup action to be executed, you can call the "forget" method.
    /// E.g.,
    ///
    /// image_cleanup.forget();
    /// jpeg_close(image);

00053     class cleanup {
    private:

        /// Internal helper class.
        
00058         class Cleaner {
        public:
            virtual void cleanup() = 0;
            virtual ~Cleaner() {}
        };
        template <class F,class T>
        class TheCleaner:public Cleaner {
        public:
            F f;
            T t;
            TheCleaner(F f,T t):f(f),t(t) {
            }
            void cleanup() {
                f(t);
            }
        };
        Cleaner *cleaner;

    public:

        /// Initialize the cleanup object with a cleanup function f and a target object t.
        
        template <class F,class T>
00081         cleanup(F f,T t) {
            cleaner = new TheCleaner<F,T>(f,t);
        }

        /// Tell the cleanup object to forget about cleaning up the target object.
        
00087         void forget() {
            if(cleaner) {
                delete cleaner;
                cleaner = 0;
            }
        }

        /// Destroy the cleanup object, cleaning up the target by calling the cleanup function if necessary.
        
00096         ~cleanup() {
            if(cleaner) {
                cleaner->cleanup();
                delete cleaner;
                cleaner = 0;
            }
        }
    };

    /// \brief Automatic deletion, linear assignment.
    ///
    /// A smart pointer class that deletes the pointer it holds when it
    /// goes out of scope.  Assignment is like it is for linear types: on
    /// assignment, the pointer gets moved to the destination, and the
    /// source gets set to NULL (this is convenient for returning values,
    /// for use in lists, and similar settings).

    template <class T>
00114     class autodel {
    private:
        T *pointer;

    public:

        /// Default constructor sets pointer to null.
    
00122         autodel() {
            pointer = 0;
        }

        /// Destructor deletes any pointer held by the class.

00128         ~autodel() {
            if(pointer) delete pointer;
        }

        /// Initialization with a pointer transfers ownership to the class.
    
00134         explicit autodel(T *other) {
            pointer = other;
        }

        /// Assignment of a pointer deletes any old pointer held by the class and
        /// transfers ownership of the pointer to the class.

00141         void operator=(T *other) {
            if(pointer) delete pointer;
            pointer = other;
        }

        /// Smart pointer dereference; throws an exception if the pointer is null,
        /// unless compiled UNSAFE.

00149         T *operator->() const {
            if(!pointer) throw "autodel: attempt to dereference null smartpointer";
            return pointer;
        }

        /// Explicit pointer dereference; throws an exception if the pointer is null,
        /// unless compiled UNSAFE.

00157         T &operator*() const {
            if(!pointer) throw "autodel: attempt to dereference null smartpointer";
            return *pointer;
        }

        /// Same as operator*()

00164         T &ref() const {
            return operator*();
        }

        /// Conversion to pointer.

00170         T *ptr() const {
            return pointer;
        }

        /// Testing whether the pointer is null.

00176         bool operator!() const {
            return !pointer;
        }

        /// Linear assignment: get the pointer from the other smart pointer,
        /// and set the other smart pointer to null.

00183         void operator=(autodel<T> &other) {
            if(pointer) delete pointer;
            pointer = other.move();
        }

        /// Take ownership away from this smart pointer and set the smart pointer to null.

00190         T *move() {
            T *result = pointer;
            pointer = 0;
            return result;
        }
    };

    /// \brief A simple smart pointer class for holding malloc-allocated pointers
    ///
    /// This is completely analogous to autodel, it just calls "free" to free the pointer.
    /// We could refactor this and have a common baseclass for autodel/autofree, but
    /// let's keep this simple.

    template <class T>
00204     class autofree {
    private:
        T *pointer;

    public:

        /// Default constructor sets pointer to null.
    
00212         autofree() {
            pointer = 0;
        }

        /// Destructor deletes any pointer held by the class.

00218         ~autofree() {
            if(pointer) free(pointer);
        }

        /// Initialization with a pointer transfers ownership to the class.
    
00224         explicit autofree(T *other) {
            pointer = other;
        }

        /// Assignment of a pointer deletes any old pointer held by the class and
        /// transfers ownership of the pointer to the class.

00231         void operator=(T *other) {
            if(pointer) free(pointer);
            pointer = other;
        }

        /// Smart pointer dereference; throws an exception if the pointer is null,
        /// unless compiled UNSAFE.

00239         T *operator->() const {
            if(!pointer) throw "autofree: attempt to dereference null smartpointer";
            return pointer;
        }

        /// Explicit pointer dereference; throws an exception if the pointer is null,
        /// unless compiled UNSAFE.

00247         T &operator*() const {
            if(!pointer) throw "autofree: attempt to dereference null smartpointer";
            return *pointer;
        }

        /// Same as operator*().

00254         T &ref() const {
            return operator*();
        }

        /// Conversion to pointer.

00260         T *ptr() const {
            return pointer;
        }

        /// Testing whether the pointer is null.

00266         bool operator!() const {
            return !pointer;
        }

        /// Linear assignment: get the pointer from the other smart pointer,
        /// and set the other smart pointer to null.

00273         void operator=(autofree<T> &other) {
            if(pointer) delete pointer;
            pointer = other.move();
        }

        /// Take ownership away from this smart pointer and set the smart pointer to null.

00280         T *move() {
            T *result = pointer;
            pointer = 0;
            return result;
        }
    };

    /// \brief Automatic allocation and deletion, linear assignment.
    ///
    /// A smart pointer class that automatically allocates an object when
    /// an attempt is made to access and dereference the pointer.
    /// Assignment is linear (ownership gets transferred from the source of
    /// the assignment to the destination, and the source gets set to
    /// null).

    template <class T>
00296     class autoref {
    private:
        T *pointer;

    public:

        /// Default initializer, sets object to null.
    
00304         autoref() {
            pointer = 0;
        }

        /// Destructor deallocates object, if any.
        
00310         ~autoref() {
            if(pointer)
                delete pointer;
        }

        /// Smart pointer dereference allocates object if none is held, then returns a pointer.
        /// This always succeeds, unless the default constructor for T throws an exception.

00318         T *operator->() {
            if(!pointer)
                pointer = new T();
            return pointer;
        }

        /// Pointer dereference allocates object if none is held, then returns a pointer.
        /// This always succeeds, unless the default constructor for T throws an exception.

00327         T &operator*() {
            if(!pointer)
                pointer = new T();
            return *pointer;
        }

        /// Same as operator*

00335         T &ref() {
            return operator*();
        }

        /// Conversion to pointer.  Does not allocate an object.

00341         T *ptr() {
            return *pointer;
        }

        /// Pointer dereference allocates object if none is held, then returns a pointer.
        /// This always succeeds, unless the default constructor for T throws an exception.

00348         T &deref() {
            if(!pointer)
                pointer = new T();
            return *pointer;
        }

        /// Set to new pointer value, deleting any old object, and transfering ownership to the class.

00356         void operator=(T *other) {
            if(pointer)
                delete pointer;
            pointer = other;
        }

        /// Linear assignment: get the pointer from the other smart pointer,
        /// and set the other smart pointer to null.

00365         void operator=(autoref<T> &other) {
            if(pointer)
                delete pointer;
            pointer = other.move();
        }

        /// Take ownership away from this smart pointer and set the smart pointer to null.

00373         T *move() {
            T *result = pointer;
            pointer = 0;
            return result;
        }

        /// Deallocate the object.

00381         void dealloc() {
            if(pointer) {
                delete pointer;
                pointer = 0;
            }
        }
    };

    /// \brief A simple class for holding stdio streams.

00391     class stdio {
    private:
        FILE *stream;

    public:

        /// Default constructor sets stream to null.
    
00399         stdio() {
            stream = 0;
        }

        /// Constructor that calls fopen.  This constructor also recognizes
        /// "-" as a special file name to refer to stdin/stdout (depending on the mode).
    
00406         stdio(const char *file,const char *mode) {
            if(!strcmp(file,"-")) {
                if(mode[0]=='r') stream = stdin;
                else stream = stdout;
            } else {
                stream = fopen(file,mode);
                CHECK_ARG(stream);
            }
        }

        /// Destructor deletes any stream held by the class.

00418         ~stdio() {
            close();
        }

        /// Initialization with a stream transfers ownership to the class.
    
00424         explicit stdio(FILE *other) {
            if(!other) throw "stdio: attempt to set stream to null";
            stream = other;
        }

        /// Assignment of a stream deletes any old stream held by the class and
        /// transfers ownership of the stream to the class.

00432         void operator=(FILE *other) {
            if(!other) throw "stdio: attempt to set stream to null";
            close();
            stream = other;
        }

        /// Implicit conversion to stream, convenient for passing as an argument.

00440         operator FILE*() const {
            return stream;
        }

        /// Testing whether the stream is null.

00446         bool operator!() const {
            return !stream;
        }

        /// Linear assignment: get the stream from the other smart stream,
        /// and set the other smart stream to null.

00453         void operator=(stdio &other) {
            close();
            stream = other.move();
        }

        /// Take ownership away from this holder and return the stream.

00460         FILE *move() {
            FILE *result = stream;
            stream = 0;
            return result;
        }

        /// Close the stream if it's open.

00468         void close() {
            if(stream) {
                if(stream != stdout && stream != stdin)
                    fclose(stream);
                stream = 0;
            }
        }
    };

    // FIXME tmb: add reference counting class here --tmb
}

#endif

Generated by  Doxygen 1.6.0   Back to index