diff options
| author | Pixel <pixel@nobis-crew.org> | 2009-11-13 16:28:15 -0800 | 
|---|---|---|
| committer | Pixel <pixel@nobis-crew.org> | 2009-11-13 16:28:15 -0800 | 
| commit | 8c415c3658e7f344dc803431726b50942e432702 (patch) | |
| tree | 5fda308ffe4420e6d1ebd9df67e7535b8069ee5e | |
| parent | c12806450806909177058eb8e7f85dcbd24cbf1c (diff) | |
BigClean: Input & Archive are a little bit more threadsafe now.
| -rw-r--r-- | include/Exceptions.h | 18 | ||||
| -rw-r--r-- | include/Input.h | 38 | ||||
| -rw-r--r-- | include/LockSmith.h | 45 | ||||
| -rw-r--r-- | include/generic.h | 8 | ||||
| -rw-r--r-- | lib/Handle.cc | 6 | ||||
| -rw-r--r-- | lib/Input.cc | 118 | ||||
| -rw-r--r-- | lib/generic.cc | 1 | 
7 files changed, 88 insertions, 146 deletions
diff --git a/include/Exceptions.h b/include/Exceptions.h index ac46e28..428e1be 100644 --- a/include/Exceptions.h +++ b/include/Exceptions.h @@ -176,24 +176,6 @@ class printer_t : public Base {  extern printer_t * printer; - -/*! -  The locker class, if it exists, will be used to produce interlocking -  inside the nested classes when needed. Define it if you're going to build -  a real threaded software with Baltisot. -*/ - -class locker_t : public Base { -  public: -    virtual void lock() = 0; -    virtual void unlock() = 0; -}; - -extern locker_t * locker; - -#define LOCK if (locker) locker->lock() -#define UNLOCK if (locker) locker->unlock(); -  #include <BString.h>  #endif diff --git a/include/Input.h b/include/Input.h index 208b185..66fa839 100644 --- a/include/Input.h +++ b/include/Input.h @@ -24,6 +24,8 @@  #include <time.h>  #include <BString.h>  #include <Handle.h> +#include <Atomic.h> +#include <LockSmith.h>  enum ArchiveType {      ARCHIVE_BUILTIN = 0, @@ -33,17 +35,17 @@ enum ArchiveType {  class Input : public Handle {    public:        Input(const String & = "") throw (GeneralException); -      Input(const Input &); -      virtual ~Input() { nb_input--; } -    virtual bool CanWrite() const; -    virtual bool CanRead() const; +      Input(const Input & i) : Handle(i), n(i.n), size(i.size), date_modif(i.date_modif) { Atomic::Increment(&nb_input); } +      virtual ~Input() { Atomic::Decrement(&nb_input); } +    virtual bool CanWrite() const { return false; } +    virtual bool CanRead() const { return true; }      virtual bool CanSeek() const;      virtual off_t seek(off_t, int = SEEK_SET) throw (GeneralException); -    virtual String GetName() const; -    virtual ssize_t GetSize() const; -    virtual time_t GetModif() const; +    virtual String GetName() const { return n; } +    virtual ssize_t GetSize() const { return size; } +    virtual time_t GetModif() const { return date_modif; }      virtual void SetZ(int = 9) throw (GeneralException); -    static int GetNbInput(); +    static int GetNbInput() { return nb_input; }      struct openresults_t {  	String name; @@ -66,10 +68,10 @@ class Input : public Handle {  class Stdin_t : public Input {    public: -      Stdin_t(); +      Stdin_t() {}        virtual ~Stdin_t() {} -    virtual bool CanSeek() const; -    virtual String GetName() const; +    virtual bool CanSeek() const { return false; } +    virtual String GetName() const { return "Stdin"; }  };  extern Stdin_t Stdin; @@ -78,10 +80,10 @@ class Archive : public Base {    public:        Archive(const String &, int = ARCHIVE_BUILTIN);        Archive(Handle *, int = ARCHIVE_BUILTIN); -      virtual ~Archive(); +      virtual ~Archive() throw(GeneralException) { throw GeneralException("Archives ain't meant to be deleted."); }    protected:      static Archive * inarchive(const String &); -    Handle * GetHandle(); +    Handle * GetHandle() { return archive; }      int open(const String &, Input::openresults_t *);    private:      void create() throw (GeneralException); @@ -90,12 +92,11 @@ class Archive : public Base {      class FileTree : public Base {        public:            FileTree(const String & = "", size_t = 0, int = 0, FileTree * = 0); -	  virtual ~FileTree();  	int compute_ptrs(size_t = 0); -	FileTree * Father(); -	FileTree * Child(); -	FileTree * Next(); -	FileTree * Prev(); +	FileTree * Father() { return father; } +	FileTree * Child() { return child; } +	FileTree * Next() { return next; } +	FileTree * Prev() { return prev; }      	String name;      	int type;  	size_t size; @@ -109,6 +110,7 @@ class Archive : public Base {      int type;      Archive * next, * prev;      static Archive * header; +    static iLock lock;      friend class Input;  }; diff --git a/include/LockSmith.h b/include/LockSmith.h new file mode 100644 index 0000000..fe2dc02 --- /dev/null +++ b/include/LockSmith.h @@ -0,0 +1,45 @@ +#ifndef __LOCKSMITH_H__ +#define __LOCKSMITH_H__ + +#include <Exceptions.h> +#include <Atomic.h> + +/*! +  The locker class, if it exists, will be used to produce interlocking +  inside the nested classes when needed. Define it if you're going to build +  a real threaded software with Baltisot. +*/ + +class locker_t : public Base { +  public: +    virtual void lock() {} +    virtual void unlock() {} +}; + +class LockSmith : public Base { +  public: +      LockSmith() { GlobalLockSmith = this; } +    static locker_t * SpawnLock() { return GlobalLockSmith->SpawnSpecificLock(); } +  protected: +    virtual locker_t * SpawnSpecificLock() { return new locker_t(); } +    static LockSmith * GlobalLockSmith; +}; + +class iLock : public Base { +  public: +      iLock() { } +      ~iLock() { if (locker) delete(locker); } +    void lock() { +        if (LIKELY(locker)) { +            locker->lock(); +        } else { +            locker = LockSmith::SpawnLock(); +            locker->lock(); +        } +    } +    void unlock() { locker->unlock(); } +  private: +    locker_t * locker; +}; + +#endif diff --git a/include/generic.h b/include/generic.h index 44aa291..ace03e8 100644 --- a/include/generic.h +++ b/include/generic.h @@ -26,6 +26,14 @@  #pragma warning(disable:4996 4244 4267)  #endif +#ifdef __GNUC__ +#define LIKELY(x) __builtin_expect(!!(x), 1) +#define UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define LIKELY(x) (x) +#define UNLIKELY(x) (x) +#endif +  #include <sys/types.h>  #include <sys/stat.h>  #include <string.h> diff --git a/lib/Handle.cc b/lib/Handle.cc index c0b3d94..efe2e15 100644 --- a/lib/Handle.cc +++ b/lib/Handle.cc @@ -617,14 +617,12 @@ void copyone(Handle * s, Handle * d, ssize_t size) {  #define BSIZE 20480  void copy(Handle * s, Handle * d, ssize_t size) { -    static unsigned char b[BSIZE]; +    unsigned char b[BSIZE];      long r;      if (size < 0)  	size = s->GetSize(); -    LOCK; -          while (size) {          if ((size > BSIZE) || (size < 0)) {      	    r = s->read(b, BSIZE); @@ -640,8 +638,6 @@ void copy(Handle * s, Handle * d, ssize_t size) {          if (size > 0)  	    size -= r;      } -     -    UNLOCK;  }  void Handle::Flush() { diff --git a/lib/Input.cc b/lib/Input.cc index 46f507b..4c2f419 100644 --- a/lib/Input.cc +++ b/lib/Input.cc @@ -37,6 +37,7 @@  #include "Input.h"  #include "Exceptions.h"  #include "gettext.h" +#include "Atomic.h"  #ifndef S_ISREG  #define S_ISREG(x) 1 @@ -86,10 +87,6 @@ static Input::openresults_t gresults;  int Input::nb_input = 0; -int Input::GetNbInput() { -    return nb_input; -} -  Input::Input(const String & no) throw (GeneralException) :      Handle(no.strlen() ? wrapopen(no, &gresults) : dup(0)),      n(no) { @@ -105,12 +102,10 @@ Input::Input(const String & no) throw (GeneralException) :  	throw IOGeneral(String(_("Error opening file ")) + no + _(" for reading: ") + strerror(errno));      } -    nb_input++; +    Atomic::Increment(&nb_input);      results = gresults; -    UNLOCK -          fromarchive = false;      if (results.name == "") {  #ifndef __MIPSEL__ @@ -145,18 +140,6 @@ Input::Input(const String & no) throw (GeneralException) :      }  } -Input::Input(const Input & i) : Handle(i), n(i.n), size(i.size), date_modif(i.date_modif) { -    nb_input++; -} - -bool Input::CanWrite() const { -    return 0; -} - -bool Input::CanRead() const { -    return 1; -} -  bool Input::CanSeek() const {  #ifdef __MIPSEL__      return true; @@ -169,18 +152,6 @@ bool Input::CanSeek() const {  #endif  } -String Input::GetName() const { -    return n; -} - -ssize_t Input::GetSize() const { -    return size; -} - -time_t Input::GetModif() const { -    return date_modif; -} -  off_t Input::seek(off_t offset, int whence) throw (GeneralException) {      if (!fromarchive) {  	if ((itell = lseek(GetHandle(), offset, whence)) < 0) { @@ -198,7 +169,6 @@ off_t Input::seek(off_t offset, int whence) throw (GeneralException) {  }  int Input::wrapopen(const String & fname, openresults_t * results) { -    LOCK;  #ifdef DEBUG      printm(M_INFO, _("Wrap-opening ") + fname + "\n");  #endif @@ -238,21 +208,12 @@ void Input::SetZ(int l) throw(GeneralException) {  	Handle::SetZ(l);  } -Stdin_t::Stdin_t() { } - -bool Stdin_t::CanSeek() const { -    return 0; -} - -String Stdin_t::GetName() const { -    return "Stdin"; -} -  #ifdef HOOK_STDS  Stdin_t Stdin;  #endif  Archive * Archive::header = 0; +iLock Archive::lock;  Archive::Archive(const String & fname, int atype) :    name(fname), archive(new Input(fname)), type(atype) { @@ -366,6 +327,8 @@ void Archive::create() throw (GeneralException) {  	archive->read(buffer, 4);  	if (*((Uint32 *)buffer) != BUILTIN_SIG)  	    throw GeneralException(_("Archive: not in built-in format.")); +	     +        lock.lock();  	while (p) {  	    archive->read(buffer, 1);  	    len = *buffer; @@ -386,27 +349,15 @@ void Archive::create() throw (GeneralException) {  	    }  	}  	filetree.compute_ptrs(archive->tell()); +        lock.unlock();  	break;      default:  	throw GeneralException(_("Archive: unsupported archive format."));      } - -    next = header; -    prev = 0; -    header = this; -    if (next) -	next->prev = this; -} - -Archive::~Archive() { -    if (prev) -	prev->next = next; -    if (next) -	next->prev = prev; -    if (header == this) -	header = next; - -    delete archive; +     +    do { +        next = header; +    } while (!Atomic::CmpXChgBool(&header, this, next));  }  Archive * Archive::inarchive(const String & fname) { @@ -426,25 +377,11 @@ Archive * Archive::inarchive(const String & fname) {  }  int Archive::open(const String & fname, Input::openresults_t * results) { -#if 0 -    Archive * p; - -    for (p = header; p; p = p->next) { -	bool t; -	t = p->inarchive(fname); -	if (t) -	    return p->openin(fname, results); -    } -    throw IOGeneral(_("File `") + fname + _("' not found in archive collection.")); -#endif      return openin(fname, results);  } -Handle * Archive::GetHandle() { -    return archive; -} -  bool Archive::inarchivein(const String & fname) { +    lock.lock();      Archive::FileTree * p = filetree.Child();      ssize_t pos;      String name = fname; @@ -472,11 +409,13 @@ bool Archive::inarchivein(const String & fname) {  	    }  	}      } +    lock.unlock();      return p != 0;  }  int Archive::openin(const String & fname, Input::openresults_t * results) throw (GeneralException) { +    lock.lock();      Archive::FileTree * p = filetree.Child();      ssize_t pos;      String name = fname; @@ -502,6 +441,7 @@ int Archive::openin(const String & fname, Input::openresults_t * results) throw  	    }  	}      } +    lock.unlock();      if (!p)  	throw IOGeneral(_("File `") + fname + _("' not in archive ") + this->name); @@ -533,20 +473,6 @@ Archive::FileTree::FileTree(const String & fname, size_t fsize, int ftype, Archi      }  } -Archive::FileTree::~FileTree() { -    if (child) -	delete child; -    if (next) -	next->prev = prev; -    if (prev) -	prev->next = next; -    if (father) { -	if (father->child == this) -	    father->child = next; -	father->touched(); -    } -} -  void Archive::FileTree::touched() {      if (father)  	father->touched(); @@ -575,19 +501,3 @@ int Archive::FileTree::compute_ptrs(size_t cptr) {      return size + ptr;  } - -Archive::FileTree * Archive::FileTree::Father() { -    return father; -} - -Archive::FileTree * Archive::FileTree::Child() { -    return child; -} - -Archive::FileTree * Archive::FileTree::Next() { -    return next; -} - -Archive::FileTree * Archive::FileTree::Prev() { -    return prev; -} diff --git a/lib/generic.cc b/lib/generic.cc index 8c2a66f..f329186 100644 --- a/lib/generic.cc +++ b/lib/generic.cc @@ -30,7 +30,6 @@  char verbosity = M_ERROR;  static const char * heads[] = {NULL, "EE", "--", "WW", "II"};  printer_t * printer = 0; -locker_t * locker = 0;  void Base::printm(int level, const ugly_string & m, ...) {      va_list ap;  | 
