summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2009-11-13 16:28:15 -0800
committerPixel <pixel@nobis-crew.org>2009-11-13 16:28:15 -0800
commit8c415c3658e7f344dc803431726b50942e432702 (patch)
tree5fda308ffe4420e6d1ebd9df67e7535b8069ee5e
parentc12806450806909177058eb8e7f85dcbd24cbf1c (diff)
BigClean: Input & Archive are a little bit more threadsafe now.
-rw-r--r--include/Exceptions.h18
-rw-r--r--include/Input.h38
-rw-r--r--include/LockSmith.h45
-rw-r--r--include/generic.h8
-rw-r--r--lib/Handle.cc6
-rw-r--r--lib/Input.cc118
-rw-r--r--lib/generic.cc1
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;