⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shared_handle.h

📁 linux pritner GUI
💻 H
字号:
/* Copyright (C) 2004 Chris VineThis program is distributed under the General Public Licence, version 2.For particulars of this and relevant disclaimers see the fileCOPYING distributed with the source files.*/#ifndef SHARED_HANDLE_H#define SHARED_HANDLE_H#include <cstdlib>#include <glibmm/thread.h>#include <glib/gmem.h>/*The Shared_handle class is similar to the Shared_ptr class (it keeps areference count and deletes the handled object when the count reaches0), but it does not have pointer semantics.  Accordingly, it can beused to manage the memory of arrays and other objects allocated on theheap.Because it is useful with arrays, by default it deallocates memoryusing C++ delete[].  However, if a Shared_handle object is passed afunction object type as a second template argument when instantiated,it will use that function object to delete memory.  This enables it tohandle the memory of any object, such as objects to be deleted usingstd::free() or Glib's g_free() and g_slist_free().  Note that thedeallocator must do nothing if the value of the pointer passed to itis NULL, so if it does not do this by default a NULL condition must betested for (std::free(), std::delete[] and Glib's g_free() do thistest themselves).To reflect the fact that it is just a handle for a pointer, it hasdifferent instantiation semantics from a Shared_ptr object.  AShared_ptr object is instantiated using this syntax:  Shared_ptr<Obj> sh_ptr(new Obj);A Shared_handle is instantiated using this syntax (note that theinstantiated handle is for type Obj* and not Obj):  Shared_handle<Obj*> sh_handle(new Obj[n]);The only method to obtain the underlying pointer is the get() method.Thus, if the object referenced is an array allocated on the heap, touse indexing you would do this:  Shared_handle<char*> handle(new char[10]);  handle.get()[0] = 'a';  std::cout << handle.get()[0] << std::endl;There is also a Scoped_handle class below, which deletes its object assoon as it goes out of scope.  It can be viewed as a Shared_handlewhich cannot be assigned to or used as the argument to a copyconstructor and therefore which cannot have a reference count of morethan 1. It is used where, if you wanted pointer semantics, you mightuse a const std::autoptr<>.*//********************* here are some deleter classes *******************/template <class T> class Standard_array_delete {public:  void operator()(T obj_p) {    delete[] obj_p;  }};class C_free {public:  void operator()(void* obj_p) {    std::free(obj_p);  }};class G_free {public:  void operator()(gpointer obj_p) {    g_free(obj_p);  }};/********************* define some typedefs for Glib ******************/template <class T, class Dealloc> class Shared_handle;template <class T, class Dealloc> class Scoped_handle;typedef Shared_handle<gchar*, G_free> Gchar_shared_handle;typedef Scoped_handle<gchar*, G_free> Gchar_scoped_handle;/******************* now the handle class definitions *****************/template <class T, class Dealloc = Standard_array_delete<T> > class Shared_handle {  Dealloc deleter;  struct {    unsigned int* ref_count_p;    void* obj_p;  } ref_items;  void unreference(void) {    --(*ref_items.ref_count_p);    if (*ref_items.ref_count_p == 0) {      deleter(static_cast<T>(ref_items.obj_p));      delete ref_items.ref_count_p;    }  }  void reference(void) {    ++(*ref_items.ref_count_p);  }public:  // constructor of first Shared_handle holding the referenced object  explicit Shared_handle(T ptr = 0) {    ref_items.ref_count_p = new unsigned int(1);    ref_items.obj_p = ptr;  }  // copy constructor  Shared_handle(const Shared_handle& sh_ptr) throw() {    ref_items = sh_ptr.ref_items;    reference();  }  // copy assignment  Shared_handle& operator=(const Shared_handle& sh_ptr) throw() {    // check whether we are already referencing this object -    // if so make this a null op.  This will also deal with    // self-assignment    if (ref_items.obj_p != sh_ptr.ref_items.obj_p) {      // first unreference any object referenced by this shared pointer      unreference();      // now inherit the ref_items structure from the assigning      // shared pointer and reference the object it references      ref_items = sh_ptr.ref_items;      reference();    }    return *this;  }  T get(void) const throw() {return static_cast<T>(ref_items.obj_p);}  unsigned int get_refcount(void) const throw() {return *ref_items.ref_count_p;}  // destructor  ~Shared_handle(void) throw() {unreference();}};template <class T, class Dealloc = Standard_array_delete<T> > class Scoped_handle {  Dealloc deleter;  void* obj_p;  // private copy constructor and assignment operator -  // scoped handle cannot be copied  Scoped_handle(const Scoped_handle&) throw();  void operator=(const Scoped_handle&) throw();public:  // constructor  explicit Scoped_handle(T ptr): obj_p(ptr) {;}  T get(void) const throw() {return static_cast<T>(obj_p);}  // destructor  ~Scoped_handle(void) throw() {deleter(static_cast<T>(obj_p));}};/*  Class Shared_lock_handle is a version of the shared handle class  which includes mutex locking so that it can be accessed in multiple  threads. Note that only the reference count is protected by a mutex,  so this is thread safe in the sense in which a raw pointer is thread  safe.  A shared handle accessed in one thread referencing a  particular object is thread safe as against another shared handle  accessing the same object in a different thread.  It is thus  suitable for use in different Std C++ containers which exist in  different threads but which contain shared objects by reference.  But:  1.  If the referenced object is to be modified in one thread and      read or modified in another thread an appropriate mutex for the      referenced object is required (unless that referenced object      does its own locking).  2.  If the same instance of shared handle is to be modified in one      thread (by assigning to the handle so that it references a      different object), and copied (assigned from or used as the      argument of a copy constructor) or modified in another thread, a      mutex for that instance of shared handle is required.  3.  Objects referenced by shared handles which are objects for      which POSIX provides no guarantees (in the main, those which are      not built-in types), such as strings and similar containers, may      not support concurrent reads in different threads.  That depends      on the library implementation concerned.  If that is the case, a      mutex for the referenced object will also be required when      reading any given instance of such an object in more than one      thread by dereferencing any shared handles referencing it (and      indeed, when not using shared handles at all).*/template <class T, class Dealloc = Standard_array_delete<T> > class Shared_lock_handle {  Dealloc deleter;  struct Ref_items {    Glib::Mutex* mutex_p;    unsigned int* ref_count_p;    void* obj_p;  } ref_items;  void unreference(void) {    ref_items.mutex_p->lock();    --(*ref_items.ref_count_p);    if (*ref_items.ref_count_p == 0) {      deleter(static_cast<T>(ref_items.obj_p));      delete ref_items.ref_count_p;      ref_items.mutex_p->unlock();      delete ref_items.mutex_p;    }    else ref_items.mutex_p->unlock();  }    void reference(void) {    Glib::Mutex::Lock lock(*ref_items.mutex_p);    ++(*ref_items.ref_count_p);  }public:  // constructor of first Shared_lock_handle holding the referenced object  explicit Shared_lock_handle(T ptr = 0) {    ref_items.mutex_p = new Glib::Mutex;    // make this constructor exception safe    try {      ref_items.ref_count_p = new unsigned int(1);    }    catch (...) {      delete ref_items.mutex_p;      throw;    }    ref_items.obj_p = ptr;  }  // copy constructor  Shared_lock_handle(const Shared_lock_handle& sh_ptr) throw() {    ref_items = sh_ptr.ref_items;    reference();  }  // copy assignment  Shared_lock_handle& operator=(const Shared_lock_handle& sh_ptr) throw() {    // check whether we are already referencing this object -    // if so make this a null op.  This will also deal with    // self-assignment    if (ref_items.obj_p != sh_ptr.ref_items.obj_p) {      // first unreference any object referenced by this shared handle      unreference();            // now inherit the ref_items structure from the assigning      // shared handle and reference the object it references      ref_items = sh_ptr.ref_items;      reference();    }    return *this;  }  T get(void) const throw() {return static_cast<T>(ref_items.obj_p);}  unsigned int get_refcount(void) const throw() {    Glib::Mutex::Lock lock(*ref_items.mutex_p);    return *ref_items.ref_count_p;  }  // destructor  ~Shared_lock_handle(void) throw() {unreference();}};#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -