Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F126481
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
16 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/file-system.h b/util/file-system.h
index d8cc412e..9d911c9d 100644
--- a/util/file-system.h
+++ b/util/file-system.h
@@ -1,248 +1,257 @@
#ifndef _paintown_file_system_h
#define _paintown_file_system_h
#include "exceptions/exception.h"
#include <string>
#include <vector>
#include <stdint.h>
namespace Filesystem{
/* sorry for the crappy abbreviation, but can't collide with the
* Exception class here
*/
namespace Exc = ::Exception;
class Exception: public Exc::Base {
public:
Exception(const std::string & where, int line, const std::string & file);
Exception(const std::string & where, int line, const Exc::Base & nested, const std::string & file);
Exception(const Exception & copy);
virtual ~Exception() throw ();
+ virtual void throwSelf() const {
+ throw *this;
+ }
protected:
virtual const std::string getReason() const;
virtual Exc::Base * copy() const {
return new Exception(*this);
}
private:
std::string reason;
};
class NotFound: public Exception {
public:
NotFound(const std::string & where, int line, const std::string & file);
NotFound(const std::string & where, int line, const Exc::Base & nested, const std::string & file);
virtual ~NotFound() throw();
NotFound(const NotFound & copy);
+ virtual void throwSelf() const {
+ throw *this;
+ }
protected:
virtual Exc::Base * copy() const {
return new NotFound(*this);
}
};
class IllegalPath: public Exception {
public:
IllegalPath(const std::string & where, int line, const std::string & file);
IllegalPath(const std::string & where, int line, const Exc::Base & nested, const std::string & file);
virtual ~IllegalPath() throw();
IllegalPath(const IllegalPath & copy);
+ virtual void throwSelf() const {
+ throw *this;
+ }
protected:
virtual Exc::Base * copy() const {
return new IllegalPath(*this);
}
};
class Path{
public:
const std::string & path() const;
bool isEmpty() const;
virtual ~Path();
protected:
Path();
Path(const std::string & path);
Path(const Path & path);
virtual inline void setPath(const std::string & s){
mypath = s;
}
std::string mypath;
};
class InsensitivePath: public Path {
public:
InsensitivePath(const Path & what);
bool operator==(const Path & path) const;
};
/* relative path should not have the leading data directory on it, just
* the path within the paintown system.
*/
class RelativePath: public Path {
public:
explicit RelativePath();
explicit RelativePath(const std::string & path);
RelativePath(const RelativePath & path);
bool operator<(const RelativePath & path) const;
virtual RelativePath getDirectory() const;
virtual RelativePath getFilename() const;
RelativePath removeFirstDirectory() const;
/* a/ + b/ = a/b/ */
RelativePath join(const RelativePath & path) const;
RelativePath & operator=(const RelativePath & copy);
bool operator==(const RelativePath & path) const;
};
/* absolute paths should have the entire filesystem path on it */
class AbsolutePath: public Path {
public:
explicit AbsolutePath();
explicit AbsolutePath(const std::string & path);
AbsolutePath(const AbsolutePath & path);
AbsolutePath & operator=(const AbsolutePath & copy);
bool operator<(const AbsolutePath & path) const;
bool operator==(const AbsolutePath & path) const;
virtual AbsolutePath getDirectory() const;
virtual AbsolutePath getFilename() const;
AbsolutePath join(const RelativePath & path) const;
};
/* given a relative path like sounds/arrow.png, prepend the proper
* data path to it to give data/sounds/arrow.png
*/
AbsolutePath find(const RelativePath & path);
/* like `find' but ignores case */
AbsolutePath findInsensitive(const RelativePath & path);
/* findInsensitive but starts in the given absolute directory path */
AbsolutePath lookupInsensitive(const AbsolutePath & directory, const RelativePath path);
/* whether the file exists at all */
bool exists(const RelativePath & path);
bool exists(const AbsolutePath & path);
/* remove the data path from a string
* data/sounds/arrow.png -> sounds/arrow.png
*/
RelativePath cleanse(const AbsolutePath & path);
/* returns all the directories starting with the given path.
* will look in the main data directory, the user directory, and
* the current working directory.
*/
std::vector<AbsolutePath> findDirectories(const RelativePath & path);
/* basename, just get the filename and remove the directory part */
std::string stripDir(const std::string & str);
/* remove extension. foo.txt -> foo */
std::string removeExtension(const std::string & str);
/* user specific directory to hold persistent data */
AbsolutePath userDirectory();
/* user specific path to store the configuration file */
AbsolutePath configFile();
/* search a directory for some files matching pattern `find' */
std::vector<AbsolutePath> getFiles(const AbsolutePath & dataPath, const std::string & find, bool caseInsensitive = false);
/* same as getFiles but search directories recursively */
std::vector<AbsolutePath> getFilesRecursive(const AbsolutePath & dataPath, const std::string & find, bool caseInsensitive = false);
std::string invertSlashes(const std::string & str);
std::string sanitize(std::string path);
class Eof: public std::exception {
public:
Eof(){
}
virtual ~Eof() throw (){
}
};
class EndianReader{
public:
EndianReader(std::ifstream & stream):
stream(stream){
}
virtual ~EndianReader(){
}
virtual int8_t readByte1(){
return convert(readBytes(sizeof(int8_t)));
}
virtual int16_t readByte2(){
return convert(readBytes(sizeof(int16_t)));
}
virtual int32_t readByte4(){
return convert(readBytes(sizeof(int32_t)));
}
virtual std::string readStringX(int length);
virtual std::string readString2(int length);
virtual void seekEnd(std::streamoff where);
virtual void seek(std::streampos where);
virtual int position();
protected:
virtual int32_t convert(const std::vector<uint8_t> & bytes) = 0;
std::vector<uint8_t> readBytes(int length);
std::ifstream & stream;
};
/* combines bytes b0 b1 b2 b3 as b0 + b1*2^8 + b2*2^16 + b3*2^24 */
class LittleEndianReader: public EndianReader {
public:
LittleEndianReader(std::ifstream & stream):
EndianReader(stream){
}
protected:
virtual int32_t convert(const std::vector<uint8_t> & bytes){
uint32_t out = 0;
for (std::vector<uint8_t>::const_reverse_iterator it = bytes.rbegin(); it != bytes.rend(); it++){
out = (out << 8) + *it;
}
return out;
}
};
/* combines bytes b0 b1 b2 b3 as b0*2^24 + b1*2^16 + b2*2^8 + b3 */
class BigEndianReader: public EndianReader {
public:
BigEndianReader(std::ifstream & stream):
EndianReader(stream){
}
protected:
virtual int32_t convert(const std::vector<uint8_t> & bytes){
uint32_t out = 0;
for (std::vector<uint8_t>::const_iterator it = bytes.begin(); it != bytes.end(); it++){
out = (out << 8) + *it;
}
return out;
}
};
}
#endif
diff --git a/util/load_exception.h b/util/load_exception.h
index 4bef6924..43a5a760 100644
--- a/util/load_exception.h
+++ b/util/load_exception.h
@@ -1,29 +1,33 @@
#ifndef _load_exception_h
#define _load_exception_h
#include "exceptions/exception.h"
/* Generic load exception class. Thrown whenever a structure is being created
* and an error occurs.
*/
#include <string>
/* FIXME: put this in the Exception namespace */
class LoadException: public Exception::Base {
public:
LoadException(const std::string & file, int line, const std::string & reason);
LoadException(const std::string & file, int line, const Exception::Base & nested, const std::string & reason);
LoadException(const LoadException & copy);
virtual ~LoadException() throw();
+ virtual void throwSelf() const {
+ throw *this;
+ }
+
protected:
virtual const std::string getReason() const;
virtual Exception::Base * copy() const;
std::string reason;
};
#endif
diff --git a/util/thread.h b/util/thread.h
index 0f8e834a..fb710a37 100644
--- a/util/thread.h
+++ b/util/thread.h
@@ -1,196 +1,189 @@
#ifndef _paintown_thread_h
#define _paintown_thread_h
#ifdef USE_SDL
#include <SDL_thread.h>
#include <SDL_mutex.h>
#else
#include <pthread.h>
#include <semaphore.h>
#endif
#include "exceptions/exception.h"
#include "util/load_exception.h"
#include "util/token_exception.h"
#include "mugen/exception.h"
#include "debug.h"
namespace Util{
/* Either uses pthreads or SDL_thread */
namespace Thread{
#ifdef USE_SDL
typedef SDL_mutex* Lock;
typedef SDL_Thread* Id;
typedef int (*ThreadFunction)(void*);
typedef SDL_semaphore* Semaphore;
#else
typedef pthread_mutex_t Lock;
typedef pthread_t Id;
typedef sem_t Semaphore;
typedef void * (*ThreadFunction)(void*);
#endif
extern Id uninitializedValue;
bool isUninitialized(Id thread);
void initializeLock(Lock * lock);
void initializeSemaphore(Semaphore * semaphore, unsigned int value);
void destroySemaphore(Semaphore * semaphore);
void semaphoreDecrease(Semaphore * semaphore);
void semaphoreIncrease(Semaphore * semaphore);
int acquireLock(Lock * lock);
int releaseLock(Lock * lock);
void destroyLock(Lock * lock);
bool createThread(Id * thread, void * attributes, ThreadFunction function, void * arg);
void joinThread(Id thread);
void cancelThread(Id thread);
}
class WaitThread{
public:
/* does not start a new thread yet */
WaitThread();
/* starts a thread */
WaitThread(Thread::ThreadFunction thread, void * arg);
/* starts a thread */
void start(Thread::ThreadFunction thread, void * arg);
bool isRunning();
void kill();
virtual ~WaitThread();
public:
/* actually runs the thread */
void doRun();
protected:
Thread::Lock doneLock;
Thread::Id thread;
volatile bool done;
void * arg;
Thread::ThreadFunction function;
};
/* wraps a boolean with lock/unlock while checking/setting it */
class ThreadBoolean{
public:
ThreadBoolean(volatile bool & what, Thread::Lock & lock);
bool get();
void set(bool value);
protected:
volatile bool & what;
Thread::Lock & lock;
};
/* Computes stuff in a separate thread and gives it back when you ask for it.
* As soon as the future is created a thread will start executing and compute
* whatever it is that the class is supposed to do. You can then call `get'
* on the future object to get the result. If the thread is still executing
* then `get' will block until the future completes. If the future has already
* completed then `get' will return immediately with the computed value.
* The use case is computing something that has to be used later:
* Future future; // might take a while to compute
* do_stuff_that_takes_a_while(); // future might finish sometime in here
* Object o = future.get(); // future is already done
*
* TODO: handle exceptions
*/
template<class X>
class Future{
protected:
/* WARNING: hack to find out the type of the exception */
+ /*
enum ExceptionType{
None,
Load,
Token,
Base,
Mugen
};
+ */
public:
Future():
thing(0),
thread(Thread::uninitializedValue),
- exception(__FILE__, __LINE__),
- haveException(None){
+ exception(NULL){
/* future will increase the count */
Thread::initializeSemaphore(&future, 0);
}
virtual ~Future(){
if (Thread::isUninitialized(thread)){
Thread::joinThread(thread);
}
Thread::destroySemaphore(&future);
+ delete exception;
}
virtual X get(){
X out;
Thread::semaphoreDecrease(&future);
- switch (haveException){
- case None : break;
- case Load : throw LoadException(__FILE__, __LINE__, exception, "Failed in future");
- case Mugen : throw MugenException(exception.getTrace());
- case Token: throw TokenException(exception);
- default : throw Exception::Base(__FILE__, __LINE__, exception);
+ if (exception != NULL){
+ exception->throwSelf();
}
out = thing;
Thread::semaphoreIncrease(&future);
return out;
}
virtual void start(){
if (!Thread::createThread(&thread, NULL, (Thread::ThreadFunction) runit, this)){
Global::debug(0) << "Could not create future thread. Blocking until its done" << std::endl;
runit(this);
// throw Exception::Base(__FILE__, __LINE__);
}
}
protected:
static void * runit(void * arg){
Future<X> * me = (Future<X>*) arg;
try{
me->compute();
} catch (const LoadException & load){
- me->haveException = Load;
- me->exception.set(load);
+ me->exception = new LoadException(load);
} catch (const TokenException & t){
- me->haveException = Token;
- me->exception.set(t);
+ me->exception = new TokenException(t);
} catch (const MugenException & m){
- me->haveException = Mugen;
- me->exception.set(m);
+ me->exception = new MugenException(m);
} catch (const Exception::Base & base){
- me->haveException = Base;
- me->exception.set(base);
+ me->exception = new Exception::Base(base);
}
Thread::semaphoreIncrease(&me->future);
return NULL;
}
virtual void set(X x){
this->thing = x;
}
virtual void compute() = 0;
X thing;
Thread::Id thread;
Thread::Semaphore future;
/* if any exceptions occur, throw them from `get' */
- Exception::Base exception;
- ExceptionType haveException;
+ Exception::Base * exception;
};
}
#endif
diff --git a/util/token_exception.h b/util/token_exception.h
index 7ea66682..0673ef64 100644
--- a/util/token_exception.h
+++ b/util/token_exception.h
@@ -1,25 +1,29 @@
#ifndef _paintown_token_exception_h
#define _paintown_token_exception_h
#include "exceptions/exception.h"
#include <string>
class TokenException: public Exception::Base {
public:
TokenException(const std::string & file, int line, const std::string reason = "");
TokenException(const TokenException & copy);
TokenException(const Exception::Base & base);
virtual ~TokenException() throw();
+ virtual void throwSelf() const {
+ throw *this;
+ }
+
protected:
virtual Exception::Base * copy() const;
virtual inline const std::string getReason() const {
return reason;
}
std::string reason;
};
#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jun 11, 11:44 AM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68849
Default Alt Text
(16 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline