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; |